summary refs log tree commit diff
path: root/synapse/events/spamcheck.py
diff options
context:
space:
mode:
Diffstat (limited to 'synapse/events/spamcheck.py')
-rw-r--r--synapse/events/spamcheck.py87
1 files changed, 78 insertions, 9 deletions
diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py

index efec16c226..abaa382133 100644 --- a/synapse/events/spamcheck.py +++ b/synapse/events/spamcheck.py
@@ -44,8 +44,13 @@ CHECK_EVENT_FOR_SPAM_CALLBACK = Callable[ ["synapse.events.EventBase"], Awaitable[Union[bool, str]], ] -USER_MAY_INVITE_CALLBACK = Callable[[str, str, str], Awaitable[bool]] -USER_MAY_CREATE_ROOM_CALLBACK = Callable[[str], Awaitable[bool]] +# FIXME: Callback signature differs from mainline +USER_MAY_INVITE_CALLBACK = Callable[[str, str, str, str, bool, bool], Awaitable[bool]] +# FIXME: Callback signature differs from mainline +USER_MAY_CREATE_ROOM_CALLBACK = Callable[ + [str, List[str], List[dict], bool], + Awaitable[bool] +] USER_MAY_CREATE_ROOM_ALIAS_CALLBACK = Callable[[str, RoomAlias], Awaitable[bool]] USER_MAY_PUBLISH_ROOM_CALLBACK = Callable[[str, str], Awaitable[bool]] CHECK_USERNAME_FOR_SPAM_CALLBACK = Callable[[Dict[str, str]], Awaitable[bool]] @@ -70,6 +75,8 @@ CHECK_MEDIA_FILE_FOR_SPAM_CALLBACK = Callable[ [ReadableFileWrapper, FileInfo], Awaitable[bool], ] +# FIXME: This callback only exists on the DINUM fork and not in mainline. +USER_MAY_JOIN_ROOM_CALLBACK = Callable[[str, str, bool], Awaitable[bool]] def load_legacy_spam_checkers(hs: "synapse.server.HomeServer"): @@ -98,6 +105,7 @@ def load_legacy_spam_checkers(hs: "synapse.server.HomeServer"): "check_username_for_spam", "check_registration_for_spam", "check_media_file_for_spam", + "user_may_join_room", } for spam_checker in spam_checkers: @@ -177,6 +185,7 @@ class SpamChecker: self._check_media_file_for_spam_callbacks: List[ CHECK_MEDIA_FILE_FOR_SPAM_CALLBACK ] = [] + self._user_may_join_room_callbacks: List[USER_MAY_JOIN_ROOM_CALLBACK] = [] def register_callbacks( self, @@ -192,6 +201,7 @@ class SpamChecker: CHECK_REGISTRATION_FOR_SPAM_CALLBACK ] = None, check_media_file_for_spam: Optional[CHECK_MEDIA_FILE_FOR_SPAM_CALLBACK] = None, + user_may_join_room: Optional[USER_MAY_JOIN_ROOM_CALLBACK] = None, ): """Register callbacks from module for each hook.""" if check_event_for_spam is not None: @@ -222,6 +232,9 @@ class SpamChecker: if check_media_file_for_spam is not None: self._check_media_file_for_spam_callbacks.append(check_media_file_for_spam) + if user_may_join_room is not None: + self._user_may_join_room_callbacks.append(user_may_join_room) + async def check_event_for_spam( self, event: "synapse.events.EventBase" ) -> Union[bool, str]: @@ -246,39 +259,76 @@ class SpamChecker: return False async def user_may_invite( - self, inviter_userid: str, invitee_userid: str, room_id: str + self, + inviter_userid: str, + invitee_userid: Optional[str], + third_party_invite: Optional[Dict], + room_id: str, + new_room: bool, + published_room: bool, ) -> bool: """Checks if a given user may send an invite If this method returns false, the invite will be rejected. Args: - inviter_userid: The user ID of the sender of the invitation - invitee_userid: The user ID targeted in the invitation - room_id: The room ID + inviter_userid: + invitee_userid: The user ID of the invitee. Is None + if this is a third party invite and the 3PID is not bound to a + user ID. + third_party_invite: If a third party invite then is a + dict containing the medium and address of the invitee. + room_id: + new_room: Whether 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`. + published_room: Whether the room the user is being invited + to has been published in the local homeserver's public room + directory. Returns: True if the user may send an invite, otherwise False """ for callback in self._user_may_invite_callbacks: - if await callback(inviter_userid, invitee_userid, room_id) is False: + if await callback( + inviter_userid, + invitee_userid, + third_party_invite, + room_id, + new_room, + published_room, + ) is False: return False return True - async def user_may_create_room(self, userid: str) -> bool: + async def user_may_create_room( + self, + userid: str, + invite_list: List[str], + third_party_invite_list: List[Dict], + cloning: bool, + ) -> bool: """Checks if a given user may create a room If this method returns false, the creation request will be rejected. Args: userid: The ID of the user attempting to create a room + invite_list: List of user IDs that would be invited to + the new room. + third_party_invite_list: List of third party invites + for the new room. + cloning: Whether the user is cloning an existing room, e.g. + upgrading a room. Returns: True if the user may create a room, otherwise False """ for callback in self._user_may_create_room_callbacks: - if await callback(userid) is False: + if await callback( + userid, invite_list, third_party_invite_list, cloning + ) is False: return False return True @@ -321,6 +371,25 @@ class SpamChecker: return True + def user_may_join_room(self, userid: str, room_id: str, is_invited: bool): + """Checks if a given users is allowed to join a room. + + Not called when a user creates a room. + + Args: + userid: + room_id: + is_invited: Whether the user is invited into the room + + Returns: + bool: Whether the user may join the room + """ + for callback in self._user_may_join_room_callbacks: + if await callback(userid, room_id, is_invited) is False: + return False + + return True + async def check_username_for_spam(self, user_profile: Dict[str, str]) -> bool: """Checks if a user ID or display name are considered "spammy" by this server.