mirror of
				https://github.com/matrix-org/synapse.git
				synced 2025-10-31 00:01:33 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/develop' into dbkr/http_request_propagate_error
This commit is contained in:
		
						commit
						2e165295b7
					
				| @ -373,7 +373,7 @@ FreeBSD | ||||
| 
 | ||||
| Synapse can be installed via FreeBSD Ports or Packages contributed by Brendan Molloy from: | ||||
| 
 | ||||
|  - Ports: ``cd /usr/ports/net/py-matrix-synapse && make install clean`` | ||||
|  - Ports: ``cd /usr/ports/net-im/py-matrix-synapse && make install clean`` | ||||
|  - Packages: ``pkg install py27-matrix-synapse`` | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										64
									
								
								synapse/handlers/read_marker.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								synapse/handlers/read_marker.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright 2017 Vector Creations Ltd | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| 
 | ||||
| from ._base import BaseHandler | ||||
| 
 | ||||
| from twisted.internet import defer | ||||
| 
 | ||||
| from synapse.util.async import Linearizer | ||||
| 
 | ||||
| import logging | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| class ReadMarkerHandler(BaseHandler): | ||||
|     def __init__(self, hs): | ||||
|         super(ReadMarkerHandler, self).__init__(hs) | ||||
|         self.server_name = hs.config.server_name | ||||
|         self.store = hs.get_datastore() | ||||
|         self.read_marker_linearizer = Linearizer(name="read_marker") | ||||
|         self.notifier = hs.get_notifier() | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|     def received_client_read_marker(self, room_id, user_id, event_id): | ||||
|         """Updates the read marker for a given user in a given room if the event ID given | ||||
|         is ahead in the stream relative to the current read marker. | ||||
| 
 | ||||
|         This uses a notifier to indicate that account data should be sent down /sync if | ||||
|         the read marker has changed. | ||||
|         """ | ||||
| 
 | ||||
|         with (yield self.read_marker_linearizer.queue((room_id, user_id))): | ||||
|             account_data = yield self.store.get_account_data_for_room(user_id, room_id) | ||||
| 
 | ||||
|             existing_read_marker = account_data.get("m.fully_read", None) | ||||
| 
 | ||||
|             should_update = True | ||||
| 
 | ||||
|             if existing_read_marker: | ||||
|                 # Only update if the new marker is ahead in the stream | ||||
|                 should_update = yield self.store.is_event_after( | ||||
|                     event_id, | ||||
|                     existing_read_marker['event_id'] | ||||
|                 ) | ||||
| 
 | ||||
|             if should_update: | ||||
|                 content = { | ||||
|                     "event_id": event_id | ||||
|                 } | ||||
|                 max_id = yield self.store.add_account_data_to_room( | ||||
|                     user_id, room_id, "m.fully_read", content | ||||
|                 ) | ||||
|                 self.notifier.on_new_event("account_data_key", max_id, users=[user_id]) | ||||
| @ -40,6 +40,7 @@ from synapse.rest.client.v2_alpha import ( | ||||
|     register, | ||||
|     auth, | ||||
|     receipts, | ||||
|     read_marker, | ||||
|     keys, | ||||
|     tokenrefresh, | ||||
|     tags, | ||||
| @ -88,6 +89,7 @@ class ClientRestResource(JsonResource): | ||||
|         register.register_servlets(hs, client_resource) | ||||
|         auth.register_servlets(hs, client_resource) | ||||
|         receipts.register_servlets(hs, client_resource) | ||||
|         read_marker.register_servlets(hs, client_resource) | ||||
|         keys.register_servlets(hs, client_resource) | ||||
|         tokenrefresh.register_servlets(hs, client_resource) | ||||
|         tags.register_servlets(hs, client_resource) | ||||
|  | ||||
| @ -16,7 +16,7 @@ | ||||
| from ._base import client_v2_patterns | ||||
| 
 | ||||
| from synapse.http.servlet import RestServlet, parse_json_object_from_request | ||||
| from synapse.api.errors import AuthError | ||||
| from synapse.api.errors import AuthError, SynapseError | ||||
| 
 | ||||
| from twisted.internet import defer | ||||
| 
 | ||||
| @ -82,6 +82,13 @@ class RoomAccountDataServlet(RestServlet): | ||||
| 
 | ||||
|         body = parse_json_object_from_request(request) | ||||
| 
 | ||||
|         if account_data_type == "m.fully_read": | ||||
|             raise SynapseError( | ||||
|                 405, | ||||
|                 "Cannot set m.fully_read through this API." | ||||
|                 " Use /rooms/!roomId:server.name/read_markers" | ||||
|             ) | ||||
| 
 | ||||
|         max_id = yield self.store.add_account_data_to_room( | ||||
|             user_id, room_id, account_data_type, body | ||||
|         ) | ||||
|  | ||||
							
								
								
									
										66
									
								
								synapse/rest/client/v2_alpha/read_marker.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								synapse/rest/client/v2_alpha/read_marker.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright 2017 Vector Creations Ltd | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| 
 | ||||
| from twisted.internet import defer | ||||
| 
 | ||||
| from synapse.http.servlet import RestServlet, parse_json_object_from_request | ||||
| from ._base import client_v2_patterns | ||||
| 
 | ||||
| import logging | ||||
| 
 | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| class ReadMarkerRestServlet(RestServlet): | ||||
|     PATTERNS = client_v2_patterns("/rooms/(?P<room_id>[^/]*)/read_markers$") | ||||
| 
 | ||||
|     def __init__(self, hs): | ||||
|         super(ReadMarkerRestServlet, self).__init__() | ||||
|         self.auth = hs.get_auth() | ||||
|         self.receipts_handler = hs.get_receipts_handler() | ||||
|         self.read_marker_handler = hs.get_read_marker_handler() | ||||
|         self.presence_handler = hs.get_presence_handler() | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|     def on_POST(self, request, room_id): | ||||
|         requester = yield self.auth.get_user_by_req(request) | ||||
| 
 | ||||
|         yield self.presence_handler.bump_presence_active_time(requester.user) | ||||
| 
 | ||||
|         body = parse_json_object_from_request(request) | ||||
| 
 | ||||
|         read_event_id = body.get("m.read", None) | ||||
|         if read_event_id: | ||||
|             yield self.receipts_handler.received_client_receipt( | ||||
|                 room_id, | ||||
|                 "m.read", | ||||
|                 user_id=requester.user.to_string(), | ||||
|                 event_id=read_event_id | ||||
|             ) | ||||
| 
 | ||||
|         read_marker_event_id = body.get("m.fully_read", None) | ||||
|         if read_marker_event_id: | ||||
|             yield self.read_marker_handler.received_client_read_marker( | ||||
|                 room_id, | ||||
|                 user_id=requester.user.to_string(), | ||||
|                 event_id=read_marker_event_id | ||||
|             ) | ||||
| 
 | ||||
|         defer.returnValue((200, {})) | ||||
| 
 | ||||
| 
 | ||||
| def register_servlets(hs, http_server): | ||||
|     ReadMarkerRestServlet(hs).register(http_server) | ||||
| @ -48,6 +48,7 @@ from synapse.handlers.typing import TypingHandler | ||||
| from synapse.handlers.events import EventHandler, EventStreamHandler | ||||
| from synapse.handlers.initial_sync import InitialSyncHandler | ||||
| from synapse.handlers.receipts import ReceiptsHandler | ||||
| from synapse.handlers.read_marker import ReadMarkerHandler | ||||
| from synapse.http.client import ( | ||||
|     SimpleHttpClient, InsecureInterceptableContextFactory, MatrixProxyClient | ||||
| ) | ||||
| @ -136,6 +137,7 @@ class HomeServer(object): | ||||
|         'receipts_handler', | ||||
|         'macaroon_generator', | ||||
|         'tcp_replication', | ||||
|         'read_marker_handler', | ||||
|     ] | ||||
| 
 | ||||
|     def __init__(self, hostname, **kwargs): | ||||
| @ -297,6 +299,9 @@ class HomeServer(object): | ||||
|     def build_receipts_handler(self): | ||||
|         return ReceiptsHandler(self) | ||||
| 
 | ||||
|     def build_read_marker_handler(self): | ||||
|         return ReadMarkerHandler(self) | ||||
| 
 | ||||
|     def build_tcp_replication(self): | ||||
|         raise NotImplementedError() | ||||
| 
 | ||||
|  | ||||
| @ -2159,6 +2159,28 @@ class EventsStore(SQLBaseStore): | ||||
|             ] | ||||
|         ) | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|     def is_event_after(self, event_id1, event_id2): | ||||
|         """Returns True if event_id1 is after event_id2 in the stream | ||||
|         """ | ||||
|         to_1, so_1 = yield self._get_event_ordering(event_id1) | ||||
|         to_2, so_2 = yield self._get_event_ordering(event_id2) | ||||
|         defer.returnValue((to_1, so_1) > (to_2, so_2)) | ||||
| 
 | ||||
|     @defer.inlineCallbacks | ||||
|     def _get_event_ordering(self, event_id): | ||||
|         res = yield self._simple_select_one( | ||||
|             table="events", | ||||
|             retcols=["topological_ordering", "stream_ordering"], | ||||
|             keyvalues={"event_id": event_id}, | ||||
|             allow_none=True | ||||
|         ) | ||||
| 
 | ||||
|         if not res: | ||||
|             raise SynapseError(404, "Could not find event %s" % (event_id,)) | ||||
| 
 | ||||
|         defer.returnValue((int(res["topological_ordering"]), int(res["stream_ordering"]))) | ||||
| 
 | ||||
| 
 | ||||
| AllNewEventsResult = namedtuple("AllNewEventsResult", [ | ||||
|     "new_forward_events", "new_backfill_events", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user