summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
Diffstat (limited to 'synapse')
-rw-r--r--synapse/handlers/room.py128
1 files changed, 60 insertions, 68 deletions
diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index b7ea321a9b..d4bb21e69e 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -482,9 +482,9 @@ class RoomMemberHandler(BaseHandler):
         Raises:
             SynapseError if there was a problem changing the membership.
         """
-        if from_client:
-            user = UserID.from_string(event.sender)
+        user = UserID.from_string(event.sender)
 
+        if from_client:
             assert self.hs.is_mine(user), "User must be our own: %s" % (user,)
 
         if event.is_state():
@@ -502,81 +502,59 @@ class RoomMemberHandler(BaseHandler):
 
         room_id = event.room_id
 
+        handled = False
+
         if event.membership == Membership.JOIN:
             if is_guest and not self._can_guest_join(context.current_state):
                 # This should be an auth check, but guests are a local concept,
                 # so don't really fit into the general auth process.
                 raise AuthError(403, "Guest access not allowed")
 
-            # If we're trying to join a room then we have to do this differently
-            # if this HS is not currently in the room, i.e. we have to do the
-            # invite/join dance.
-
-            # XXX: We don't do an auth check if we are doing an invite
-            # join dance for now, since we're kinda implicitly checking
-            # that we are allowed to join when we decide whether or not we
-            # need to do the invite/join dance.
+            should_do_dance, room_hosts = yield self._should_do_dance(
+                room_id,
+                context,
+                (yield self.get_inviter(target_user.to_string(), room_id)),
+                room_hosts,
+            )
 
-            is_host_in_room = yield self.is_host_in_room(room_id, context)
-            if is_host_in_room:
-                should_do_dance = False
-            elif room_hosts:  # TODO: Shouldn't this be remote_room_host?
-                should_do_dance = True
-            else:
-                inviter = yield self.get_inviter(event)
-                if not inviter:
+            if should_do_dance:
+                if len(room_hosts) == 0:
                     # return the same error as join_room_alias does
                     raise SynapseError(404, "No known servers")
-                should_do_dance = not self.hs.is_mine(inviter)
-                room_hosts = [inviter.domain]
 
-            if should_do_dance:
-                handler = self.hs.get_handlers().federation_handler
-                yield handler.do_invite_join(
+                # We don't do an auth check if we are doing an invite
+                # join dance for now, since we're kinda implicitly checking
+                # that we are allowed to join when we decide whether or not we
+                # need to do the invite/join dance.
+                yield self.hs.get_handlers().federation_handler.do_invite_join(
                     room_hosts,
                     room_id,
                     event.user_id,
                     event.content,
                 )
-            else:
-                logger.debug("Doing normal join")
-
-                yield self.handle_new_client_event(
-                    event,
-                    context,
-                    extra_users=[target_user],
-                    ratelimit=ratelimit,
+                handled = True
+        if event.membership == Membership.LEAVE:
+            is_host_in_room = yield self.is_host_in_room(room_id, context)
+            if not is_host_in_room:
+                # Rejecting an invite, rather than leaving a joined room
+                handler = self.hs.get_handlers().federation_handler
+                inviter = yield self.get_inviter(target_user.to_string(), room_id)
+                if not inviter:
+                    # return the same error as join_room_alias does
+                    raise SynapseError(404, "No known servers")
+                yield handler.do_remotely_reject_invite(
+                    [inviter.domain],
+                    room_id,
+                    event.user_id
                 )
-
-            prev_state = context.current_state.get((event.type, event.state_key))
-            if not prev_state or prev_state.membership != Membership.JOIN:
-                # Only fire user_joined_room if the user has acutally joined the
-                # room. Don't bother if the user is just changing their profile
-                # info.
-                user = UserID.from_string(event.user_id)
-                yield user_joined_room(self.distributor, user, room_id)
-        else:
-            if event.membership == Membership.LEAVE:
-                is_host_in_room = yield self.is_host_in_room(room_id, context)
-                if not is_host_in_room:
-                    # Rejecting an invite, rather than leaving a joined room
-                    handler = self.hs.get_handlers().federation_handler
-                    inviter = yield self.get_inviter(event)
-                    if not inviter:
-                        # return the same error as join_room_alias does
-                        raise SynapseError(404, "No known servers")
-                    yield handler.do_remotely_reject_invite(
-                        [inviter.domain],
-                        room_id,
-                        event.user_id
-                    )
-                    return
+                handled = True
 
             # FIXME: This isn't idempotency.
             if prev_state and prev_state.membership == event.membership:
                 # double same action, treat this event as a NOOP.
                 return
 
+        if not handled:
             yield self.handle_new_client_event(
                 event,
                 context,
@@ -584,9 +562,15 @@ class RoomMemberHandler(BaseHandler):
                 ratelimit=ratelimit,
             )
 
+        if event.membership == Membership.JOIN:
+            if not prev_state or prev_state.membership != Membership.JOIN:
+                # Only fire user_joined_room if the user has acutally joined the
+                # room. Don't bother if the user is just changing their profile
+                # info.
+                yield user_joined_room(self.distributor, target_user, room_id)
+        elif event.membership == Membership.LEAVE:
             if prev_state and prev_state.membership == Membership.JOIN:
-                user = UserID.from_string(event.user_id)
-                user_left_room(self.distributor, user, event.room_id)
+                user_left_room(self.distributor, target_user, room_id)
 
     def _can_guest_join(self, current_state):
         """
@@ -601,6 +585,21 @@ class RoomMemberHandler(BaseHandler):
         )
 
     @defer.inlineCallbacks
+    def _should_do_dance(self, room_id, context, inviter, room_hosts=None):
+        # TODO: Shouldn't this be remote_room_host?
+        room_hosts = room_hosts or []
+
+        # TODO(danielwh): This shouldn't need to yield for this check, we have a context.
+        is_host_in_room = yield self.is_host_in_room(room_id, context)
+        if is_host_in_room:
+            defer.returnValue((False, room_hosts))
+
+        if inviter and not self.hs.is_mine(inviter):
+            room_hosts.append(inviter.domain)
+
+        defer.returnValue((True, room_hosts))
+
+    @defer.inlineCallbacks
     def lookup_room_alias(self, room_alias):
         """
         Get the room ID associated with a room alias.
@@ -625,24 +624,17 @@ class RoomMemberHandler(BaseHandler):
 
         defer.returnValue((RoomID.from_string(room_id), hosts))
 
+    # TODO(danielwh): This should use the context, rather than looking up the store.
     @defer.inlineCallbacks
-    def get_inviter(self, event):
+    def get_inviter(self, user_id, room_id):
         # TODO(markjh): get prev_state from snapshot
         prev_state = yield self.store.get_room_member(
-            event.user_id, event.room_id
+            user_id, room_id
         )
-
         if prev_state and prev_state.membership == Membership.INVITE:
             defer.returnValue(UserID.from_string(prev_state.user_id))
-            return
-        elif "third_party_invite" in event.content:
-            if "sender" in event.content["third_party_invite"]:
-                inviter = UserID.from_string(
-                    event.content["third_party_invite"]["sender"]
-                )
-                defer.returnValue(inviter)
-        defer.returnValue(None)
 
+    # TODO(danielwh): This looks insane. Please make it not insane.
     @defer.inlineCallbacks
     def is_host_in_room(self, room_id, context):
         is_host_in_room = yield self.auth.check_host_in_room(