Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Ignore incoming events for rooms that we have left #2490

Merged
merged 5 commits into from Oct 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions synapse/handlers/federation.py
Expand Up @@ -125,6 +125,28 @@ def on_receive_pdu(self, origin, pdu, get_missing=True):
self.room_queues[pdu.room_id].append((pdu, origin))
return

# If we're no longer in the room just ditch the event entirely. This
# is probably an old server that has come back and thinks we're still
# in the room (or we've been rejoined to the room by a state reset).
#
# If we were never in the room then maybe our database got vaped and
# we should check if we *are* in fact in the room. If we are then we
# can magically rejoin the room.
is_in_room = yield self.auth.check_host_in_room(
pdu.room_id,
self.server_name
)
if not is_in_room:
was_in_room = yield self.store.was_host_joined(
pdu.room_id, self.server_name,
)
if was_in_room:
logger.info(
"Ignoring PDU %s for room %s from %s as we've left the room!",
pdu.event_id, pdu.room_id, origin,
)
return

state = None

auth_chain = []
Expand Down
3 changes: 3 additions & 0 deletions synapse/storage/events.py
Expand Up @@ -784,6 +784,9 @@ def _update_current_state_txn(self, txn, state_delta_by_room, max_stream_order):
self._invalidate_cache_and_stream(
txn, self.is_host_joined, (room_id, host)
)
self._invalidate_cache_and_stream(
txn, self.was_host_joined, (room_id, host)
)

self._invalidate_cache_and_stream(
txn, self.get_users_in_room, (room_id,)
Expand Down
40 changes: 40 additions & 0 deletions synapse/storage/roommember.py
Expand Up @@ -533,6 +533,46 @@ def is_host_joined(self, room_id, host):

defer.returnValue(True)

@cachedInlineCallbacks()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

erm; do we not need to arrange for this cache to be flushed?

def was_host_joined(self, room_id, host):
"""Check whether the server is or ever was in the room.

Args:
room_id (str)
host (str)

Returns:
Deferred: Resolves to True if the host is/was in the room, otherwise
False.
"""
if '%' in host or '_' in host:
raise Exception("Invalid host name")

sql = """
SELECT user_id FROM room_memberships
WHERE room_id = ?
AND user_id LIKE ?
AND membership = 'join'
LIMIT 1
"""

# We do need to be careful to ensure that host doesn't have any wild cards
# in it, but we checked above for known ones and we'll check below that
# the returned user actually has the correct domain.
like_clause = "%:" + host

rows = yield self._execute("was_host_joined", None, sql, room_id, like_clause)

if not rows:
defer.returnValue(False)

user_id = rows[0][0]
if get_domain_from_id(user_id) != host:
# This can only happen if the host name has something funky in it
raise Exception("Invalid host name")

defer.returnValue(True)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is almost an exact copy of is_host_joined above.

def get_joined_hosts(self, room_id, state_entry):
state_group = state_entry.state_group
if not state_group:
Expand Down