diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py
index 064e8723c8..a516a84a66 100644
--- a/synapse/handlers/_base.py
+++ b/synapse/handlers/_base.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
from synapse.api.errors import LimitExceededError, SynapseError, AuthError
from synapse.crypto.event_signing import add_hashes_and_signatures
from synapse.api.constants import Membership, EventTypes
-from synapse.types import UserID, RoomAlias
+from synapse.types import UserID, RoomAlias, Requester
from synapse.push.action_generator import ActionGenerator
from synapse.util.logcontext import PreserveLoggingContext
@@ -147,7 +147,7 @@ class BaseHandler(object):
@defer.inlineCallbacks
def _create_new_client_event(self, builder):
- latest_ret = yield self.store.get_latest_events_in_room(
+ latest_ret = yield self.store.get_latest_event_ids_and_hashes_in_room(
builder.room_id,
)
@@ -156,7 +156,10 @@ class BaseHandler(object):
else:
depth = 1
- prev_events = [(e, h) for e, h, _ in latest_ret]
+ prev_events = [
+ (event_id, prev_hashes)
+ for event_id, prev_hashes, _ in latest_ret
+ ]
builder.prev_events = prev_events
builder.depth = depth
@@ -165,6 +168,31 @@ class BaseHandler(object):
context = yield state_handler.compute_event_context(builder)
+ # If we've received an invite over federation, there are no latest
+ # events in the room, because we don't know enough about the graph
+ # fragment we received to treat it like a graph, so the above returned
+ # no relevant events. It may have returned some events (if we have
+ # joined and left the room), but not useful ones, like the invite. So we
+ # forcibly set our context to the invite we received over federation.
+ if (
+ not self.is_host_in_room(context.current_state) and
+ builder.type == EventTypes.Member
+ ):
+ prev_member_event = yield self.store.get_room_member(
+ builder.sender, builder.room_id
+ )
+ if prev_member_event:
+ builder.prev_events = (
+ prev_member_event.event_id,
+ prev_member_event.prev_events
+ )
+
+ context = yield state_handler.compute_event_context(
+ builder,
+ old_state=(prev_member_event,),
+ outlier=True
+ )
+
if builder.is_state():
builder.prev_state = yield self.store.add_event_hashes(
context.prev_state_events
@@ -187,10 +215,33 @@ class BaseHandler(object):
(event, context,)
)
+ def is_host_in_room(self, current_state):
+ room_members = [
+ (state_key, event.membership)
+ for ((event_type, state_key), event) in current_state.items()
+ if event_type == EventTypes.Member
+ ]
+ if len(room_members) == 0:
+ # Have we just created the room, and is this about to be the very
+ # first member event?
+ create_event = current_state.get(("m.room.create", ""))
+ if create_event:
+ return True
+ for (state_key, membership) in room_members:
+ if (
+ UserID.from_string(state_key).domain == self.hs.hostname
+ and membership == Membership.JOIN
+ ):
+ return True
+ return False
+
@defer.inlineCallbacks
- def handle_new_client_event(self, event, context, extra_users=[]):
+ def handle_new_client_event(self, event, context, ratelimit=True, extra_users=[]):
# We now need to go and hit out to wherever we need to hit out to.
+ if ratelimit:
+ self.ratelimit(event.sender)
+
self.auth.check(event, auth_events=context.current_state)
yield self.maybe_kick_guest_users(event, context.current_state.values())
@@ -316,7 +367,8 @@ class BaseHandler(object):
if member_event.type != EventTypes.Member:
continue
- if not self.hs.is_mine(UserID.from_string(member_event.state_key)):
+ target_user = UserID.from_string(member_event.state_key)
+ if not self.hs.is_mine(target_user):
continue
if member_event.content["membership"] not in {
@@ -338,18 +390,13 @@ class BaseHandler(object):
# and having homeservers have their own users leave keeps more
# of that decision-making and control local to the guest-having
# homeserver.
- message_handler = self.hs.get_handlers().message_handler
- yield message_handler.create_and_send_event(
- {
- "type": EventTypes.Member,
- "state_key": member_event.state_key,
- "content": {
- "membership": Membership.LEAVE,
- "kind": "guest"
- },
- "room_id": member_event.room_id,
- "sender": member_event.state_key
- },
+ requester = Requester(target_user, "", True)
+ handler = self.hs.get_handlers().room_member_handler
+ yield handler.update_membership(
+ requester,
+ target_user,
+ member_event.room_id,
+ "leave",
ratelimit=False,
)
except Exception as e:
|