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

Commit cf78077

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 cf78077

File tree

4 files changed

+34
-16
lines changed

4 files changed

+34
-16
lines changed

changelog.d/12846.feature

+1
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

+13-10
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

+12-6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
Union[
4848
Allow,
4949
Codes,
50+
# Highly experimental, not officially part of the spamchecker API, may
51+
# disappear without warning depending on the results of ongoing
52+
# experiments.
53+
# Use this to return additional information as part of an error.
54+
Tuple[Codes, Dict],
5055
# Deprecated
5156
bool,
5257
# Deprecated
@@ -269,7 +274,7 @@ def register_callbacks(
269274

270275
async def check_event_for_spam(
271276
self, event: "synapse.events.EventBase"
272-
) -> Union[Decision, str]:
277+
) -> Union[Decision, Tuple[Codes, Dict], str]:
273278
"""Checks if a given event is considered "spammy" by this server.
274279
275280
If the server considers an event spammy, then it will be rejected if
@@ -292,9 +297,9 @@ async def check_event_for_spam(
292297
with Measure(
293298
self.clock, "{}.{}".format(callback.__module__, callback.__qualname__)
294299
):
295-
res: Union[Decision, str, bool] = await delay_cancellation(
296-
callback(event)
297-
)
300+
res: Union[
301+
Decision, Tuple[Codes, Dict], str, bool
302+
] = await delay_cancellation(callback(event))
298303
if res is False or res is Allow.ALLOW:
299304
# This spam-checker accepts the event.
300305
# Other spam-checkers may reject it, though.
@@ -304,8 +309,9 @@ async def check_event_for_spam(
304309
# return value `True`
305310
return Codes.FORBIDDEN
306311
else:
307-
# This spam-checker rejects the event either with a `str`
308-
# or with a `Codes`. In either case, we stop here.
312+
# This spam-checker rejects the event either with a `str`,
313+
# with a `Codes` or with a `Tuple[Codes, Dict]`. In either
314+
# case, we stop here.
309315
return res
310316

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

synapse/handlers/message.py

+8
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)