diff --git a/synapse/events/spamcheck.py b/synapse/events/spamcheck.py
index f30207376a..61bcbe2abe 100644
--- a/synapse/events/spamcheck.py
+++ b/synapse/events/spamcheck.py
@@ -44,6 +44,10 @@ CHECK_EVENT_FOR_SPAM_CALLBACK = Callable[
["synapse.events.EventBase"],
Awaitable[Union[bool, str]],
]
+SHOULD_DROP_FEDERATED_EVENT_CALLBACK = Callable[
+ ["synapse.events.EventBase"],
+ Awaitable[Union[bool, str]],
+]
USER_MAY_JOIN_ROOM_CALLBACK = Callable[[str, str, bool], Awaitable[bool]]
USER_MAY_INVITE_CALLBACK = Callable[[str, str, str], Awaitable[bool]]
USER_MAY_SEND_3PID_INVITE_CALLBACK = Callable[[str, str, str, str], Awaitable[bool]]
@@ -168,6 +172,9 @@ class SpamChecker:
self.clock = hs.get_clock()
self._check_event_for_spam_callbacks: List[CHECK_EVENT_FOR_SPAM_CALLBACK] = []
+ self._should_drop_federated_event_callbacks: List[
+ SHOULD_DROP_FEDERATED_EVENT_CALLBACK
+ ] = []
self._user_may_join_room_callbacks: List[USER_MAY_JOIN_ROOM_CALLBACK] = []
self._user_may_invite_callbacks: List[USER_MAY_INVITE_CALLBACK] = []
self._user_may_send_3pid_invite_callbacks: List[
@@ -191,6 +198,9 @@ class SpamChecker:
def register_callbacks(
self,
check_event_for_spam: Optional[CHECK_EVENT_FOR_SPAM_CALLBACK] = None,
+ should_drop_federated_event: Optional[
+ SHOULD_DROP_FEDERATED_EVENT_CALLBACK
+ ] = None,
user_may_join_room: Optional[USER_MAY_JOIN_ROOM_CALLBACK] = None,
user_may_invite: Optional[USER_MAY_INVITE_CALLBACK] = None,
user_may_send_3pid_invite: Optional[USER_MAY_SEND_3PID_INVITE_CALLBACK] = None,
@@ -209,6 +219,11 @@ class SpamChecker:
if check_event_for_spam is not None:
self._check_event_for_spam_callbacks.append(check_event_for_spam)
+ if should_drop_federated_event is not None:
+ self._should_drop_federated_event_callbacks.append(
+ should_drop_federated_event
+ )
+
if user_may_join_room is not None:
self._user_may_join_room_callbacks.append(user_may_join_room)
@@ -268,6 +283,31 @@ class SpamChecker:
return False
+ async def should_drop_federated_event(
+ self, event: "synapse.events.EventBase"
+ ) -> Union[bool, str]:
+ """Checks if a given federated event is considered "spammy" by this
+ server.
+
+ If the server considers an event spammy, it will be silently dropped,
+ and in doing so will split-brain our view of the room's DAG.
+
+ Args:
+ event: the event to be checked
+
+ Returns:
+ True if the event should be silently dropped
+ """
+ for callback in self._should_drop_federated_event_callbacks:
+ with Measure(
+ self.clock, "{}.{}".format(callback.__module__, callback.__qualname__)
+ ):
+ res: Union[bool, str] = await delay_cancellation(callback(event))
+ if res:
+ return res
+
+ return False
+
async def user_may_join_room(
self, user_id: str, room_id: str, is_invited: bool
) -> bool:
|