From 4eca8d3fb3d906b1bc5be6c8d4b98cf555e154b7 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 18 Mar 2019 10:16:19 +0000 Subject: [PATCH] Add invite_list and cloning param to create room rule --- synapse/events/spamcheck.py | 21 ++++++++++++++----- synapse/handlers/federation.py | 2 +- synapse/handlers/room.py | 17 +++++++++++++--- synapse/handlers/room_member.py | 26 ++++++++++++++++++++++++ synapse/rulecheck/domain_rule_checker.py | 5 +++-- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py index 633e068eb8..aa559e1f50 100644 --- a/synapse/events/spamcheck.py +++ b/synapse/events/spamcheck.py @@ -46,13 +46,18 @@ class SpamChecker(object): return self.spam_checker.check_event_for_spam(event) - def user_may_invite(self, inviter_userid, invitee_userid, room_id): + def user_may_invite(self, inviter_userid, invitee_userid, room_id, new_room): """Checks if a given user may send an invite If this method returns false, the invite will be rejected. Args: - userid (string): The sender's user ID + inviter_userid (str) + invitee_userid (str) + room_id (str) + new_room (bool): Wether the user is being invited to the room as + part of a room creation, if so the invitee would have been + included in the call to `user_may_create_room`. Returns: bool: True if the user may send an invite, otherwise False @@ -60,15 +65,21 @@ class SpamChecker(object): if self.spam_checker is None: return True - return self.spam_checker.user_may_invite(inviter_userid, invitee_userid, room_id) + return self.spam_checker.user_may_invite( + inviter_userid, invitee_userid, room_id, new_room, + ) - def user_may_create_room(self, userid): + def user_may_create_room(self, userid, invite_list, cloning): """Checks if a given user may create a room If this method returns false, the creation request will be rejected. Args: userid (string): The sender's user ID + invite_list (list[str]): List of user IDs that would be invited to + the new room. + cloning (bool): Whether the user is cloning an existing room, e.g. + upgrading a room. Returns: bool: True if the user may create a room, otherwise False @@ -76,7 +87,7 @@ class SpamChecker(object): if self.spam_checker is None: return True - return self.spam_checker.user_may_create_room(userid) + return self.spam_checker.user_may_create_room(userid, invite_list, cloning) def user_may_create_room_alias(self, userid, room_alias): """Checks if a given user may create a room alias diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index f80486102a..a222d67190 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -1299,7 +1299,7 @@ class FederationHandler(BaseHandler): raise SynapseError(403, "This server does not accept room invites") if not self.spam_checker.user_may_invite( - event.sender, event.state_key, event.room_id, + event.sender, event.state_key, event.room_id, new_room=False, ): raise SynapseError( 403, "This user is not permitted to send invites to this server/user" diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index eb4b437ce8..2d42a41134 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -254,7 +254,11 @@ class RoomCreationHandler(BaseHandler): """ user_id = requester.user.to_string() - if not self.spam_checker.user_may_create_room(user_id): + if not self.spam_checker.user_may_create_room( + user_id, + invite_list=[], + cloning=True, + ): raise SynapseError(403, "You are not permitted to create rooms") creation_content = { @@ -475,7 +479,13 @@ class RoomCreationHandler(BaseHandler): yield self.auth.check_auth_blocking(user_id) - if not self.spam_checker.user_may_create_room(user_id): + invite_list = config.get("invite", []) + + if not self.spam_checker.user_may_create_room( + user_id, + invite_list=invite_list, + cloning=False, + ): raise SynapseError(403, "You are not permitted to create rooms") if ratelimit: @@ -518,7 +528,6 @@ class RoomCreationHandler(BaseHandler): else: room_alias = None - invite_list = config.get("invite", []) for i in invite_list: try: UserID.from_string(i) @@ -615,6 +624,7 @@ class RoomCreationHandler(BaseHandler): "invite", ratelimit=False, content=content, + new_room=True, ) for invite_3pid in invite_3pid_list: @@ -699,6 +709,7 @@ class RoomCreationHandler(BaseHandler): "join", ratelimit=False, content=creator_join_profile, + new_room=True, ) # We treat the power levels override specially as this needs to be one diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index 190ea2c7b1..1bf500776a 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -301,7 +301,30 @@ class RoomMemberHandler(object): third_party_signed=None, ratelimit=True, content=None, + new_room=False, ): + """Update a users membership in a room + + Args: + requester (Requester) + target (UserID) + room_id (str) + action (str): The "action" the requester is performing against the + target. One of join/leave/kick/ban/invite/unban. + txn_id (str|None): The transaction ID associated with the request, + or None not provided. + remote_room_hosts (list[str]|None): List of remote servers to try + and join via if server isn't already in the room. + third_party_signed (dict|None): The signed object for third party + invites. + ratelimit (bool): Whether to apply ratelimiting to this request. + content (dict|None): Fields to include in the new events content. + new_room (bool): Whether these membership changes are happening + as part of a room creation (e.g. initial joins and invites) + + Returns: + Deferred[FrozenEvent] + """ key = (room_id,) with (yield self.member_linearizer.queue(key)): @@ -315,6 +338,7 @@ class RoomMemberHandler(object): third_party_signed=third_party_signed, ratelimit=ratelimit, content=content, + new_room=new_room, ) defer.returnValue(result) @@ -331,6 +355,7 @@ class RoomMemberHandler(object): third_party_signed=None, ratelimit=True, content=None, + new_room=False, ): content_specified = bool(content) if content is None: @@ -392,6 +417,7 @@ class RoomMemberHandler(object): if not self.spam_checker.user_may_invite( requester.user.to_string(), target.to_string(), room_id, + new_room=new_room, ): logger.info("Blocking invite due to spam checker") block_invite = True diff --git a/synapse/rulecheck/domain_rule_checker.py b/synapse/rulecheck/domain_rule_checker.py index 3caa6b34cb..ed56f16c6f 100644 --- a/synapse/rulecheck/domain_rule_checker.py +++ b/synapse/rulecheck/domain_rule_checker.py @@ -48,7 +48,8 @@ class DomainRuleChecker(object): """ return False - def user_may_invite(self, inviter_userid, invitee_userid, room_id): + def user_may_invite(self, inviter_userid, invitee_userid, room_id, + new_room): """Implements synapse.events.SpamChecker.user_may_invite """ inviter_domain = self._get_domain_from_id(inviter_userid) @@ -59,7 +60,7 @@ class DomainRuleChecker(object): return invitee_domain in self.domain_mapping[inviter_domain] - def user_may_create_room(self, userid): + def user_may_create_room(self, userid, invite_list, cloning): """Implements synapse.events.SpamChecker.user_may_create_room """ return True