diff options
author | Travis Ralston <travisr@element.io> | 2024-06-12 04:27:46 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-12 12:27:46 +0200 |
commit | f1c4dfb08b530f2bfaf9c6723ce69ccd231a3370 (patch) | |
tree | 4c6a10da47f03ead7817b7c1188bb0e2bb53dfaa /synapse | |
parent | Bump types-jsonschema from 4.21.0.20240311 to 4.22.0.20240610 (#17288) (diff) | |
download | synapse-f1c4dfb08b530f2bfaf9c6723ce69ccd231a3370.tar.xz |
Add report room API (MSC4151) (#17270)
https://github.com/matrix-org/matrix-spec-proposals/pull/4151 This is intended to be enabled by default for immediate use. When FCP is complete, the unstable endpoint will be dropped and stable endpoint supported instead - no backwards compatibility is expected for the unstable endpoint.
Diffstat (limited to 'synapse')
-rw-r--r-- | synapse/config/experimental.py | 3 | ||||
-rw-r--r-- | synapse/rest/__init__.py | 4 | ||||
-rw-r--r-- | synapse/rest/client/reporting.py (renamed from synapse/rest/client/report_event.py) | 57 | ||||
-rw-r--r-- | synapse/rest/client/versions.py | 2 | ||||
-rw-r--r-- | synapse/storage/databases/main/room.py | 32 | ||||
-rw-r--r-- | synapse/storage/schema/main/delta/85/06_add_room_reports.sql | 20 |
6 files changed, 115 insertions, 3 deletions
diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py index 75fe6d7b24..5fe5b951dd 100644 --- a/synapse/config/experimental.py +++ b/synapse/config/experimental.py @@ -443,3 +443,6 @@ class ExperimentalConfig(Config): self.msc3916_authenticated_media_enabled = experimental.get( "msc3916_authenticated_media_enabled", False ) + + # MSC4151: Report room API (Client-Server API) + self.msc4151_enabled: bool = experimental.get("msc4151_enabled", False) diff --git a/synapse/rest/__init__.py b/synapse/rest/__init__.py index 534dc0e276..0024ccf708 100644 --- a/synapse/rest/__init__.py +++ b/synapse/rest/__init__.py @@ -53,7 +53,7 @@ from synapse.rest.client import ( register, relations, rendezvous, - report_event, + reporting, room, room_keys, room_upgrade_rest_servlet, @@ -128,7 +128,7 @@ class ClientRestResource(JsonResource): tags.register_servlets(hs, client_resource) account_data.register_servlets(hs, client_resource) if is_main_process: - report_event.register_servlets(hs, client_resource) + reporting.register_servlets(hs, client_resource) openid.register_servlets(hs, client_resource) notifications.register_servlets(hs, client_resource) devices.register_servlets(hs, client_resource) diff --git a/synapse/rest/client/report_event.py b/synapse/rest/client/reporting.py index 447281931e..a95b83b14d 100644 --- a/synapse/rest/client/report_event.py +++ b/synapse/rest/client/reporting.py @@ -23,17 +23,28 @@ import logging from http import HTTPStatus from typing import TYPE_CHECKING, Tuple +from synapse._pydantic_compat import HAS_PYDANTIC_V2 from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError from synapse.http.server import HttpServer -from synapse.http.servlet import RestServlet, parse_json_object_from_request +from synapse.http.servlet import ( + RestServlet, + parse_and_validate_json_object_from_request, + parse_json_object_from_request, +) from synapse.http.site import SynapseRequest from synapse.types import JsonDict +from synapse.types.rest import RequestBodyModel from ._base import client_patterns if TYPE_CHECKING: from synapse.server import HomeServer +if TYPE_CHECKING or HAS_PYDANTIC_V2: + from pydantic.v1 import StrictStr +else: + from pydantic import StrictStr + logger = logging.getLogger(__name__) @@ -95,5 +106,49 @@ class ReportEventRestServlet(RestServlet): return 200, {} +class ReportRoomRestServlet(RestServlet): + # https://github.com/matrix-org/matrix-spec-proposals/pull/4151 + PATTERNS = client_patterns( + "/org.matrix.msc4151/rooms/(?P<room_id>[^/]*)/report$", + releases=[], + v1=False, + unstable=True, + ) + + def __init__(self, hs: "HomeServer"): + super().__init__() + self.hs = hs + self.auth = hs.get_auth() + self.clock = hs.get_clock() + self.store = hs.get_datastores().main + + class PostBody(RequestBodyModel): + reason: StrictStr + + async def on_POST( + self, request: SynapseRequest, room_id: str + ) -> Tuple[int, JsonDict]: + requester = await self.auth.get_user_by_req(request) + user_id = requester.user.to_string() + + body = parse_and_validate_json_object_from_request(request, self.PostBody) + + room = await self.store.get_room(room_id) + if room is None: + raise NotFoundError("Room does not exist") + + await self.store.add_room_report( + room_id=room_id, + user_id=user_id, + reason=body.reason, + received_ts=self.clock.time_msec(), + ) + + return 200, {} + + def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None: ReportEventRestServlet(hs).register(http_server) + + if hs.config.experimental.msc4151_enabled: + ReportRoomRestServlet(hs).register(http_server) diff --git a/synapse/rest/client/versions.py b/synapse/rest/client/versions.py index 56de6906d0..f428158139 100644 --- a/synapse/rest/client/versions.py +++ b/synapse/rest/client/versions.py @@ -149,6 +149,8 @@ class VersionsRestServlet(RestServlet): is not None ) ), + # MSC4151: Report room API (Client-Server API) + "org.matrix.msc4151": self.config.experimental.msc4151_enabled, }, }, ) diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py index 616c941687..b8a71c803e 100644 --- a/synapse/storage/databases/main/room.py +++ b/synapse/storage/databases/main/room.py @@ -2207,6 +2207,7 @@ class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore): super().__init__(database, db_conn, hs) self._event_reports_id_gen = IdGenerator(db_conn, "event_reports", "id") + self._room_reports_id_gen = IdGenerator(db_conn, "room_reports", "id") self._instance_name = hs.get_instance_name() @@ -2416,6 +2417,37 @@ class RoomStore(RoomBackgroundUpdateStore, RoomWorkerStore): ) return next_id + async def add_room_report( + self, + room_id: str, + user_id: str, + reason: str, + received_ts: int, + ) -> int: + """Add a room report + + Args: + room_id: The room ID being reported. + user_id: User who reports the room. + reason: Description that the user specifies. + received_ts: Time when the user submitted the report (milliseconds). + Returns: + Id of the room report. + """ + next_id = self._room_reports_id_gen.get_next() + await self.db_pool.simple_insert( + table="room_reports", + values={ + "id": next_id, + "received_ts": received_ts, + "room_id": room_id, + "user_id": user_id, + "reason": reason, + }, + desc="add_room_report", + ) + return next_id + async def block_room(self, room_id: str, user_id: str) -> None: """Marks the room as blocked. diff --git a/synapse/storage/schema/main/delta/85/06_add_room_reports.sql b/synapse/storage/schema/main/delta/85/06_add_room_reports.sql new file mode 100644 index 0000000000..f7b45276cf --- /dev/null +++ b/synapse/storage/schema/main/delta/85/06_add_room_reports.sql @@ -0,0 +1,20 @@ +-- +-- This file is licensed under the Affero General Public License (AGPL) version 3. +-- +-- Copyright (C) 2024 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 room_reports ( + id BIGINT NOT NULL PRIMARY KEY, + received_ts BIGINT NOT NULL, + room_id TEXT NOT NULL, + user_id TEXT NOT NULL, + reason TEXT NOT NULL +); |