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

Commit 66e6801

Browse files
authored
Split admin API for reported events into a detail and a list view (#8539)
Split admin API for reported events in detail und list view. API was introduced with #8217 in synapse v.1.21.0. It makes the list (`GET /_synapse/admin/v1/event_reports`) less complex and provides a better overview. The details can be queried with: `GET /_synapse/admin/v1/event_reports/<report_id>`. It is similar to room and users API. It is a kind of regression in `GET /_synapse/admin/v1/event_reports`. `event_json` was removed. But the api was introduced one version before and it is an admin API (not under spec). Signed-off-by: Dirk Klimpel [email protected]
1 parent 6c9ab61 commit 66e6801

File tree

6 files changed

+411
-86
lines changed

6 files changed

+411
-86
lines changed

changelog.d/8539.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Split admin API for reported events (`GET /_synapse/admin/v1/event_reports`) into detail and list endpoints. This is a breaking change to #8217 which was introduced in Synapse v1.21.0. Those who already use this API should check their scripts. Contributed by @dklimpel.

docs/admin_api/event_reports.rst

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,67 +17,26 @@ It returns a JSON body like the following:
1717
{
1818
"event_reports": [
1919
{
20-
"content": {
21-
"reason": "foo",
22-
"score": -100
23-
},
2420
"event_id": "$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY",
25-
"event_json": {
26-
"auth_events": [
27-
"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M",
28-
"$oggsNXxzPFRE3y53SUNd7nsj69-QzKv03a1RucHu-ws"
29-
],
30-
"content": {
31-
"body": "matrix.org: This Week in Matrix",
32-
"format": "org.matrix.custom.html",
33-
"formatted_body": "<strong>matrix.org</strong>:<br><a href=\"https://matrix.org/blog/\"><strong>This Week in Matrix</strong></a>",
34-
"msgtype": "m.notice"
35-
},
36-
"depth": 546,
37-
"hashes": {
38-
"sha256": "xK1//xnmvHJIOvbgXlkI8eEqdvoMmihVDJ9J4SNlsAw"
39-
},
40-
"origin": "matrix.org",
41-
"origin_server_ts": 1592291711430,
42-
"prev_events": [
43-
"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M"
44-
],
45-
"prev_state": [],
46-
"room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org",
47-
"sender": "@foobar:matrix.org",
48-
"signatures": {
49-
"matrix.org": {
50-
"ed25519:a_JaEG": "cs+OUKW/iHx5pEidbWxh0UiNNHwe46Ai9LwNz+Ah16aWDNszVIe2gaAcVZfvNsBhakQTew51tlKmL2kspXk/Dg"
51-
}
52-
},
53-
"type": "m.room.message",
54-
"unsigned": {
55-
"age_ts": 1592291711430,
56-
}
57-
},
5821
"id": 2,
5922
"reason": "foo",
23+
"score": -100,
6024
"received_ts": 1570897107409,
61-
"room_alias": "#alias1:matrix.org",
25+
"canonical_alias": "#alias1:matrix.org",
6226
"room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org",
27+
"name": "Matrix HQ",
6328
"sender": "@foobar:matrix.org",
6429
"user_id": "@foo:matrix.org"
6530
},
6631
{
67-
"content": {
68-
"reason": "bar",
69-
"score": -100
70-
},
7132
"event_id": "$3IcdZsDaN_En-S1DF4EMCy3v4gNRKeOJs8W5qTOKj4I",
72-
"event_json": {
73-
// hidden items
74-
// see above
75-
},
7633
"id": 3,
7734
"reason": "bar",
35+
"score": -100,
7836
"received_ts": 1598889612059,
79-
"room_alias": "#alias2:matrix.org",
37+
"canonical_alias": "#alias2:matrix.org",
8038
"room_id": "!eGvUQuTCkHGVwNMOjv:matrix.org",
39+
"name": "Your room name here",
8140
"sender": "@foobar:matrix.org",
8241
"user_id": "@bar:matrix.org"
8342
}
@@ -113,17 +72,94 @@ The following fields are returned in the JSON response body:
11372
- ``id``: integer - ID of event report.
11473
- ``received_ts``: integer - The timestamp (in milliseconds since the unix epoch) when this report was sent.
11574
- ``room_id``: string - The ID of the room in which the event being reported is located.
75+
- ``name``: string - The name of the room.
11676
- ``event_id``: string - The ID of the reported event.
11777
- ``user_id``: string - This is the user who reported the event and wrote the reason.
11878
- ``reason``: string - Comment made by the ``user_id`` in this report. May be blank.
119-
- ``content``: object - Content of reported event.
120-
121-
- ``reason``: string - Comment made by the ``user_id`` in this report. May be blank.
122-
- ``score``: integer - Content is reported based upon a negative score, where -100 is "most offensive" and 0 is "inoffensive".
123-
79+
- ``score``: integer - Content is reported based upon a negative score, where -100 is "most offensive" and 0 is "inoffensive".
12480
- ``sender``: string - This is the ID of the user who sent the original message/event that was reported.
125-
- ``room_alias``: string - The alias of the room. ``null`` if the room does not have a canonical alias set.
126-
- ``event_json``: object - Details of the original event that was reported.
81+
- ``canonical_alias``: string - The canonical alias of the room. ``null`` if the room does not have a canonical alias set.
12782
- ``next_token``: integer - Indication for pagination. See above.
12883
- ``total``: integer - Total number of event reports related to the query (``user_id`` and ``room_id``).
12984

85+
Show details of a specific event report
86+
=======================================
87+
88+
This API returns information about a specific event report.
89+
90+
The api is::
91+
92+
GET /_synapse/admin/v1/event_reports/<report_id>
93+
94+
To use it, you will need to authenticate by providing an ``access_token`` for a
95+
server admin: see `README.rst <README.rst>`_.
96+
97+
It returns a JSON body like the following:
98+
99+
.. code:: jsonc
100+
101+
{
102+
"event_id": "$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY",
103+
"event_json": {
104+
"auth_events": [
105+
"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M",
106+
"$oggsNXxzPFRE3y53SUNd7nsj69-QzKv03a1RucHu-ws"
107+
],
108+
"content": {
109+
"body": "matrix.org: This Week in Matrix",
110+
"format": "org.matrix.custom.html",
111+
"formatted_body": "<strong>matrix.org</strong>:<br><a href=\"https://matrix.org/blog/\"><strong>This Week in Matrix</strong></a>",
112+
"msgtype": "m.notice"
113+
},
114+
"depth": 546,
115+
"hashes": {
116+
"sha256": "xK1//xnmvHJIOvbgXlkI8eEqdvoMmihVDJ9J4SNlsAw"
117+
},
118+
"origin": "matrix.org",
119+
"origin_server_ts": 1592291711430,
120+
"prev_events": [
121+
"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M"
122+
],
123+
"prev_state": [],
124+
"room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org",
125+
"sender": "@foobar:matrix.org",
126+
"signatures": {
127+
"matrix.org": {
128+
"ed25519:a_JaEG": "cs+OUKW/iHx5pEidbWxh0UiNNHwe46Ai9LwNz+Ah16aWDNszVIe2gaAcVZfvNsBhakQTew51tlKmL2kspXk/Dg"
129+
}
130+
},
131+
"type": "m.room.message",
132+
"unsigned": {
133+
"age_ts": 1592291711430,
134+
}
135+
},
136+
"id": <report_id>,
137+
"reason": "foo",
138+
"score": -100,
139+
"received_ts": 1570897107409,
140+
"canonical_alias": "#alias1:matrix.org",
141+
"room_id": "!ERAgBpSOcCCuTJqQPk:matrix.org",
142+
"name": "Matrix HQ",
143+
"sender": "@foobar:matrix.org",
144+
"user_id": "@foo:matrix.org"
145+
}
146+
147+
**URL parameters:**
148+
149+
- ``report_id``: string - The ID of the event report.
150+
151+
**Response**
152+
153+
The following fields are returned in the JSON response body:
154+
155+
- ``id``: integer - ID of event report.
156+
- ``received_ts``: integer - The timestamp (in milliseconds since the unix epoch) when this report was sent.
157+
- ``room_id``: string - The ID of the room in which the event being reported is located.
158+
- ``name``: string - The name of the room.
159+
- ``event_id``: string - The ID of the reported event.
160+
- ``user_id``: string - This is the user who reported the event and wrote the reason.
161+
- ``reason``: string - Comment made by the ``user_id`` in this report. May be blank.
162+
- ``score``: integer - Content is reported based upon a negative score, where -100 is "most offensive" and 0 is "inoffensive".
163+
- ``sender``: string - This is the ID of the user who sent the original message/event that was reported.
164+
- ``canonical_alias``: string - The canonical alias of the room. ``null`` if the room does not have a canonical alias set.
165+
- ``event_json``: object - Details of the original event that was reported.

synapse/rest/admin/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
DeviceRestServlet,
3232
DevicesRestServlet,
3333
)
34-
from synapse.rest.admin.event_reports import EventReportsRestServlet
34+
from synapse.rest.admin.event_reports import (
35+
EventReportDetailRestServlet,
36+
EventReportsRestServlet,
37+
)
3538
from synapse.rest.admin.groups import DeleteGroupAdminRestServlet
3639
from synapse.rest.admin.media import ListMediaInRoom, register_servlets_for_media_repo
3740
from synapse.rest.admin.purge_room_servlet import PurgeRoomServlet
@@ -222,6 +225,7 @@ def register_servlets(hs, http_server):
222225
DevicesRestServlet(hs).register(http_server)
223226
DeleteDevicesRestServlet(hs).register(http_server)
224227
EventReportsRestServlet(hs).register(http_server)
228+
EventReportDetailRestServlet(hs).register(http_server)
225229

226230

227231
def register_servlets_for_client_rest_resource(hs, http_server):

synapse/rest/admin/event_reports.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import logging
1717

18-
from synapse.api.errors import Codes, SynapseError
18+
from synapse.api.errors import Codes, NotFoundError, SynapseError
1919
from synapse.http.servlet import RestServlet, parse_integer, parse_string
2020
from synapse.rest.admin._base import admin_patterns, assert_requester_is_admin
2121

@@ -86,3 +86,47 @@ async def on_GET(self, request):
8686
ret["next_token"] = start + len(event_reports)
8787

8888
return 200, ret
89+
90+
91+
class EventReportDetailRestServlet(RestServlet):
92+
"""
93+
Get a specific reported event that is known to the homeserver. Results are returned
94+
in a dictionary containing report information.
95+
The requester must have administrator access in Synapse.
96+
97+
GET /_synapse/admin/v1/event_reports/<report_id>
98+
returns:
99+
200 OK with details report if success otherwise an error.
100+
101+
Args:
102+
The parameter `report_id` is the ID of the event report in the database.
103+
Returns:
104+
JSON blob of information about the event report
105+
"""
106+
107+
PATTERNS = admin_patterns("/event_reports/(?P<report_id>[^/]*)$")
108+
109+
def __init__(self, hs):
110+
self.hs = hs
111+
self.auth = hs.get_auth()
112+
self.store = hs.get_datastore()
113+
114+
async def on_GET(self, request, report_id):
115+
await assert_requester_is_admin(self.auth, request)
116+
117+
message = (
118+
"The report_id parameter must be a string representing a positive integer."
119+
)
120+
try:
121+
report_id = int(report_id)
122+
except ValueError:
123+
raise SynapseError(400, message, errcode=Codes.INVALID_PARAM)
124+
125+
if report_id < 0:
126+
raise SynapseError(400, message, errcode=Codes.INVALID_PARAM)
127+
128+
ret = await self.store.get_event_report(report_id)
129+
if not ret:
130+
raise NotFoundError("Event report not found")
131+
132+
return 200, ret

synapse/storage/databases/main/room.py

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,65 @@ async def add_event_report(
14111411
desc="add_event_report",
14121412
)
14131413

1414+
async def get_event_report(self, report_id: int) -> Optional[Dict[str, Any]]:
1415+
"""Retrieve an event report
1416+
1417+
Args:
1418+
report_id: ID of reported event in database
1419+
Returns:
1420+
event_report: json list of information from event report
1421+
"""
1422+
1423+
def _get_event_report_txn(txn, report_id):
1424+
1425+
sql = """
1426+
SELECT
1427+
er.id,
1428+
er.received_ts,
1429+
er.room_id,
1430+
er.event_id,
1431+
er.user_id,
1432+
er.content,
1433+
events.sender,
1434+
room_stats_state.canonical_alias,
1435+
room_stats_state.name,
1436+
event_json.json AS event_json
1437+
FROM event_reports AS er
1438+
LEFT JOIN events
1439+
ON events.event_id = er.event_id
1440+
JOIN event_json
1441+
ON event_json.event_id = er.event_id
1442+
JOIN room_stats_state
1443+
ON room_stats_state.room_id = er.room_id
1444+
WHERE er.id = ?
1445+
"""
1446+
1447+
txn.execute(sql, [report_id])
1448+
row = txn.fetchone()
1449+
1450+
if not row:
1451+
return None
1452+
1453+
event_report = {
1454+
"id": row[0],
1455+
"received_ts": row[1],
1456+
"room_id": row[2],
1457+
"event_id": row[3],
1458+
"user_id": row[4],
1459+
"score": db_to_json(row[5]).get("score"),
1460+
"reason": db_to_json(row[5]).get("reason"),
1461+
"sender": row[6],
1462+
"canonical_alias": row[7],
1463+
"name": row[8],
1464+
"event_json": db_to_json(row[9]),
1465+
}
1466+
1467+
return event_report
1468+
1469+
return await self.db_pool.runInteraction(
1470+
"get_event_report", _get_event_report_txn, report_id
1471+
)
1472+
14141473
async def get_event_reports_paginate(
14151474
self,
14161475
start: int,
@@ -1468,18 +1527,15 @@ def _get_event_reports_paginate_txn(txn):
14681527
er.room_id,
14691528
er.event_id,
14701529
er.user_id,
1471-
er.reason,
14721530
er.content,
14731531
events.sender,
1474-
room_aliases.room_alias,
1475-
event_json.json AS event_json
1532+
room_stats_state.canonical_alias,
1533+
room_stats_state.name
14761534
FROM event_reports AS er
1477-
LEFT JOIN room_aliases
1478-
ON room_aliases.room_id = er.room_id
1479-
JOIN events
1535+
LEFT JOIN events
14801536
ON events.event_id = er.event_id
1481-
JOIN event_json
1482-
ON event_json.event_id = er.event_id
1537+
JOIN room_stats_state
1538+
ON room_stats_state.room_id = er.room_id
14831539
{where_clause}
14841540
ORDER BY er.received_ts {order}
14851541
LIMIT ?
@@ -1490,15 +1546,29 @@ def _get_event_reports_paginate_txn(txn):
14901546

14911547
args += [limit, start]
14921548
txn.execute(sql, args)
1493-
event_reports = self.db_pool.cursor_to_dict(txn)
1494-
1495-
if count > 0:
1496-
for row in event_reports:
1497-
try:
1498-
row["content"] = db_to_json(row["content"])
1499-
row["event_json"] = db_to_json(row["event_json"])
1500-
except Exception:
1501-
continue
1549+
1550+
event_reports = []
1551+
for row in txn:
1552+
try:
1553+
s = db_to_json(row[5]).get("score")
1554+
r = db_to_json(row[5]).get("reason")
1555+
except Exception:
1556+
logger.error("Unable to parse json from event_reports: %s", row[0])
1557+
continue
1558+
event_reports.append(
1559+
{
1560+
"id": row[0],
1561+
"received_ts": row[1],
1562+
"room_id": row[2],
1563+
"event_id": row[3],
1564+
"user_id": row[4],
1565+
"score": s,
1566+
"reason": r,
1567+
"sender": row[6],
1568+
"canonical_alias": row[7],
1569+
"name": row[8],
1570+
}
1571+
)
15021572

15031573
return event_reports, count
15041574

0 commit comments

Comments
 (0)