diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 8e3c86d3a7..722dadde77 100644
--- a/synapse/handlers/room.py
+++ b/synapse/handlers/room.py
@@ -24,7 +24,6 @@ from synapse.api.constants import (
)
from synapse.api.errors import AuthError, StoreError, SynapseError, Codes
from synapse.util import stringutils, unwrapFirstError
-from synapse.util.async import run_on_reactor
from synapse.util.logcontext import preserve_context_over_fn
from signedjson.sign import verify_signed_json
@@ -42,10 +41,6 @@ logger = logging.getLogger(__name__)
id_server_scheme = "https://"
-def collect_presencelike_data(distributor, user, content):
- return distributor.fire("collect_presencelike_data", user, content)
-
-
def user_left_room(distributor, user, room_id):
return preserve_context_over_fn(
distributor.fire,
@@ -184,13 +179,24 @@ class RoomCreationHandler(BaseHandler):
)
msg_handler = self.hs.get_handlers().message_handler
+ room_member_handler = self.hs.get_handlers().room_member_handler
for event in creation_events:
- yield msg_handler.create_and_send_event(event, ratelimit=False)
+ if event["type"] == EventTypes.Member:
+ # TODO(danielwh): This is hideous
+ yield room_member_handler.update_membership(
+ requester,
+ user,
+ room_id,
+ "join",
+ ratelimit=False,
+ )
+ else:
+ yield msg_handler.create_and_send_nonmember_event(event, ratelimit=False)
if "name" in config:
name = config["name"]
- yield msg_handler.create_and_send_event({
+ yield msg_handler.create_and_send_nonmember_event({
"type": EventTypes.Name,
"room_id": room_id,
"sender": user_id,
@@ -200,7 +206,7 @@ class RoomCreationHandler(BaseHandler):
if "topic" in config:
topic = config["topic"]
- yield msg_handler.create_and_send_event({
+ yield msg_handler.create_and_send_nonmember_event({
"type": EventTypes.Topic,
"room_id": room_id,
"sender": user_id,
@@ -209,13 +215,13 @@ class RoomCreationHandler(BaseHandler):
}, ratelimit=False)
for invitee in invite_list:
- yield msg_handler.create_and_send_event({
- "type": EventTypes.Member,
- "state_key": invitee,
- "room_id": room_id,
- "sender": user_id,
- "content": {"membership": Membership.INVITE},
- }, ratelimit=False)
+ room_member_handler.update_membership(
+ requester,
+ UserID.from_string(invitee),
+ room_id,
+ "invite",
+ ratelimit=False,
+ )
for invite_3pid in invite_3pid_list:
id_server = invite_3pid["id_server"]
@@ -227,7 +233,7 @@ class RoomCreationHandler(BaseHandler):
medium,
address,
id_server,
- token_id=None,
+ requester,
txn_id=None,
)
@@ -392,7 +398,16 @@ class RoomMemberHandler(BaseHandler):
remotedomains.add(member.domain)
@defer.inlineCallbacks
- def update_membership(self, requester, target, room_id, action, txn_id=None):
+ def update_membership(
+ self,
+ requester,
+ target,
+ room_id,
+ action,
+ txn_id=None,
+ room_hosts=None,
+ ratelimit=True,
+ ):
effective_membership_state = action
if action in ["kick", "unban"]:
effective_membership_state = "leave"
@@ -401,7 +416,7 @@ class RoomMemberHandler(BaseHandler):
msg_handler = self.hs.get_handlers().message_handler
- content = {"membership": unicode(effective_membership_state)}
+ content = {"membership": effective_membership_state}
if requester.is_guest:
content["kind"] = "guest"
@@ -412,6 +427,9 @@ class RoomMemberHandler(BaseHandler):
"room_id": room_id,
"sender": requester.user.to_string(),
"state_key": target.to_string(),
+
+ # For backwards compatibility:
+ "membership": effective_membership_state,
},
token_id=requester.access_token_id,
txn_id=txn_id,
@@ -432,18 +450,23 @@ class RoomMemberHandler(BaseHandler):
errcode=Codes.BAD_STATE
)
- yield msg_handler.send_event(
+ member_handler = self.hs.get_handlers().room_member_handler
+ yield member_handler.send_membership_event(
event,
context,
- ratelimit=True,
- is_guest=requester.is_guest
+ is_guest=requester.is_guest,
+ ratelimit=ratelimit,
+ room_hosts=room_hosts,
+ from_client=True,
)
if action == "forget":
yield self.forget(requester.user, room_id)
@defer.inlineCallbacks
- def send_membership_event(self, event, context, is_guest=False):
+ def send_membership_event(
+ self, event, context, is_guest=False, room_hosts=None, ratelimit=True, from_client=True,
+ ):
""" Change the membership status of a user in a room.
Args:
@@ -451,7 +474,18 @@ class RoomMemberHandler(BaseHandler):
Raises:
SynapseError if there was a problem changing the membership.
"""
+ if from_client:
+ user = UserID.from_string(event.sender)
+
+ assert self.hs.is_mine(user), "User must be our own: %s" % (user,)
+
+ if event.is_state():
+ prev_state = self.hs.get_handlers().message_handler.deduplicate_state_event(event, context)
+ if prev_state is not None:
+ return
+
target_user_id = event.state_key
+ target_user = UserID.from_string(event.state_key)
prev_state = context.current_state.get(
(EventTypes.Member, target_user_id),
@@ -478,7 +512,51 @@ class RoomMemberHandler(BaseHandler):
if not is_guest_access_allowed:
raise AuthError(403, "Guest access not allowed")
- yield self._do_join(event, context)
+ room_id = event.room_id
+
+ # 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.
+
+ 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:
+ # 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(
+ 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,
+ )
+
+ 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)
@@ -494,28 +572,36 @@ class RoomMemberHandler(BaseHandler):
room_id,
event.user_id
)
- defer.returnValue({"room_id": room_id})
return
# FIXME: This isn't idempotency.
if prev_state and prev_state.membership == event.membership:
# double same action, treat this event as a NOOP.
- defer.returnValue({})
return
- yield self._do_local_membership_update(
+ yield self.handle_new_client_event(
event,
- context=context,
+ context,
+ extra_users=[target_user],
+ ratelimit=ratelimit,
)
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)
- defer.returnValue({"room_id": room_id})
-
@defer.inlineCallbacks
- def join_room_alias(self, joinee, room_alias, content={}):
+ def lookup_room_alias(self, room_alias):
+ """
+ Get the room ID associated with a room alias.
+
+ Args:
+ room_alias (RoomAlias): The alias to look up.
+ Returns:
+ The room ID as a RoomID object.
+ Raises:
+ SynapseError if room alias could not be found.
+ """
directory_handler = self.hs.get_handlers().directory_handler
mapping = yield directory_handler.get_association(room_alias)
@@ -527,69 +613,7 @@ class RoomMemberHandler(BaseHandler):
if not hosts:
raise SynapseError(404, "No known servers")
- # If event doesn't include a display name, add one.
- yield collect_presencelike_data(self.distributor, joinee, content)
-
- content.update({"membership": Membership.JOIN})
- builder = self.event_builder_factory.new({
- "type": EventTypes.Member,
- "state_key": joinee.to_string(),
- "room_id": room_id,
- "sender": joinee.to_string(),
- "membership": Membership.JOIN,
- "content": content,
- })
- event, context = yield self._create_new_client_event(builder)
-
- yield self._do_join(event, context, room_hosts=hosts)
-
- defer.returnValue({"room_id": room_id})
-
- @defer.inlineCallbacks
- def _do_join(self, event, context, room_hosts=None):
- room_id = event.room_id
-
- # 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.
-
- 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:
- # 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(
- room_hosts,
- room_id,
- event.user_id,
- event.content,
- )
- else:
- logger.debug("Doing normal join")
-
- yield self._do_local_membership_update(
- event,
- context=context,
- )
-
- 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)
+ defer.returnValue((RoomID.from_string(room_id), hosts))
@defer.inlineCallbacks
def get_inviter(self, event):
@@ -645,18 +669,6 @@ class RoomMemberHandler(BaseHandler):
defer.returnValue(room_ids)
@defer.inlineCallbacks
- def _do_local_membership_update(self, event, context):
- yield run_on_reactor()
-
- target_user = UserID.from_string(event.state_key)
-
- yield self.handle_new_client_event(
- event,
- context,
- extra_users=[target_user],
- )
-
- @defer.inlineCallbacks
def do_3pid_invite(
self,
room_id,
@@ -664,7 +676,7 @@ class RoomMemberHandler(BaseHandler):
medium,
address,
id_server,
- token_id,
+ requester,
txn_id
):
invitee = yield self._lookup_3pid(
@@ -672,19 +684,12 @@ class RoomMemberHandler(BaseHandler):
)
if invitee:
- # make sure it looks like a user ID; it'll throw if it's invalid.
- UserID.from_string(invitee)
- yield self.hs.get_handlers().message_handler.create_and_send_event(
- {
- "type": EventTypes.Member,
- "content": {
- "membership": unicode("invite")
- },
- "room_id": room_id,
- "sender": inviter.to_string(),
- "state_key": invitee,
- },
- token_id=token_id,
+ handler = self.hs.get_handlers().room_member_handler
+ yield handler.update_membership(
+ requester,
+ UserID.from_string(invitee),
+ room_id,
+ "invite",
txn_id=txn_id,
)
else:
@@ -694,7 +699,7 @@ class RoomMemberHandler(BaseHandler):
address,
room_id,
inviter,
- token_id,
+ requester.access_token_id,
txn_id=txn_id
)
@@ -805,7 +810,7 @@ class RoomMemberHandler(BaseHandler):
)
)
msg_handler = self.hs.get_handlers().message_handler
- yield msg_handler.create_and_send_event(
+ yield msg_handler.create_and_send_nonmember_event(
{
"type": EventTypes.ThirdPartyInvite,
"content": {
|