Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 4abb05b

Browse files
committed
Uniformize spam-checker API, part 3: Expand check_event_for_spam with the ability to return additional fields.
1 parent 89545a7 commit 4abb05b

File tree

4 files changed

+35
-16
lines changed

4 files changed

+35
-16
lines changed

changelog.d/12846.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Experimental: expand `check_event_for_spam` with ability to return additional fields.

synapse/api/errors.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,13 @@ class SynapseError(CodeMessageException):
139139
errcode: Matrix error code e.g 'M_FORBIDDEN'
140140
"""
141141

142-
def __init__(self, code: int, msg: str, errcode: str = Codes.UNKNOWN):
142+
def __init__(
143+
self,
144+
code: int,
145+
msg: str,
146+
errcode: str = Codes.UNKNOWN,
147+
additional_fields: Optional[Dict] = None,
148+
):
143149
"""Constructs a synapse error.
144150
145151
Args:
@@ -149,9 +155,13 @@ def __init__(self, code: int, msg: str, errcode: str = Codes.UNKNOWN):
149155
"""
150156
super().__init__(code, msg)
151157
self.errcode = errcode
158+
if additional_fields is None:
159+
self._additional_fields: Dict = {}
160+
else:
161+
self._additional_fields = dict(additional_fields)
152162

153163
def error_dict(self) -> "JsonDict":
154-
return cs_error(self.msg, self.errcode)
164+
return cs_error(self.msg, self.errcode, **self._additional_fields)
155165

156166

157167
class InvalidAPICallError(SynapseError):
@@ -176,14 +186,7 @@ def __init__(
176186
errcode: str = Codes.UNKNOWN,
177187
additional_fields: Optional[Dict] = None,
178188
):
179-
super().__init__(code, msg, errcode)
180-
if additional_fields is None:
181-
self._additional_fields: Dict = {}
182-
else:
183-
self._additional_fields = dict(additional_fields)
184-
185-
def error_dict(self) -> "JsonDict":
186-
return cs_error(self.msg, self.errcode, **self._additional_fields)
189+
super().__init__(code, msg, errcode, additional_fields)
187190

188191

189192
class ConsentNotGivenError(SynapseError):

synapse/events/spamcheck.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
Awaitable,
2222
Callable,
2323
Collection,
24+
Dict,
2425
List,
2526
Optional,
2627
Tuple,
@@ -47,6 +48,11 @@
4748
Union[
4849
Allow,
4950
Codes,
51+
# Highly experimental, not officially part of the spamchecker API, may
52+
# disappear without warning depending on the results of ongoing
53+
# experiments.
54+
# Use this to return additional information as part of an error.
55+
Tuple[Codes, Dict],
5056
# Deprecated
5157
bool,
5258
# Deprecated
@@ -269,7 +275,7 @@ def register_callbacks(
269275

270276
async def check_event_for_spam(
271277
self, event: "synapse.events.EventBase"
272-
) -> Union[Decision, str]:
278+
) -> Union[Decision, Tuple[Codes, Dict], str]:
273279
"""Checks if a given event is considered "spammy" by this server.
274280
275281
If the server considers an event spammy, then it will be rejected if
@@ -292,9 +298,9 @@ async def check_event_for_spam(
292298
with Measure(
293299
self.clock, "{}.{}".format(callback.__module__, callback.__qualname__)
294300
):
295-
res: Union[Decision, str, bool] = await delay_cancellation(
296-
callback(event)
297-
)
301+
res: Union[
302+
Decision, Tuple[Codes, Dict], str, bool
303+
] = await delay_cancellation(callback(event))
298304
if res is False or res is Allow.ALLOW:
299305
# This spam-checker accepts the event.
300306
# Other spam-checkers may reject it, though.
@@ -304,8 +310,9 @@ async def check_event_for_spam(
304310
# return value `True`
305311
return Codes.FORBIDDEN
306312
else:
307-
# This spam-checker rejects the event either with a `str`
308-
# or with a `Codes`. In either case, we stop here.
313+
# This spam-checker rejects the event either with a `str`,
314+
# with a `Codes` or with a `Tuple[Codes, Dict]`. In either
315+
# case, we stop here.
309316
return res
310317

311318
# No spam-checker has rejected the event, let it pass.

synapse/handlers/message.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,14 @@ async def create_and_send_nonmember_event(
888888

889889
spam_check = await self.spam_checker.check_event_for_spam(event)
890890
if spam_check is not synapse.spam_checker_api.Allow.ALLOW:
891+
if isinstance(spam_check, tuple):
892+
[code, dict] = spam_check
893+
raise SynapseError(
894+
403,
895+
"This message had been rejected as probable spam",
896+
code,
897+
dict,
898+
)
891899
raise SynapseError(
892900
403, "This message had been rejected as probable spam", spam_check
893901
)

0 commit comments

Comments
 (0)