-
Notifications
You must be signed in to change notification settings - Fork 349
Add report user API from MSC4260 #18120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f347547
b5f359a
f0dcc7a
61f2750
facf07a
85747b7
e8d102d
a842c66
44dbcab
41d185c
133380f
6ef7a87
dbe43a1
8b84c23
79c2a0a
1029a79
6ce8cc0
42b4207
386a9e6
2058b2b
c394ad1
2f8958c
9251b45
ff53217
51aceab
ba32d12
223df14
592a32d
cf03535
746c506
7d46b07
c4cdded
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add support for the [MSC4260 user report API](https://github.com/matrix-org/matrix-spec-proposals/pull/4260). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# | ||
# This file is licensed under the Affero General Public License (AGPL) version 3. | ||
# | ||
# Copyright 2015, 2016 OpenMarket Ltd | ||
# Copyright (C) 2023 New Vector, Ltd | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU Affero General Public License as | ||
# published by the Free Software Foundation, either version 3 of the | ||
# License, or (at your option) any later version. | ||
# | ||
# See the GNU Affero General Public License for more details: | ||
# <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
# | ||
# | ||
import logging | ||
from http import HTTPStatus | ||
from typing import TYPE_CHECKING | ||
|
||
from synapse.api.errors import Codes, SynapseError | ||
from synapse.api.ratelimiting import Ratelimiter | ||
from synapse.types import ( | ||
Requester, | ||
) | ||
|
||
if TYPE_CHECKING: | ||
from synapse.server import HomeServer | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ReportsHandler: | ||
def __init__(self, hs: "HomeServer"): | ||
self._hs = hs | ||
self._store = hs.get_datastores().main | ||
self._clock = hs.get_clock() | ||
|
||
# Ratelimiter for management of existing delayed events, | ||
# keyed by the requesting user ID. | ||
self._reports_ratelimiter = Ratelimiter( | ||
store=self._store, | ||
clock=self._clock, | ||
cfg=hs.config.ratelimiting.rc_reports, | ||
) | ||
|
||
async def report_user( | ||
self, requester: Requester, target_user_id: str, reason: str | ||
) -> None: | ||
"""Files a report against a user from a user. | ||
|
||
Rate and size limits are applied to the report. If the user being reported | ||
does not belong to this server, the report is ignored. This check is done | ||
after the limits to reduce DoS potential. | ||
|
||
If the user being reported belongs to this server, but doesn't exist, we | ||
similarly ignore the report. The spec allows us to return an error if we | ||
want to, but we choose to hide that user's existence instead. | ||
|
||
If the report is otherwise valid (for a user which exists on our server), | ||
we append it to the database for later processing. | ||
|
||
Args: | ||
requester - The user filing the report. | ||
target_user_id - The user being reported. | ||
reason - The user-supplied reason the user is being reported. | ||
|
||
Raises: | ||
SynapseError for BAD_REQUEST/BAD_JSON if the reason is too long. | ||
""" | ||
|
||
await self._check_limits(requester) | ||
|
||
if len(reason) > 1000: | ||
raise SynapseError( | ||
HTTPStatus.BAD_REQUEST, | ||
"Reason must be less than 1000 characters", | ||
Codes.BAD_JSON, | ||
) | ||
|
||
if not self._hs.is_mine_id(target_user_id): | ||
return # hide that they're not ours/that we can't do anything about them | ||
Comment on lines
+80
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking, but would it not be useful for the reporter to get an error here telling them that the homeserver operator likely don't do much about remote users? And tell them to contact the remote homeserver's operator instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Possibly/probably, though IIRC this is in the MSC. One day we do also hope to support federated reports. |
||
|
||
user = await self._store.get_user_by_id(target_user_id) | ||
if user is None: | ||
return # hide that they don't exist | ||
|
||
await self._store.add_user_report( | ||
target_user_id=target_user_id, | ||
user_id=requester.user.to_string(), | ||
reason=reason, | ||
received_ts=self._clock.time_msec(), | ||
) | ||
|
||
async def _check_limits(self, requester: Requester) -> None: | ||
await self._reports_ratelimiter.ratelimit( | ||
requester, | ||
requester.user.to_string(), | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
-- | ||
-- This file is licensed under the Affero General Public License (AGPL) version 3. | ||
-- | ||
-- Copyright (C) 2025 New Vector, Ltd | ||
-- | ||
-- This program is free software: you can redistribute it and/or modify | ||
-- it under the terms of the GNU Affero General Public License as | ||
-- published by the Free Software Foundation, either version 3 of the | ||
-- License, or (at your option) any later version. | ||
-- | ||
-- See the GNU Affero General Public License for more details: | ||
-- <https://www.gnu.org/licenses/agpl-3.0.html>. | ||
|
||
CREATE TABLE user_reports ( | ||
id BIGINT NOT NULL PRIMARY KEY, | ||
received_ts BIGINT NOT NULL, | ||
target_user_id TEXT NOT NULL, | ||
user_id TEXT NOT NULL, | ||
reason TEXT NOT NULL | ||
); | ||
CREATE INDEX user_reports_target_user_id ON user_reports(target_user_id); -- for lookups | ||
CREATE INDEX user_reports_user_id ON user_reports(user_id); -- for lookups |
Uh oh!
There was an error while loading. Please reload this page.