From 5f19c55731deef0381338fcab9847f5c762a36c8 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 20 Nov 2014 19:33:45 +0000 Subject: SYN-58: Allow passing explicit limit=0 to initialSync to request no messages at all; missing still implies default 10 --- synapse/handlers/message.py | 2 +- synapse/streams/config.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'synapse') diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index 06a4e173f6..ae0fc43ca2 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -243,7 +243,7 @@ class MessageHandler(BaseHandler): public_room_ids = [r["room_id"] for r in public_rooms] limit = pagin_config.limit - if not limit: + if limit is None: limit = 10 for event in room_list: diff --git a/synapse/streams/config.py b/synapse/streams/config.py index 527507e5cd..0317e78c08 100644 --- a/synapse/streams/config.py +++ b/synapse/streams/config.py @@ -28,11 +28,11 @@ class SourcePaginationConfig(object): specific event source.""" def __init__(self, from_key=None, to_key=None, direction='f', - limit=0): + limit=None): self.from_key = from_key self.to_key = to_key self.direction = 'f' if direction == 'f' else 'b' - self.limit = int(limit) + self.limit = int(limit) if limit is not None else None class PaginationConfig(object): @@ -40,11 +40,11 @@ class PaginationConfig(object): """A configuration object which stores pagination parameters.""" def __init__(self, from_token=None, to_token=None, direction='f', - limit=0): + limit=None): self.from_token = from_token self.to_token = to_token self.direction = 'f' if direction == 'f' else 'b' - self.limit = int(limit) + self.limit = int(limit) if limit is not None else None @classmethod def from_request(cls, request, raise_invalid_params=True): @@ -80,8 +80,8 @@ class PaginationConfig(object): except: raise SynapseError(400, "'to' paramater is invalid") - limit = get_param("limit", "0") - if not limit.isdigit(): + limit = get_param("limit", None) + if limit is not None and not limit.isdigit(): raise SynapseError(400, "'limit' parameter must be an integer.") try: -- cgit 1.4.1 From fd40a80a6885f02ebe77aa4c95a137e2e1ae9cae Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Fri, 21 Nov 2014 15:11:48 +0000 Subject: Return 404 M_NOT_FOUND when trying to look up a room alias that doesn't exist --- synapse/handlers/directory.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'synapse') diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py index af4e7d49c8..3b37e49e6f 100644 --- a/synapse/handlers/directory.py +++ b/synapse/handlers/directory.py @@ -17,7 +17,7 @@ from twisted.internet import defer from ._base import BaseHandler -from synapse.api.errors import SynapseError +from synapse.api.errors import SynapseError, Codes, CodeMessageException from synapse.api.events.room import RoomAliasesEvent import logging @@ -84,22 +84,32 @@ class DirectoryHandler(BaseHandler): room_id = result.room_id servers = result.servers else: - result = yield self.federation.make_query( - destination=room_alias.domain, - query_type="directory", - args={ - "room_alias": room_alias.to_string(), - }, - retry_on_dns_fail=False, - ) + try: + result = yield self.federation.make_query( + destination=room_alias.domain, + query_type="directory", + args={ + "room_alias": room_alias.to_string(), + }, + retry_on_dns_fail=False, + ) + except CodeMessageException as e: + logging.warn("Error retrieving alias") + if e.code == 404: + result = None + else: + raise if result and "room_id" in result and "servers" in result: room_id = result["room_id"] servers = result["servers"] if not room_id: - defer.returnValue({}) - return + raise SynapseError( + 404, + "Room alias %r not found" % (room_alias.to_string(),), + Codes.NOT_FOUND + ) extra_servers = yield self.store.get_joined_hosts_for_room(room_id) servers = list(set(extra_servers) | set(servers)) @@ -129,7 +139,9 @@ class DirectoryHandler(BaseHandler): }) else: raise SynapseError( - 404, "Room alias \"%s\" not found" % (room_alias,) + 404, + "Room alias %r not found" % (room_alias.to_string(),), + Codes.NOT_FOUND ) @defer.inlineCallbacks -- cgit 1.4.1 From ae8ad55cb8ab773b8a24f38ef8219ee7d0551dec Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 24 Nov 2014 01:41:12 +0000 Subject: typos --- synapse/http/content_repository.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'synapse') diff --git a/synapse/http/content_repository.py b/synapse/http/content_repository.py index 7e046dfe49..64ecb5346e 100644 --- a/synapse/http/content_repository.py +++ b/synapse/http/content_repository.py @@ -181,7 +181,7 @@ class ContentRepoResource(resource.Resource): fname = yield self.map_request_to_name(request) - # TODO I have a suspcious feeling this is just going to block + # TODO I have a suspicious feeling this is just going to block with open(fname, "wb") as f: f.write(request.content.read()) @@ -190,7 +190,7 @@ class ContentRepoResource(resource.Resource): # FIXME: we can't assume what the repo's public mounted path is # ...plus self-signed SSL won't work to remote clients anyway # ...and we can't assume that it's SSL anyway, as we might want to - # server it via the non-SSL listener... + # serve it via the non-SSL listener... url = "%s/_matrix/content/%s" % ( self.external_addr, file_name ) -- cgit 1.4.1 From a46e5ef6216ca8c6023593c6c24dfb62be49df10 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 24 Nov 2014 10:50:28 +0000 Subject: SYN-163: Add an order by rowid to selects. This should fix the bug where the edges of the graph get returned in a different order than they were inserted in, and so no get_event no longer returned the exact same JSON as was inserted. This meant that signature checks failed. --- synapse/storage/_base.py | 15 ++++++++++----- tests/storage/test_base.py | 12 ++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'synapse') diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py index fd5b2affad..4881f03368 100644 --- a/synapse/storage/_base.py +++ b/synapse/storage/_base.py @@ -246,7 +246,10 @@ class SQLBaseStore(object): raise StoreError(404, "No row found") def _simple_select_onecol_txn(self, txn, table, keyvalues, retcol): - sql = "SELECT %(retcol)s FROM %(table)s WHERE %(where)s" % { + sql = ( + "SELECT %(retcol)s FROM %(table)s WHERE %(where)s " + "ORDER BY rowid asc" + ) % { "retcol": retcol, "table": table, "where": " AND ".join("%s = ?" % k for k in keyvalues.keys()), @@ -299,7 +302,7 @@ class SQLBaseStore(object): keyvalues : dict of column names and values to select the rows with retcols : list of strings giving the names of the columns to return """ - sql = "SELECT %s FROM %s WHERE %s" % ( + sql = "SELECT %s FROM %s WHERE %s ORDER BY rowid asc" % ( ", ".join(retcols), table, " AND ".join("%s = ?" % (k, ) for k in keyvalues) @@ -334,7 +337,7 @@ class SQLBaseStore(object): retcols=None, allow_none=False): """ Combined SELECT then UPDATE.""" if retcols: - select_sql = "SELECT %s FROM %s WHERE %s" % ( + select_sql = "SELECT %s FROM %s WHERE %s ORDER BY rowid asc" % ( ", ".join(retcols), table, " AND ".join("%s = ?" % (k) for k in keyvalues) @@ -461,7 +464,7 @@ class SQLBaseStore(object): def _get_events_txn(self, txn, event_ids): # FIXME (erikj): This should be batched? - sql = "SELECT * FROM events WHERE event_id = ?" + sql = "SELECT * FROM events WHERE event_id = ? ORDER BY rowid asc" event_rows = [] for e_id in event_ids: @@ -478,7 +481,9 @@ class SQLBaseStore(object): def _parse_events_txn(self, txn, rows): events = [self._parse_event_from_row(r) for r in rows] - select_event_sql = "SELECT * FROM events WHERE event_id = ?" + select_event_sql = ( + "SELECT * FROM events WHERE event_id = ? ORDER BY rowid asc" + ) for i, ev in enumerate(events): signatures = self._get_event_signatures_txn( diff --git a/tests/storage/test_base.py b/tests/storage/test_base.py index fabd364be9..a6f1d6a333 100644 --- a/tests/storage/test_base.py +++ b/tests/storage/test_base.py @@ -84,7 +84,8 @@ class SQLBaseStoreTestCase(unittest.TestCase): self.assertEquals("Value", value) self.mock_txn.execute.assert_called_with( - "SELECT retcol FROM tablename WHERE keycol = ?", + "SELECT retcol FROM tablename WHERE keycol = ? " + "ORDER BY rowid asc", ["TheKey"] ) @@ -101,7 +102,8 @@ class SQLBaseStoreTestCase(unittest.TestCase): self.assertEquals({"colA": 1, "colB": 2, "colC": 3}, ret) self.mock_txn.execute.assert_called_with( - "SELECT colA, colB, colC FROM tablename WHERE keycol = ?", + "SELECT colA, colB, colC FROM tablename WHERE keycol = ? " + "ORDER BY rowid asc", ["TheKey"] ) @@ -135,7 +137,8 @@ class SQLBaseStoreTestCase(unittest.TestCase): self.assertEquals([{"colA": 1}, {"colA": 2}, {"colA": 3}], ret) self.mock_txn.execute.assert_called_with( - "SELECT colA FROM tablename WHERE keycol = ?", + "SELECT colA FROM tablename WHERE keycol = ? " + "ORDER BY rowid asc", ["A set"] ) @@ -184,7 +187,8 @@ class SQLBaseStoreTestCase(unittest.TestCase): self.assertEquals({"columname": "Old Value"}, ret) self.mock_txn.execute.assert_has_calls([ - call('SELECT columname FROM tablename WHERE keycol = ?', + call('SELECT columname FROM tablename WHERE keycol = ? ' + 'ORDER BY rowid asc', ['TheKey']), call("UPDATE tablename SET columname = ? WHERE keycol = ?", ["New Value", "TheKey"]) -- cgit 1.4.1 From 4bd0ab76c69b8f4861de26894f8e50407e9fc87f Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 24 Nov 2014 12:56:17 +0000 Subject: We don't always want to Auth get_persisted_pdu --- synapse/federation/replication.py | 16 ++++++++++++---- synapse/handlers/federation.py | 15 ++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'synapse') diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 124dc31225..4cd17bdb9c 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -504,13 +504,15 @@ class ReplicationLayer(object): defer.returnValue(self.event_from_pdu_json(pdu_dict)) @log_function - def _get_persisted_pdu(self, origin, event_id): + def _get_persisted_pdu(self, origin, event_id, do_auth=True): """ Get a PDU from the database with given origin and id. Returns: Deferred: Results in a `Pdu`. """ - return self.handler.get_persisted_pdu(origin, event_id) + return self.handler.get_persisted_pdu( + origin, event_id, do_auth=do_auth + ) def _transaction_from_pdus(self, pdu_list): """Returns a new Transaction containing the given PDUs suitable for @@ -529,7 +531,9 @@ class ReplicationLayer(object): @log_function def _handle_new_pdu(self, origin, pdu, backfilled=False): # We reprocess pdus when we have seen them only as outliers - existing = yield self._get_persisted_pdu(origin, pdu.event_id) + existing = yield self._get_persisted_pdu( + origin, pdu.event_id, do_auth=False + ) if existing and (not existing.outlier or pdu.outlier): logger.debug("Already seen pdu %s", pdu.event_id) @@ -547,7 +551,11 @@ class ReplicationLayer(object): if min_depth and pdu.depth > min_depth: for event_id, hashes in pdu.prev_events: - exists = yield self._get_persisted_pdu(origin, event_id) + exists = yield self._get_persisted_pdu( + origin, + event_id, + do_auth=False + ) if not exists: logger.debug("Requesting pdu %s", event_id) diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 2e8b8a1f9a..f601de4488 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -529,7 +529,7 @@ class FederationHandler(BaseHandler): @defer.inlineCallbacks @log_function - def get_persisted_pdu(self, origin, event_id): + def get_persisted_pdu(self, origin, event_id, do_auth=True): """ Get a PDU from the database with given origin and id. Returns: @@ -541,12 +541,13 @@ class FederationHandler(BaseHandler): ) if event: - in_room = yield self.auth.check_host_in_room( - event.room_id, - origin - ) - if not in_room: - raise AuthError(403, "Host not in room.") + if do_auth: + in_room = yield self.auth.check_host_in_room( + event.room_id, + origin + ) + if not in_room: + raise AuthError(403, "Host not in room.") defer.returnValue(event) else: -- cgit 1.4.1 From 2bca242fdc397bc5d67a77589bda2a9068f86b4e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 24 Nov 2014 13:46:41 +0000 Subject: Ask for any auth events that we don't have --- synapse/federation/replication.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'synapse') diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 4cd17bdb9c..30aab7f35a 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -542,6 +542,21 @@ class ReplicationLayer(object): state = None + # We need to make sure we have all the auth events. + for e_id, _ in pdu.auth_events: + exists = yield self._get_persisted_pdu( + origin, + e_id, + do_auth=False + ) + + if not exists: + yield self.get_pdu( + origin, + event_id=e_id, + ) + logger.debug("Processed pdu %s", e_id) + # Get missing pdus if necessary. if not pdu.outlier: # We only backfill backwards to the min depth. -- cgit 1.4.1 From e549aac12714c36f3a27d131a031d219283ac3d7 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 24 Nov 2014 13:47:58 +0000 Subject: Add missing None check --- synapse/api/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/api/auth.py b/synapse/api/auth.py index cbf3ae0ca4..c4597c1757 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -155,7 +155,7 @@ class Auth(object): # Get room creation event: key = (RoomCreateEvent.TYPE, "", ) create = event.old_state_events.get(key) - if event.prev_events[0][0] == create.event_id: + if create and event.prev_events[0][0] == create.event_id: if create.content["creator"] == event.state_key: return True -- cgit 1.4.1 From 4961a4fab1bd5229521b77a7296f5650c70865be Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 24 Nov 2014 13:55:49 +0000 Subject: Mark the auth events as possible outlier --- synapse/federation/replication.py | 1 + 1 file changed, 1 insertion(+) (limited to 'synapse') diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 30aab7f35a..fa2463d4a3 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -554,6 +554,7 @@ class ReplicationLayer(object): yield self.get_pdu( origin, event_id=e_id, + outlier=True, ) logger.debug("Processed pdu %s", e_id) -- cgit 1.4.1 From 15099fade5ec9b52e48f952327f1e979b185e7fe Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 25 Nov 2014 10:57:31 +0000 Subject: Drop log level for incorrect logging contexts to WARN if the context is wrong and DEBUG if the context is missing --- synapse/util/logcontext.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'synapse') diff --git a/synapse/util/logcontext.py b/synapse/util/logcontext.py index 23b3decb45..7d85018d97 100644 --- a/synapse/util/logcontext.py +++ b/synapse/util/logcontext.py @@ -55,11 +55,14 @@ class LoggingContext(object): None to avoid suppressing any exeptions that were thrown. """ if self.thread_local.current_context is not self: - logger.error( - "Current logging context %s is not the expected context %s", - self.thread_local.current_context, - self - ) + if self.thread_local.current_context is self.sentinel: + logger.debug("Expected logging context %s has been lost", self) + else: + logger.warn( + "Current logging context %s is not expected context %s", + self.thread_local.current_context, + self + ) self.thread_local.current_context = self.parent_context self.parent_context = None -- cgit 1.4.1 From 3536fd7d60c626a20123105357c6b131b9ceb26f Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Tue, 25 Nov 2014 11:02:19 +0000 Subject: Don't double url-decode state event types. --- synapse/rest/room.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/rest/room.py b/synapse/rest/room.py index 4f6d039b61..cc6ffb9aff 100644 --- a/synapse/rest/room.py +++ b/synapse/rest/room.py @@ -148,7 +148,7 @@ class RoomStateEventRestServlet(RestServlet): content = _parse_json(request) event = self.event_factory.create_event( - etype=urllib.unquote(event_type), + etype=event_type, # already urldecoded content=content, room_id=urllib.unquote(room_id), user_id=user.to_string(), -- cgit 1.4.1 From 64fc859dac122a44a753eafe015a453085e6e9a8 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Tue, 25 Nov 2014 11:31:18 +0000 Subject: Fix bugs in invite/join dances. We now do more implement more of the auth on the events so that we don't reject valid events. --- synapse/api/auth.py | 138 ++++++++++++++++++------------------ synapse/api/events/__init__.py | 1 + synapse/federation/replication.py | 42 ++++++++--- synapse/handlers/_base.py | 2 +- synapse/handlers/federation.py | 144 ++++++++++++++++++++++++-------------- synapse/handlers/message.py | 2 +- tests/handlers/test_federation.py | 12 ++-- tests/handlers/test_room.py | 16 ++++- 8 files changed, 215 insertions(+), 142 deletions(-) (limited to 'synapse') diff --git a/synapse/api/auth.py b/synapse/api/auth.py index c4597c1757..fb911e51a6 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -38,79 +38,66 @@ class Auth(object): self.store = hs.get_datastore() self.state = hs.get_state_handler() - def check(self, event, raises=False): + def check(self, event, auth_events): """ Checks if this event is correctly authed. Returns: True if the auth checks pass. - Raises: - AuthError if there was a problem authorising this event. This will - be raised only if raises=True. """ try: - if hasattr(event, "room_id"): - if event.old_state_events is None: - # Oh, we don't know what the state of the room was, so we - # are trusting that this is allowed (at least for now) - logger.warn("Trusting event: %s", event.event_id) - return True - - if hasattr(event, "outlier") and event.outlier is True: - # TODO (erikj): Auth for outliers is done differently. - return True + if not hasattr(event, "room_id"): + raise AuthError(500, "Event has no room_id: %s" % event) + if auth_events is None: + # Oh, we don't know what the state of the room was, so we + # are trusting that this is allowed (at least for now) + logger.warn("Trusting event: %s", event.event_id) + return True - if event.type == RoomCreateEvent.TYPE: - # FIXME - return True + if event.type == RoomCreateEvent.TYPE: + # FIXME + return True - # FIXME: Temp hack - if event.type == RoomAliasesEvent.TYPE: - return True + # FIXME: Temp hack + if event.type == RoomAliasesEvent.TYPE: + return True - if event.type == RoomMemberEvent.TYPE: - allowed = self.is_membership_change_allowed(event) - if allowed: - logger.debug("Allowing! %s", event) - else: - logger.debug("Denying! %s", event) - return allowed + if event.type == RoomMemberEvent.TYPE: + allowed = self.is_membership_change_allowed( + event, auth_events + ) + if allowed: + logger.debug("Allowing! %s", event) + else: + logger.debug("Denying! %s", event) + return allowed - self.check_event_sender_in_room(event) - self._can_send_event(event) + self.check_event_sender_in_room(event, auth_events) + self._can_send_event(event, auth_events) - if event.type == RoomPowerLevelsEvent.TYPE: - self._check_power_levels(event) + if event.type == RoomPowerLevelsEvent.TYPE: + self._check_power_levels(event, auth_events) - if event.type == RoomRedactionEvent.TYPE: - self._check_redaction(event) + if event.type == RoomRedactionEvent.TYPE: + self._check_redaction(event, auth_events) - logger.debug("Allowing! %s", event) - return True - else: - raise AuthError(500, "Unknown event: %s" % event) + logger.debug("Allowing! %s", event) except AuthError as e: logger.info( "Event auth check failed on event %s with msg: %s", event, e.msg ) logger.info("Denying! %s", event) - if raises: - raise - - return False + raise @defer.inlineCallbacks def check_joined_room(self, room_id, user_id): - try: - member = yield self.store.get_room_member( - room_id=room_id, - user_id=user_id - ) - self._check_joined_room(member, user_id, room_id) - defer.returnValue(member) - except AttributeError: - pass - defer.returnValue(None) + member = yield self.state.get_current_state( + room_id=room_id, + event_type=RoomMemberEvent.TYPE, + state_key=user_id + ) + self._check_joined_room(member, user_id, room_id) + defer.returnValue(member) @defer.inlineCallbacks def check_host_in_room(self, room_id, host): @@ -130,9 +117,9 @@ class Auth(object): defer.returnValue(False) - def check_event_sender_in_room(self, event): + def check_event_sender_in_room(self, event, auth_events): key = (RoomMemberEvent.TYPE, event.user_id, ) - member_event = event.state_events.get(key) + member_event = auth_events.get(key) return self._check_joined_room( member_event, @@ -147,14 +134,14 @@ class Auth(object): )) @log_function - def is_membership_change_allowed(self, event): + def is_membership_change_allowed(self, event, auth_events): membership = event.content["membership"] # Check if this is the room creator joining: if len(event.prev_events) == 1 and Membership.JOIN == membership: # Get room creation event: key = (RoomCreateEvent.TYPE, "", ) - create = event.old_state_events.get(key) + create = auth_events.get(key) if create and event.prev_events[0][0] == create.event_id: if create.content["creator"] == event.state_key: return True @@ -163,19 +150,19 @@ class Auth(object): # get info about the caller key = (RoomMemberEvent.TYPE, event.user_id, ) - caller = event.old_state_events.get(key) + caller = auth_events.get(key) caller_in_room = caller and caller.membership == Membership.JOIN caller_invited = caller and caller.membership == Membership.INVITE # get info about the target key = (RoomMemberEvent.TYPE, target_user_id, ) - target = event.old_state_events.get(key) + target = auth_events.get(key) target_in_room = target and target.membership == Membership.JOIN key = (RoomJoinRulesEvent.TYPE, "", ) - join_rule_event = event.old_state_events.get(key) + join_rule_event = auth_events.get(key) if join_rule_event: join_rule = join_rule_event.content.get( "join_rule", JoinRules.INVITE @@ -186,11 +173,13 @@ class Auth(object): user_level = self._get_power_level_from_event_state( event, event.user_id, + auth_events, ) ban_level, kick_level, redact_level = ( self._get_ops_level_from_event_state( - event + event, + auth_events, ) ) @@ -260,9 +249,9 @@ class Auth(object): return True - def _get_power_level_from_event_state(self, event, user_id): + def _get_power_level_from_event_state(self, event, user_id, auth_events): key = (RoomPowerLevelsEvent.TYPE, "", ) - power_level_event = event.old_state_events.get(key) + power_level_event = auth_events.get(key) level = None if power_level_event: level = power_level_event.content.get("users", {}).get(user_id) @@ -270,16 +259,16 @@ class Auth(object): level = power_level_event.content.get("users_default", 0) else: key = (RoomCreateEvent.TYPE, "", ) - create_event = event.old_state_events.get(key) + create_event = auth_events.get(key) if (create_event is not None and create_event.content["creator"] == user_id): return 100 return level - def _get_ops_level_from_event_state(self, event): + def _get_ops_level_from_event_state(self, event, auth_events): key = (RoomPowerLevelsEvent.TYPE, "", ) - power_level_event = event.old_state_events.get(key) + power_level_event = auth_events.get(key) if power_level_event: return ( @@ -375,6 +364,11 @@ class Auth(object): key = (RoomMemberEvent.TYPE, event.user_id, ) member_event = event.old_state_events.get(key) + key = (RoomCreateEvent.TYPE, "", ) + create_event = event.old_state_events.get(key) + if create_event: + auth_events.append(create_event.event_id) + if join_rule_event: join_rule = join_rule_event.content.get("join_rule") is_public = join_rule == JoinRules.PUBLIC if join_rule else False @@ -406,9 +400,9 @@ class Auth(object): event.auth_events = zip(auth_events, hashes) @log_function - def _can_send_event(self, event): + def _can_send_event(self, event, auth_events): key = (RoomPowerLevelsEvent.TYPE, "", ) - send_level_event = event.old_state_events.get(key) + send_level_event = auth_events.get(key) send_level = None if send_level_event: send_level = send_level_event.content.get("events", {}).get( @@ -432,6 +426,7 @@ class Auth(object): user_level = self._get_power_level_from_event_state( event, event.user_id, + auth_events, ) if user_level: @@ -468,14 +463,16 @@ class Auth(object): return True - def _check_redaction(self, event): + def _check_redaction(self, event, auth_events): user_level = self._get_power_level_from_event_state( event, event.user_id, + auth_events, ) _, _, redact_level = self._get_ops_level_from_event_state( - event + event, + auth_events, ) if user_level < redact_level: @@ -484,7 +481,7 @@ class Auth(object): "You don't have permission to redact events" ) - def _check_power_levels(self, event): + def _check_power_levels(self, event, auth_events): user_list = event.content.get("users", {}) # Validate users for k, v in user_list.items(): @@ -499,7 +496,7 @@ class Auth(object): raise SynapseError(400, "Not a valid power level: %s" % (v,)) key = (event.type, event.state_key, ) - current_state = event.old_state_events.get(key) + current_state = auth_events.get(key) if not current_state: return @@ -507,6 +504,7 @@ class Auth(object): user_level = self._get_power_level_from_event_state( event, event.user_id, + auth_events, ) # Check other levels: diff --git a/synapse/api/events/__init__.py b/synapse/api/events/__init__.py index 8a35b4cb7d..22939d011a 100644 --- a/synapse/api/events/__init__.py +++ b/synapse/api/events/__init__.py @@ -125,6 +125,7 @@ class SynapseEvent(JsonEncodedObject): pdu_json.pop("outlier", None) pdu_json.pop("replaces_state", None) pdu_json.pop("redacted", None) + pdu_json.pop("prev_content", None) state_hash = pdu_json.pop("state_hash", None) if state_hash is not None: pdu_json.setdefault("unsigned", {})["state_hash"] = state_hash diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index fa2463d4a3..89c0ef49e9 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -481,11 +481,17 @@ class ReplicationLayer(object): # FIXME: We probably want to do something with the auth_chain given # to us - # auth_chain = [ - # Pdu(outlier=True, **p) for p in content.get("auth_chain", []) - # ] + auth_chain = [ + self.event_from_pdu_json(p, outlier=True) + for p in content.get("auth_chain", []) + ] - defer.returnValue(state) + auth_chain.sort(key=lambda e: e.depth) + + defer.returnValue({ + "state": state, + "auth_chain": auth_chain, + }) @defer.inlineCallbacks def send_invite(self, destination, context, event_id, pdu): @@ -551,12 +557,26 @@ class ReplicationLayer(object): ) if not exists: - yield self.get_pdu( - origin, - event_id=e_id, - outlier=True, - ) - logger.debug("Processed pdu %s", e_id) + try: + logger.debug( + "Getting missing auth event %s from %s", + e_id, + origin, + ) + + yield self.get_pdu( + origin, + event_id=e_id, + outlier=True, + ) + + logger.debug("Processed pdu %s", e_id) + except: + logger.warn( + "Failed to get auth event %s from %s", + e_id, + origin + ) # Get missing pdus if necessary. if not pdu.outlier: @@ -578,7 +598,7 @@ class ReplicationLayer(object): try: yield self.get_pdu( - pdu.origin, + origin, event_id=event_id, ) logger.debug("Processed pdu %s", event_id) diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py index d53cd3df3e..15adc9dc2c 100644 --- a/synapse/handlers/_base.py +++ b/synapse/handlers/_base.py @@ -78,7 +78,7 @@ class BaseHandler(object): if not suppress_auth: logger.debug("Authing...") - self.auth.check(event, raises=True) + self.auth.check(event, auth_events=event.old_state_events) logger.debug("Authed") else: logger.debug("Suppressed auth.") diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index f601de4488..14066ac4f3 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -24,7 +24,8 @@ from synapse.api.constants import Membership from synapse.util.logutils import log_function from synapse.util.async import run_on_reactor from synapse.crypto.event_signing import ( - compute_event_signature, check_event_content_hash + compute_event_signature, check_event_content_hash, + add_hashes_and_signatures, ) from syutil.jsonutil import encode_canonical_json @@ -141,15 +142,14 @@ class FederationHandler(BaseHandler): ) event = redacted_event - is_new_state = yield self.state_handler.annotate_event_with_state( - event, - old_state=state - ) - logger.debug("Event: %s", event) try: - self.auth.check(event, raises=True) + yield self._handle_new_event( + event, + state=state, + backfilled=backfilled + ) except AuthError as e: raise FederationError( "ERROR", @@ -158,17 +158,6 @@ class FederationHandler(BaseHandler): affected=event.event_id, ) - is_new_state = is_new_state and not backfilled - - # TODO: Implement something in federation that allows us to - # respond to PDU. - - yield self.store.persist_event( - event, - backfilled, - is_new_state=is_new_state - ) - room = yield self.store.get_room(event.room_id) if not room: @@ -276,6 +265,8 @@ class FederationHandler(BaseHandler): We suspend processing of any received events from this room until we have finished processing the join. """ + logger.debug("Joining %s to %s", joinee, room_id) + pdu = yield self.replication_layer.make_join( target_host, room_id, @@ -298,19 +289,28 @@ class FederationHandler(BaseHandler): try: event.event_id = self.event_factory.create_event_id() + event.origin = self.hs.hostname event.content = content - state = yield self.replication_layer.send_join( + if not hasattr(event, "signatures"): + event.signatures = {} + + add_hashes_and_signatures( + event, + self.hs.hostname, + self.hs.config.signing_key[0], + ) + + ret = yield self.replication_layer.send_join( target_host, event ) - logger.debug("do_invite_join state: %s", state) + state = ret["state"] + auth_chain = ret["auth_chain"] - yield self.state_handler.annotate_event_with_state( - event, - old_state=state - ) + logger.debug("do_invite_join auth_chain: %s", auth_chain) + logger.debug("do_invite_join state: %s", state) logger.debug("do_invite_join event: %s", event) @@ -324,34 +324,31 @@ class FederationHandler(BaseHandler): # FIXME pass + for e in auth_chain: + e.outlier = True + yield self._handle_new_event(e) + for e in state: # FIXME: Auth these. e.outlier = True + yield self._handle_new_event(e) - yield self.state_handler.annotate_event_with_state( - e, - ) - - yield self.store.persist_event( - e, - backfilled=False, - is_new_state=True - ) + yield self._handle_new_event(event, state=state) - yield self.store.persist_event( - event, - backfilled=False, - is_new_state=True + yield self.notifier.on_new_room_event( + event, extra_users=[joinee] ) + + logger.debug("Finished joining %s to %s", joinee, room_id) finally: room_queue = self.room_queues[room_id] del self.room_queues[room_id] for p in room_queue: try: - yield self.on_receive_pdu(p, backfilled=False) + self.on_receive_pdu(p, backfilled=False) except: - pass + logger.exception("Couldn't handle pdu") defer.returnValue(True) @@ -375,7 +372,7 @@ class FederationHandler(BaseHandler): yield self.state_handler.annotate_event_with_state(event) yield self.auth.add_auth_events(event) - self.auth.check(event, raises=True) + self.auth.check(event, auth_events=event.old_state_events) pdu = event @@ -391,17 +388,7 @@ class FederationHandler(BaseHandler): event.outlier = False - state_handler = self.state_handler - is_new_state = yield state_handler.annotate_event_with_state(event) - self.auth.check(event, raises=True) - - # FIXME (erikj): All this is duplicated above :( - - yield self.store.persist_event( - event, - backfilled=False, - is_new_state=is_new_state - ) + yield self._handle_new_event(event) extra_users = [] if event.type == RoomMemberEvent.TYPE: @@ -414,7 +401,7 @@ class FederationHandler(BaseHandler): ) if event.type == RoomMemberEvent.TYPE: - if event.membership == Membership.JOIN: + if event.content["membership"] == Membership.JOIN: user = self.hs.parse_userid(event.state_key) yield self.distributor.fire( "user_joined_room", user=user, room_id=event.room_id @@ -565,3 +552,56 @@ class FederationHandler(BaseHandler): ) while waiters: waiters.pop().callback(None) + + @defer.inlineCallbacks + def _handle_new_event(self, event, state=None, backfilled=False): + is_new_state = yield self.state_handler.annotate_event_with_state( + event, + old_state=state + ) + + if event.old_state_events: + known_ids = set( + [s.event_id for s in event.old_state_events.values()] + ) + for e_id, _ in event.auth_events: + if e_id not in known_ids: + e = yield self.store.get_event( + e_id, + allow_none=True, + ) + + if not e: + # TODO: Do some conflict res to make sure that we're + # not the ones who are wrong. + logger.info( + "Rejecting %s as %s not in %s", + event.event_id, e_id, known_ids, + ) + raise AuthError(403, "Auth events are stale") + + auth_events = event.old_state_events + else: + # We need to get the auth events from somewhere. + + # TODO: Don't just hit the DBs? + + auth_events = {} + for e_id, _ in event.auth_events: + e = yield self.store.get_event( + e_id, + allow_none=True, + ) + + if not e: + raise AuthError(403, "Can't find auth event.") + + auth_events[(e.type, e.state_key)] = e + + self.auth.check(event, auth_events=auth_events) + + yield self.store.persist_event( + event, + backfilled=backfilled, + is_new_state=(is_new_state and not backfilled) + ) diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index ae0fc43ca2..42dc4d46f3 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -306,7 +306,7 @@ class MessageHandler(BaseHandler): auth_user = self.hs.parse_userid(user_id) # TODO: These concurrently - state_tuples = yield self.store.get_current_state(room_id) + state_tuples = yield self.state_handler.get_current_state(room_id) state = [self.hs.serialize_event(x) for x in state_tuples] member_event = (yield self.store.get_room_member( diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index 3487a090e9..548bae7a8d 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -83,20 +83,22 @@ class FederationTestCase(unittest.TestCase): event_id="$a:b", user_id="@a:b", origin="b", + auth_events=[], hashes={"sha256":"AcLrgtUIqqwaGoHhrEvYG1YLDIsVPYJdSRGhkp3jJp8"}, ) self.datastore.persist_event.return_value = defer.succeed(None) self.datastore.get_room.return_value = defer.succeed(True) - self.state_handler.annotate_event_with_state.return_value = ( - defer.succeed(False) - ) + def annotate(ev, old_state=None): + ev.old_state_events = [] + return defer.succeed(False) + self.state_handler.annotate_event_with_state.side_effect = annotate yield self.handlers.federation_handler.on_receive_pdu(pdu, False) self.datastore.persist_event.assert_called_once_with( - ANY, False, is_new_state=False + ANY, is_new_state=False, backfilled=False ) self.state_handler.annotate_event_with_state.assert_called_once_with( @@ -104,7 +106,7 @@ class FederationTestCase(unittest.TestCase): old_state=None, ) - self.auth.check.assert_called_once_with(ANY, raises=True) + self.auth.check.assert_called_once_with(ANY, auth_events={}) self.notifier.on_new_room_event.assert_called_once_with( ANY, diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index cbe591ab90..0279ab703a 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -120,7 +120,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): self.datastore.get_room_member.return_value = defer.succeed(None) - event.state_events = { + event.old_state_events = { (RoomMemberEvent.TYPE, "@alice:green"): self._create_member( user_id="@alice:green", room_id=room_id, @@ -129,9 +129,11 @@ class RoomMemberHandlerTestCase(unittest.TestCase): user_id="@bob:red", room_id=room_id, ), - (RoomMemberEvent.TYPE, target_user_id): event, } + event.state_events = event.old_state_events + event.state_events[(RoomMemberEvent.TYPE, target_user_id)] = event + # Actual invocation yield self.room_member_handler.change_membership(event) @@ -187,6 +189,16 @@ class RoomMemberHandlerTestCase(unittest.TestCase): (RoomMemberEvent.TYPE, user_id): event, } + event.old_state_events = { + (RoomMemberEvent.TYPE, "@alice:green"): self._create_member( + user_id="@alice:green", + room_id=room_id, + ), + } + + event.state_events = event.old_state_events + event.state_events[(RoomMemberEvent.TYPE, user_id)] = event + # Actual invocation yield self.room_member_handler.change_membership(event) -- cgit 1.4.1 From 3598c11c8dcb5fb0df16276298760e0de31d0a84 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 10:41:08 +0000 Subject: Correctly handle the case where we get an event for an unknown room, which turns out we are actually in --- synapse/federation/replication.py | 16 +++++++-- synapse/handlers/federation.py | 72 ++++++++++++++++++++++++--------------- synapse/state.py | 2 +- synapse/storage/__init__.py | 54 +++++++++++++++++++++-------- synapse/storage/state.py | 2 +- 5 files changed, 99 insertions(+), 47 deletions(-) (limited to 'synapse') diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 89c0ef49e9..6bfb30b42d 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -559,7 +559,7 @@ class ReplicationLayer(object): if not exists: try: logger.debug( - "Getting missing auth event %s from %s", + "_handle_new_pdu fetch missing auth event %s from %s", e_id, origin, ) @@ -585,6 +585,11 @@ class ReplicationLayer(object): pdu.room_id ) + logger.debug( + "_handle_new_pdu min_depth for %s: %d", + pdu.room_id, min_depth + ) + if min_depth and pdu.depth > min_depth: for event_id, hashes in pdu.prev_events: exists = yield self._get_persisted_pdu( @@ -594,7 +599,10 @@ class ReplicationLayer(object): ) if not exists: - logger.debug("Requesting pdu %s", event_id) + logger.debug( + "_handle_new_pdu requesting pdu %s", + event_id + ) try: yield self.get_pdu( @@ -608,6 +616,10 @@ class ReplicationLayer(object): else: # We need to get the state at this event, since we have reached # a backward extremity edge. + logger.debug( + "_handle_new_pdu getting state for %s", + pdu.room_id + ) state = yield self.get_state_for_context( origin, pdu.room_id, pdu.event_id, ) diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 14066ac4f3..252c1f1684 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -144,11 +144,24 @@ class FederationHandler(BaseHandler): logger.debug("Event: %s", event) + # FIXME (erikj): Awful hack to make the case where we are not currently + # in the room work + current_state = None + if state: + is_in_room = yield self.auth.check_host_in_room( + event.room_id, + self.server_name + ) + if not is_in_room: + logger.debug("Got event for room we're not in.") + current_state = state + try: yield self._handle_new_event( event, state=state, - backfilled=backfilled + backfilled=backfilled, + current_state=current_state, ) except AuthError as e: raise FederationError( @@ -161,29 +174,11 @@ class FederationHandler(BaseHandler): room = yield self.store.get_room(event.room_id) if not room: - # Huh, let's try and get the current state - try: - yield self.replication_layer.get_state_for_context( - event.origin, event.room_id, event.event_id, - ) - - hosts = yield self.store.get_joined_hosts_for_room( - event.room_id - ) - if self.hs.hostname in hosts: - try: - yield self.store.store_room( - room_id=event.room_id, - room_creator_user_id="", - is_public=False, - ) - except: - pass - except: - logger.exception( - "Failed to get current state for room %s", - event.room_id - ) + yield self.store.store_room( + room_id=event.room_id, + room_creator_user_id="", + is_public=False, + ) if not backfilled: extra_users = [] @@ -244,6 +239,8 @@ class FederationHandler(BaseHandler): pdu=event ) + + defer.returnValue(pdu) @defer.inlineCallbacks @@ -327,13 +324,23 @@ class FederationHandler(BaseHandler): for e in auth_chain: e.outlier = True yield self._handle_new_event(e) + yield self.notifier.on_new_room_event( + e, extra_users=[joinee] + ) for e in state: # FIXME: Auth these. e.outlier = True yield self._handle_new_event(e) + yield self.notifier.on_new_room_event( + e, extra_users=[joinee] + ) - yield self._handle_new_event(event, state=state) + yield self._handle_new_event( + event, + state=state, + current_state=state + ) yield self.notifier.on_new_room_event( event, extra_users=[joinee] @@ -554,7 +561,12 @@ class FederationHandler(BaseHandler): waiters.pop().callback(None) @defer.inlineCallbacks - def _handle_new_event(self, event, state=None, backfilled=False): + def _handle_new_event(self, event, state=None, backfilled=False, + current_state=None): + if state: + for s in state: + yield self._handle_new_event(s) + is_new_state = yield self.state_handler.annotate_event_with_state( event, old_state=state @@ -594,7 +606,10 @@ class FederationHandler(BaseHandler): ) if not e: - raise AuthError(403, "Can't find auth event.") + raise AuthError( + 403, + "Can't find auth event %s." % (e_id, ) + ) auth_events[(e.type, e.state_key)] = e @@ -603,5 +618,6 @@ class FederationHandler(BaseHandler): yield self.store.persist_event( event, backfilled=backfilled, - is_new_state=(is_new_state and not backfilled) + is_new_state=(is_new_state and not backfilled), + current_state=current_state, ) diff --git a/synapse/state.py b/synapse/state.py index 1c999e4d79..430665f7ba 100644 --- a/synapse/state.py +++ b/synapse/state.py @@ -82,7 +82,7 @@ class StateHandler(object): if hasattr(event, "outlier") and event.outlier: event.state_group = None event.old_state_events = None - event.state_events = {} + event.state_events = None defer.returnValue(False) return diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index 1231794de0..a5ee923bc3 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -93,7 +93,8 @@ class DataStore(RoomMemberStore, RoomStore, @defer.inlineCallbacks @log_function - def persist_event(self, event, backfilled=False, is_new_state=True): + def persist_event(self, event, backfilled=False, is_new_state=True, + current_state=None): stream_ordering = None if backfilled: if not self.min_token_deferred.called: @@ -109,6 +110,7 @@ class DataStore(RoomMemberStore, RoomStore, backfilled=backfilled, stream_ordering=stream_ordering, is_new_state=is_new_state, + current_state=current_state, ) except _RollbackButIsFineException: pass @@ -137,7 +139,7 @@ class DataStore(RoomMemberStore, RoomStore, @log_function def _persist_event_txn(self, txn, event, backfilled, stream_ordering=None, - is_new_state=True): + is_new_state=True, current_state=None): if event.type == RoomMemberEvent.TYPE: self._store_room_member_txn(txn, event) elif event.type == FeedbackEvent.TYPE: @@ -206,8 +208,24 @@ class DataStore(RoomMemberStore, RoomStore, self._store_state_groups_txn(txn, event) + if current_state: + txn.execute("DELETE FROM current_state_events") + + for s in current_state: + self._simple_insert_txn( + txn, + "current_state_events", + { + "event_id": s.event_id, + "room_id": s.room_id, + "type": s.type, + "state_key": s.state_key, + }, + or_replace=True, + ) + is_state = hasattr(event, "state_key") and event.state_key is not None - if is_new_state and is_state: + if is_state: vals = { "event_id": event.event_id, "room_id": event.room_id, @@ -225,17 +243,18 @@ class DataStore(RoomMemberStore, RoomStore, or_replace=True, ) - self._simple_insert_txn( - txn, - "current_state_events", - { - "event_id": event.event_id, - "room_id": event.room_id, - "type": event.type, - "state_key": event.state_key, - }, - or_replace=True, - ) + if is_new_state: + self._simple_insert_txn( + txn, + "current_state_events", + { + "event_id": event.event_id, + "room_id": event.room_id, + "type": event.type, + "state_key": event.state_key, + }, + or_replace=True, + ) for e_id, h in event.prev_state: self._simple_insert_txn( @@ -312,7 +331,12 @@ class DataStore(RoomMemberStore, RoomStore, txn, event.event_id, ref_alg, ref_hash_bytes ) - self._update_min_depth_for_room_txn(txn, event.room_id, event.depth) + if not outlier: + self._update_min_depth_for_room_txn( + txn, + event.room_id, + event.depth + ) def _store_redaction(self, txn, event): txn.execute( diff --git a/synapse/storage/state.py b/synapse/storage/state.py index 55ea567793..e0f44b3e59 100644 --- a/synapse/storage/state.py +++ b/synapse/storage/state.py @@ -87,7 +87,7 @@ class StateStore(SQLBaseStore): ) def _store_state_groups_txn(self, txn, event): - if not event.state_events: + if event.state_events is None: return state_group = event.state_group -- cgit 1.4.1 From 87538711b6fe26b1c1c708ed67345a91fd64c8fb Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 11:14:30 +0000 Subject: Update schema to support multiple signatures --- synapse/storage/schema/event_signatures.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/storage/schema/event_signatures.sql b/synapse/storage/schema/event_signatures.sql index 4efa8a3e63..b6b56b47a2 100644 --- a/synapse/storage/schema/event_signatures.sql +++ b/synapse/storage/schema/event_signatures.sql @@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS event_signatures ( signature_name TEXT, key_id TEXT, signature BLOB, - CONSTRAINT uniqueness UNIQUE (event_id, key_id) + CONSTRAINT uniqueness UNIQUE (event_id, signature_name, key_id) ); CREATE INDEX IF NOT EXISTS event_signatures_id ON event_signatures ( -- cgit 1.4.1 From cb76945688e8f594392ba4e1b5ba8ee14abb1234 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 11:17:19 +0000 Subject: Add update delta for schema change --- synapse/storage/__init__.py | 2 +- synapse/storage/schema/delta/v8.sql | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 synapse/storage/schema/delta/v8.sql (limited to 'synapse') diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index a5ee923bc3..1fb33171e8 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -67,7 +67,7 @@ SCHEMAS = [ # Remember to update this number every time an incompatible change is made to # database schema files, so the users will be informed on server restarts. -SCHEMA_VERSION = 7 +SCHEMA_VERSION = 8 class _RollbackButIsFineException(Exception): diff --git a/synapse/storage/schema/delta/v8.sql b/synapse/storage/schema/delta/v8.sql new file mode 100644 index 0000000000..daf6646ed5 --- /dev/null +++ b/synapse/storage/schema/delta/v8.sql @@ -0,0 +1,34 @@ +/* Copyright 2014 OpenMarket 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. + */ + + CREATE TABLE IF NOT EXISTS event_signatures_2 ( + event_id TEXT, + signature_name TEXT, + key_id TEXT, + signature BLOB, + CONSTRAINT uniqueness UNIQUE (event_id, signature_name, key_id) +); + +INSERT INTO event_signatures_2 (event_id, signature_name, key_id, signature) +SELECT event_id, signature_name, key_id, signature FROM event_signatures; + +DROP TABLE event_signatures; +ALTER TABLE event_signatures_2 RENAME TO event_signatures; + +CREATE INDEX IF NOT EXISTS event_signatures_id ON event_signatures ( + event_id +); + +PRAGMA user_version = 8; \ No newline at end of file -- cgit 1.4.1 From ad13f14432d04e6eac50d49194d1158c22b6f5e0 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 11:53:12 +0000 Subject: Bump version numbers and change log --- CHANGES.rst | 8 ++++++++ VERSION | 2 +- setup.py | 4 ++-- synapse/__init__.py | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) (limited to 'synapse') diff --git a/CHANGES.rst b/CHANGES.rst index 5a284c3853..3cd08938a2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,11 @@ +Changes in synapse 0.5.1 (2014-11-26) +===================================== +See UPGRADES.rst for specific instructions on how to upgrade. + + * Fix bug where we served up an Event that did not match its signatures. + * Fix regression where we no longer correctly handled the case where a + homeserver receives an event for a room it doesn't recognise (but is in.) + Changes in synapse 0.5.0 (2014-11-19) ===================================== This release includes changes to the federation protocol and client-server API diff --git a/VERSION b/VERSION index 8f0916f768..4b9fcbec10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.0 +0.5.1 diff --git a/setup.py b/setup.py index d0d649612d..6b4320f0c9 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ setup( description="Reference Synapse Home Server", install_requires=[ "syutil==0.0.2", - "matrix_angular_sdk==0.5.0", + "matrix_angular_sdk==0.5.1", "Twisted>=14.0.0", "service_identity>=1.0.0", "pyopenssl>=0.14", @@ -45,7 +45,7 @@ setup( dependency_links=[ "https://github.com/matrix-org/syutil/tarball/v0.0.2#egg=syutil-0.0.2", "https://github.com/pyca/pynacl/tarball/52dbe2dc33f1#egg=pynacl-0.3.0", - "https://github.com/matrix-org/matrix-angular-sdk/tarball/v0.5.0/#egg=matrix_angular_sdk-0.5.0", + "https://github.com/matrix-org/matrix-angular-sdk/tarball/v0.5.1/#egg=matrix_angular_sdk-0.5.1", ], setup_requires=[ "setuptools_trial", diff --git a/synapse/__init__.py b/synapse/__init__.py index 14564e735e..1c10c2074e 100644 --- a/synapse/__init__.py +++ b/synapse/__init__.py @@ -16,4 +16,4 @@ """ This is a reference implementation of a synapse home server. """ -__version__ = "0.5.0" +__version__ = "0.5.1" -- cgit 1.4.1 From 4e2ffe79a4406616990eac1a00682f08d668218a Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 15:17:08 +0000 Subject: Don't delete the entire current_state_events table --- synapse/storage/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index 1fb33171e8..f15e3dfe62 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -209,7 +209,10 @@ class DataStore(RoomMemberStore, RoomStore, self._store_state_groups_txn(txn, event) if current_state: - txn.execute("DELETE FROM current_state_events") + txn.execute( + "DELETE FROM current_state_events WHERE room_id = ?", + (event.room_id,) + ) for s in current_state: self._simple_insert_txn( -- cgit 1.4.1 From 5288a7dc9a1009f6063ac5b4da55090225176ded Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 15:19:08 +0000 Subject: Bump version and changelog --- CHANGES.rst | 5 +++++ VERSION | 2 +- synapse/__init__.py | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'synapse') diff --git a/CHANGES.rst b/CHANGES.rst index 3cd08938a2..5f1fa3a9d5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,8 @@ +Changes in synapse 0.5.2 (2014-11-26) +===================================== + +Fix major bug that caused rooms to disspear from peoples initial sync. + Changes in synapse 0.5.1 (2014-11-26) ===================================== See UPGRADES.rst for specific instructions on how to upgrade. diff --git a/VERSION b/VERSION index 4b9fcbec10..cb0c939a93 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.1 +0.5.2 diff --git a/synapse/__init__.py b/synapse/__init__.py index 1c10c2074e..d5c2f25484 100644 --- a/synapse/__init__.py +++ b/synapse/__init__.py @@ -16,4 +16,4 @@ """ This is a reference implementation of a synapse home server. """ -__version__ = "0.5.1" +__version__ = "0.5.2" -- cgit 1.4.1 From 6c485c282dced1e60c0702ae8e9278fcc6a4f54c Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 16:06:20 +0000 Subject: Catch exceptions when trying to add an entry to rooms tables --- synapse/handlers/federation.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'synapse') diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 252c1f1684..5c6ed28e62 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -18,7 +18,9 @@ from ._base import BaseHandler from synapse.api.events.utils import prune_event -from synapse.api.errors import AuthError, FederationError, SynapseError +from synapse.api.errors import ( + AuthError, FederationError, SynapseError, StoreError, +) from synapse.api.events.room import RoomMemberEvent from synapse.api.constants import Membership from synapse.util.logutils import log_function @@ -174,11 +176,14 @@ class FederationHandler(BaseHandler): room = yield self.store.get_room(event.room_id) if not room: - yield self.store.store_room( - room_id=event.room_id, - room_creator_user_id="", - is_public=False, - ) + try: + yield self.store.store_room( + room_id=event.room_id, + room_creator_user_id="", + is_public=False, + ) + except StoreError: + logger.exception("Failed to store room.") if not backfilled: extra_users = [] -- cgit 1.4.1 From 858e87ab0d1bd88fcd5c819c482a40130e571874 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 16:29:03 +0000 Subject: Add a workaround for bug where some initial join events don't reference creation events in their auth_events --- synapse/handlers/federation.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 5c6ed28e62..fcef602055 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -21,7 +21,7 @@ from synapse.api.events.utils import prune_event from synapse.api.errors import ( AuthError, FederationError, SynapseError, StoreError, ) -from synapse.api.events.room import RoomMemberEvent +from synapse.api.events.room import RoomMemberEvent, RoomCreateEvent from synapse.api.constants import Membership from synapse.util.logutils import log_function from synapse.util.async import run_on_reactor @@ -618,6 +618,12 @@ class FederationHandler(BaseHandler): auth_events[(e.type, e.state_key)] = e + if event.type == RoomMemberEvent.TYPE and not event.auth_events: + if len(event.prev_events) == 1: + c = yield self.store.get_event(event.prev_events[0][0]) + if c.type == RoomCreateEvent.TYPE: + auth_events[(c.type, c.state_key)] = c + self.auth.check(event, auth_events=auth_events) yield self.store.persist_event( -- cgit 1.4.1 From 00ab5cd6f2bd3952e1216f13794c9ff392736ad7 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 26 Nov 2014 18:04:33 +0000 Subject: Attempt to fix bug where we 500d an event stream due to trying to cancel a timer twice --- synapse/handlers/events.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'synapse') diff --git a/synapse/handlers/events.py b/synapse/handlers/events.py index d59221a4fb..02202692d4 100644 --- a/synapse/handlers/events.py +++ b/synapse/handlers/events.py @@ -53,8 +53,12 @@ class EventStreamHandler(BaseHandler): if auth_user not in self._streams_per_user: self._streams_per_user[auth_user] = 0 if auth_user in self._stop_timer_per_user: - self.clock.cancel_call_later( - self._stop_timer_per_user.pop(auth_user)) + try: + self.clock.cancel_call_later( + self._stop_timer_per_user.pop(auth_user) + ) + except: + logger.exception("Failed to cancel event timer") else: yield self.distributor.fire( "started_user_eventstream", auth_user @@ -95,10 +99,12 @@ class EventStreamHandler(BaseHandler): logger.debug( "_later stopped_user_eventstream %s", auth_user ) + + self._stop_timer_per_user.pop(auth_user, None) + yield self.distributor.fire( "stopped_user_eventstream", auth_user ) - del self._stop_timer_per_user[auth_user] logger.debug("Scheduling _later: for %s", auth_user) self._stop_timer_per_user[auth_user] = ( -- cgit 1.4.1 From b8849c8cbf7666688d26a0503ddd678fba56425c Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 13:53:31 +0000 Subject: Re-sign events when we return them via federation as a temporary hack to work around the problem where we reconstruct events differently than when they were signed --- synapse/handlers/federation.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'synapse') diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index fcef602055..7903494e08 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -540,6 +540,17 @@ class FederationHandler(BaseHandler): ) if event: + # FIXME: This is a temporary work around where we occasionally + # return events slightly differently than when they were + # originally signed + event.signatures.update( + compute_event_signature( + event, + self.hs.hostname, + self.hs.config.signing_key[0] + ) + ) + if do_auth: in_room = yield self.auth.check_host_in_room( event.room_id, -- cgit 1.4.1 From 07699b587144d9a9e92294f041db51f2a6621d59 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 14:31:43 +0000 Subject: Change the way we get missing auth and state events --- synapse/federation/replication.py | 73 +++++++++++++++++++++++-------------- synapse/handlers/federation.py | 77 +++++++++++++++++++++++++++++++-------- 2 files changed, 106 insertions(+), 44 deletions(-) (limited to 'synapse') diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 6bfb30b42d..312d69fcaa 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -281,6 +281,22 @@ class ReplicationLayer(object): defer.returnValue(pdus) + @defer.inlineCallbacks + @log_function + def get_event_auth(self, destination, context, event_id): + res = yield self.transport_layer.get_event_auth( + destination, context, event_id, + ) + + auth_chain = [ + self.event_from_pdu_json(p, outlier=True) + for p in res["auth_chain"] + ] + + auth_chain.sort(key=lambda e: e.depth) + + defer.returnValue(auth_chain) + @defer.inlineCallbacks @log_function def on_backfill_request(self, origin, context, versions, limit): @@ -549,34 +565,34 @@ class ReplicationLayer(object): state = None # We need to make sure we have all the auth events. - for e_id, _ in pdu.auth_events: - exists = yield self._get_persisted_pdu( - origin, - e_id, - do_auth=False - ) - - if not exists: - try: - logger.debug( - "_handle_new_pdu fetch missing auth event %s from %s", - e_id, - origin, - ) - - yield self.get_pdu( - origin, - event_id=e_id, - outlier=True, - ) - - logger.debug("Processed pdu %s", e_id) - except: - logger.warn( - "Failed to get auth event %s from %s", - e_id, - origin - ) + # for e_id, _ in pdu.auth_events: + # exists = yield self._get_persisted_pdu( + # origin, + # e_id, + # do_auth=False + # ) + # + # if not exists: + # try: + # logger.debug( + # "_handle_new_pdu fetch missing auth event %s from %s", + # e_id, + # origin, + # ) + # + # yield self.get_pdu( + # origin, + # event_id=e_id, + # outlier=True, + # ) + # + # logger.debug("Processed pdu %s", e_id) + # except: + # logger.warn( + # "Failed to get auth event %s from %s", + # e_id, + # origin + # ) # Get missing pdus if necessary. if not pdu.outlier: @@ -626,6 +642,7 @@ class ReplicationLayer(object): if not backfilled: ret = yield self.handler.on_receive_pdu( + origin, pdu, backfilled=backfilled, state=state, diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 7903494e08..0863fdb13e 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -101,7 +101,7 @@ class FederationHandler(BaseHandler): @log_function @defer.inlineCallbacks - def on_receive_pdu(self, pdu, backfilled, state=None): + def on_receive_pdu(self, origin, pdu, backfilled, state=None): """ Called by the ReplicationLayer when we have a new pdu. We need to do auth checks and put it through the StateHandler. """ @@ -149,14 +149,47 @@ class FederationHandler(BaseHandler): # FIXME (erikj): Awful hack to make the case where we are not currently # in the room work current_state = None - if state: - is_in_room = yield self.auth.check_host_in_room( - event.room_id, - self.server_name + is_in_room = yield self.auth.check_host_in_room( + event.room_id, + self.server_name + ) + if not is_in_room: + logger.debug("Got event for room we're not in.") + + replication_layer = self.replication_layer + auth_chain = yield replication_layer.get_event_auth( + origin, + context=event.room_id, + event_id=event.event_id, + ) + + current_state = yield replication_layer.get_state_for_context( + origin, + context=event.room_id, + event_id=event.event_id, ) - if not is_in_room: - logger.debug("Got event for room we're not in.") - current_state = state + + for e in auth_chain: + e.outlier = True + try: + yield self._handle_new_event(e) + yield self.notifier.on_new_room_event(e) + except: + logger.exception( + "Failed to parse auth event %s", + e.event_id, + ) + + for e in current_state: + e.outlier = True + try: + yield self._handle_new_event(e) + yield self.notifier.on_new_room_event(e) + except: + logger.exception( + "Failed to parse state event %s", + e.event_id, + ) try: yield self._handle_new_event( @@ -328,18 +361,30 @@ class FederationHandler(BaseHandler): for e in auth_chain: e.outlier = True - yield self._handle_new_event(e) - yield self.notifier.on_new_room_event( - e, extra_users=[joinee] - ) + try: + yield self._handle_new_event(e) + yield self.notifier.on_new_room_event( + e, extra_users=[joinee] + ) + except: + logger.exception( + "Failed to parse auth event %s", + e.event_id, + ) for e in state: # FIXME: Auth these. e.outlier = True - yield self._handle_new_event(e) - yield self.notifier.on_new_room_event( - e, extra_users=[joinee] - ) + try: + yield self._handle_new_event(e) + yield self.notifier.on_new_room_event( + e, extra_users=[joinee] + ) + except: + logger.exception( + "Failed to parse state event %s", + e.event_id, + ) yield self._handle_new_event( event, -- cgit 1.4.1 From 0294fba0429a789c87f359f58218e2183ef69d96 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 14:46:33 +0000 Subject: on_receive_pdu takes more args --- synapse/handlers/federation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'synapse') diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 0863fdb13e..27ecd35b4b 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -112,7 +112,7 @@ class FederationHandler(BaseHandler): # If we are currently in the process of joining this room, then we # queue up events for later processing. if event.room_id in self.room_queues: - self.room_queues[event.room_id].append(pdu) + self.room_queues[event.room_id].append((pdu, origin)) return logger.debug("Processing event: %s", event.event_id) @@ -401,9 +401,9 @@ class FederationHandler(BaseHandler): room_queue = self.room_queues[room_id] del self.room_queues[room_id] - for p in room_queue: + for p, origin in room_queue: try: - self.on_receive_pdu(p, backfilled=False) + self.on_receive_pdu(origin, p, backfilled=False) except: logger.exception("Couldn't handle pdu") -- cgit 1.4.1 From 027542e2e5daa94c6517c0283be40834773fb475 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 16:02:26 +0000 Subject: Fix bugs when joining a remote room that has dodgy event graphs. This should also fix the number of times a HS will trigger a GET /event/ --- synapse/api/auth.py | 10 ++++- synapse/handlers/federation.py | 83 ++++++++++++++++++++++++++------------- tests/handlers/test_federation.py | 6 ++- 3 files changed, 68 insertions(+), 31 deletions(-) (limited to 'synapse') diff --git a/synapse/api/auth.py b/synapse/api/auth.py index fb911e51a6..2b0475543d 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -202,7 +202,10 @@ class Auth(object): # Invites are valid iff caller is in the room and target isn't. if not caller_in_room: # caller isn't joined - raise AuthError(403, "You are not in room %s." % event.room_id) + raise AuthError( + 403, + "%s not in room %s." % (event.user_id, event.room_id,) + ) elif target_in_room: # the target is already in the room. raise AuthError(403, "%s is already in the room." % target_user_id) @@ -225,7 +228,10 @@ class Auth(object): # TODO (erikj): Implement kicks. if not caller_in_room: # trying to leave a room you aren't joined - raise AuthError(403, "You are not in room %s." % event.room_id) + raise AuthError( + 403, + "%s not in room %s." % (target_user_id, event.room_id,) + ) elif target_user_id != event.user_id: if kick_level: kick_level = int(kick_level) diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 27ecd35b4b..925eb5376e 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -153,7 +153,7 @@ class FederationHandler(BaseHandler): event.room_id, self.server_name ) - if not is_in_room: + if not is_in_room and not event.outlier: logger.debug("Got event for room we're not in.") replication_layer = self.replication_layer @@ -163,28 +163,30 @@ class FederationHandler(BaseHandler): event_id=event.event_id, ) - current_state = yield replication_layer.get_state_for_context( - origin, - context=event.room_id, - event_id=event.event_id, - ) - for e in auth_chain: e.outlier = True try: - yield self._handle_new_event(e) - yield self.notifier.on_new_room_event(e) + yield self._handle_new_event(e, fetch_missing=False) except: logger.exception( "Failed to parse auth event %s", e.event_id, ) - for e in current_state: + if not state: + state = yield replication_layer.get_state_for_context( + origin, + context=event.room_id, + event_id=event.event_id, + ) + + current_state = state + + if state: + for e in state: e.outlier = True try: yield self._handle_new_event(e) - yield self.notifier.on_new_room_event(e) except: logger.exception( "Failed to parse state event %s", @@ -284,6 +286,16 @@ class FederationHandler(BaseHandler): @defer.inlineCallbacks def on_event_auth(self, event_id): auth = yield self.store.get_auth_chain(event_id) + + for event in auth: + event.signatures.update( + compute_event_signature( + event, + self.hs.hostname, + self.hs.config.signing_key[0] + ) + ) + defer.returnValue([e for e in auth]) @log_function @@ -343,6 +355,7 @@ class FederationHandler(BaseHandler): state = ret["state"] auth_chain = ret["auth_chain"] + auth_chain.sort(key=lambda e: e.depth) logger.debug("do_invite_join auth_chain: %s", auth_chain) logger.debug("do_invite_join state: %s", state) @@ -362,10 +375,7 @@ class FederationHandler(BaseHandler): for e in auth_chain: e.outlier = True try: - yield self._handle_new_event(e) - yield self.notifier.on_new_room_event( - e, extra_users=[joinee] - ) + yield self._handle_new_event(e, fetch_missing=False) except: logger.exception( "Failed to parse auth event %s", @@ -376,9 +386,9 @@ class FederationHandler(BaseHandler): # FIXME: Auth these. e.outlier = True try: - yield self._handle_new_event(e) - yield self.notifier.on_new_room_event( - e, extra_users=[joinee] + yield self._handle_new_event( + e, + fetch_missing=True ) except: logger.exception( @@ -389,7 +399,7 @@ class FederationHandler(BaseHandler): yield self._handle_new_event( event, state=state, - current_state=state + current_state=state, ) yield self.notifier.on_new_room_event( @@ -552,7 +562,17 @@ class FederationHandler(BaseHandler): else: del results[(event.type, event.state_key)] - defer.returnValue(results.values()) + res = results.values() + for event in res: + event.signatures.update( + compute_event_signature( + event, + self.hs.hostname, + self.hs.config.signing_key[0] + ) + ) + + defer.returnValue(res) else: defer.returnValue([]) @@ -623,11 +643,7 @@ class FederationHandler(BaseHandler): @defer.inlineCallbacks def _handle_new_event(self, event, state=None, backfilled=False, - current_state=None): - if state: - for s in state: - yield self._handle_new_event(s) - + current_state=None, fetch_missing=True): is_new_state = yield self.state_handler.annotate_event_with_state( event, old_state=state @@ -667,11 +683,22 @@ class FederationHandler(BaseHandler): ) if not e: - raise AuthError( - 403, - "Can't find auth event %s." % (e_id, ) + e = yield self.replication_layer.get_pdu( + event.origin, e_id, outlier=True ) + if e and fetch_missing: + try: + yield self.on_receive_pdu(event.origin, e, False) + except: + logger.exception( + "Failed to parse auth event %s", + e_id, + ) + + if not e: + logger.warn("Can't find auth event %s.", e_id) + auth_events[(e.type, e.state_key)] = e if event.type == RoomMemberEvent.TYPE and not event.auth_events: diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index 98cfbe50b3..33016c16ef 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -42,6 +42,7 @@ class FederationTestCase(unittest.TestCase): self.auth = NonCallableMock(spec_set=[ "check", + "check_host_in_room", ]) self.hostname = "test" @@ -89,13 +90,16 @@ class FederationTestCase(unittest.TestCase): self.datastore.persist_event.return_value = defer.succeed(None) self.datastore.get_room.return_value = defer.succeed(True) + self.auth.check_host_in_room.return_value = defer.succeed(True) def annotate(ev, old_state=None): ev.old_state_events = [] return defer.succeed(False) self.state_handler.annotate_event_with_state.side_effect = annotate - yield self.handlers.federation_handler.on_receive_pdu(pdu, False) + yield self.handlers.federation_handler.on_receive_pdu( + "fo", pdu, False + ) self.datastore.persist_event.assert_called_once_with( ANY, is_new_state=False, backfilled=False, current_state=None -- cgit 1.4.1 From 1505055334ecff6516c0b388efe4c5759e59fad0 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 16:38:50 +0000 Subject: Don't return outliers when we get recent events for rooms. --- synapse/storage/stream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'synapse') diff --git a/synapse/storage/stream.py b/synapse/storage/stream.py index b84735e61c..3405cb365e 100644 --- a/synapse/storage/stream.py +++ b/synapse/storage/stream.py @@ -283,7 +283,7 @@ class StreamStore(SQLBaseStore): sql = ( "SELECT *, (%(redacted)s) AS redacted FROM events " - "WHERE room_id = ? AND stream_ordering <= ? " + "WHERE room_id = ? AND stream_ordering <= ? AND outlier = 0 " "ORDER BY topological_ordering DESC, stream_ordering DESC LIMIT ? " ) % { "redacted": del_sql, -- cgit 1.4.1 From cce32f8dc54cfbda5670c91d36477faedd3b9cc9 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 17:15:32 +0000 Subject: Bump version and changelog --- CHANGES.rst | 8 ++++++++ VERSION | 2 +- synapse/__init__.py | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'synapse') diff --git a/CHANGES.rst b/CHANGES.rst index 207f1e4d74..6779a36f72 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,11 @@ +Changes in synapse 0.5.3 (2014-11-27) +===================================== + + * Fix bug that caused joining a remote room to fail if a single event was not + signed correctly. + * Fix bug which caused servers to continuously try and fetch events from other + servers. + Changes in synapse 0.5.2 (2014-11-26) ===================================== diff --git a/VERSION b/VERSION index cb0c939a93..be14282b7f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.2 +0.5.3 diff --git a/synapse/__init__.py b/synapse/__init__.py index d5c2f25484..c99cd96537 100644 --- a/synapse/__init__.py +++ b/synapse/__init__.py @@ -16,4 +16,4 @@ """ This is a reference implementation of a synapse home server. """ -__version__ = "0.5.2" +__version__ = "0.5.3" -- cgit 1.4.1 From ab74afdd8d32402c0b89eb2db7413ce00be84e89 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 27 Nov 2014 17:30:08 +0000 Subject: Bump version --- VERSION | 2 +- synapse/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'synapse') diff --git a/VERSION b/VERSION index be14282b7f..dc74c5626d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.3 +0.5.3a diff --git a/synapse/__init__.py b/synapse/__init__.py index c99cd96537..658574dab9 100644 --- a/synapse/__init__.py +++ b/synapse/__init__.py @@ -16,4 +16,4 @@ """ This is a reference implementation of a synapse home server. """ -__version__ = "0.5.3" +__version__ = "0.5.3a" -- cgit 1.4.1