diff options
Diffstat (limited to 'synapse/events/spamcheck.py')
-rw-r--r-- | synapse/events/spamcheck.py | 49 |
1 files changed, 27 insertions, 22 deletions
diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py index 7984874e21..1048b4c825 100644 --- a/synapse/events/spamcheck.py +++ b/synapse/events/spamcheck.py @@ -30,7 +30,7 @@ from typing import ( from synapse.api.errors import Codes from synapse.rest.media.v1._base import FileInfo from synapse.rest.media.v1.media_storage import ReadableFileWrapper -from synapse.spam_checker_api import Allow, Decision, RegistrationBehaviour +from synapse.spam_checker_api import RegistrationBehaviour from synapse.types import RoomAlias, UserProfile from synapse.util.async_helpers import delay_cancellation, maybe_awaitable from synapse.util.metrics import Measure @@ -46,12 +46,9 @@ CHECK_EVENT_FOR_SPAM_CALLBACK = Callable[ ["synapse.events.EventBase"], Awaitable[ Union[ - Allow, - Codes, + str, # Deprecated bool, - # Deprecated - str, ] ], ] @@ -178,6 +175,8 @@ def load_legacy_spam_checkers(hs: "synapse.server.HomeServer") -> None: class SpamChecker: + NOT_SPAM = "NOT_SPAM" + def __init__(self, hs: "synapse.server.HomeServer") -> None: self.hs = hs self.clock = hs.get_clock() @@ -268,9 +267,7 @@ class SpamChecker: if check_media_file_for_spam is not None: self._check_media_file_for_spam_callbacks.append(check_media_file_for_spam) - async def check_event_for_spam( - self, event: "synapse.events.EventBase" - ) -> Union[Decision, str]: + async def check_event_for_spam(self, event: "synapse.events.EventBase") -> str: """Checks if a given event is considered "spammy" by this server. If the server considers an event spammy, then it will be rejected if @@ -281,22 +278,20 @@ class SpamChecker: event: the event to be checked Returns: - - on `ALLOW`, the event is considered good (non-spammy) and should - be let through. Other spamcheck filters may still reject it. - - on `Code`, the event is considered spammy and is rejected with a specific + - `NOT_SPAM` if the event is considered good (non-spammy) and should be let + through. Other spamcheck filters may still reject it. + - A `Code` if the event is considered spammy and is rejected with a specific error message/code. - - on `str`, the event is considered spammy and the string is used as error - message. This usage is generally discouraged as it doesn't support - internationalization. + - A string that isn't `NOT_SPAM` if the event is considered spammy and the + string should be used as the client-facing error message. This usage is + generally discouraged as it doesn't support internationalization. """ for callback in self._check_event_for_spam_callbacks: with Measure( self.clock, "{}.{}".format(callback.__module__, callback.__qualname__) ): - res: Union[Decision, str, bool] = await delay_cancellation( - callback(event) - ) - if res is False or res is Allow.ALLOW: + res = await delay_cancellation(callback(event)) + if res is False or res == self.NOT_SPAM: # This spam-checker accepts the event. # Other spam-checkers may reject it, though. continue @@ -304,13 +299,23 @@ class SpamChecker: # This spam-checker rejects the event with deprecated # return value `True` return Codes.FORBIDDEN + elif not isinstance(res, str): + # mypy complains that we can't reach this code because of the + # return type in CHECK_EVENT_FOR_SPAM_CALLBACK, but we don't know + # for sure that the module actually returns it. + logger.warning( # type: ignore[unreachable] + "Module returned invalid value, rejecting message as spam" + ) + res = "This message has been rejected as probable spam" else: - # This spam-checker rejects the event either with a `str` - # or with a `Codes`. In either case, we stop here. - return res + # The module rejected the event either with a `Codes` + # or some other `str`. In either case, we stop here. + pass + + return res # No spam-checker has rejected the event, let it pass. - return Allow.ALLOW + return self.NOT_SPAM async def should_drop_federated_event( self, event: "synapse.events.EventBase" |