From 10332c175c829a21b6565bc5e865bca154ffb084 Mon Sep 17 00:00:00 2001 From: David Teller Date: Mon, 18 Jan 2021 15:02:22 +0100 Subject: [PATCH 1/8] New API /_synapse/admin/rooms/{roomId}/context/{eventId} Signed-off-by: David Teller --- changelog.d/9150.feature | 4 +++ synapse/handlers/room.py | 11 +++++-- synapse/rest/admin/__init__.py | 2 ++ synapse/rest/admin/rooms.py | 53 ++++++++++++++++++++++++++++++++++ synapse/visibility.py | 26 +++++++++++++---- tests/rest/admin/test_room.py | 48 ++++++++++++++++++++++++++++++ 6 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 changelog.d/9150.feature diff --git a/changelog.d/9150.feature b/changelog.d/9150.feature new file mode 100644 index 000000000000..86c4fd3d7260 --- /dev/null +++ b/changelog.d/9150.feature @@ -0,0 +1,4 @@ +New API /_synapse/admin/rooms/{roomId}/context/{eventId} + +This API mirrors /_matrix/client/r0/rooms/{roomId}/context/{eventId} but lets administrators +inspect rooms. Designed to annotate abuse reports with context. diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index ee27d991351b..15e90fdd4ed3 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1008,6 +1008,7 @@ async def get_event_context( event_id: str, limit: int, event_filter: Optional[Filter], + use_admin_priviledge: bool = False, ) -> Optional[JsonDict]: """Retrieves events, pagination tokens and state around a given event in a room. @@ -1020,7 +1021,9 @@ async def get_event_context( (excluding state). event_filter: the filter to apply to the events returned (excluding the target event_id) - + use_admin_priviledge: if `True`, return all events, regardless + of whether `user` has access to them. To be used **ONLY** + from the admin API. Returns: dict, or None if the event isn't found """ @@ -1032,7 +1035,11 @@ async def get_event_context( def filter_evts(events): return filter_events_for_client( - self.storage, user.to_string(), events, is_peeking=is_peeking + self.storage, + user.to_string(), + events, + is_peeking=is_peeking, + use_admin_priviledge=use_admin_priviledge, ) event = await self.store.get_event( diff --git a/synapse/rest/admin/__init__.py b/synapse/rest/admin/__init__.py index 57e0a108376e..cb24998b474a 100644 --- a/synapse/rest/admin/__init__.py +++ b/synapse/rest/admin/__init__.py @@ -42,6 +42,7 @@ JoinRoomAliasServlet, ListRoomRestServlet, MakeRoomAdminRestServlet, + RoomEventContextServlet, RoomMembersRestServlet, RoomRestServlet, ShutdownRoomRestServlet, @@ -236,6 +237,7 @@ def register_servlets(hs, http_server): MakeRoomAdminRestServlet(hs).register(http_server) ShadowBanRestServlet(hs).register(http_server) ForwardExtremitiesRestServlet(hs).register(http_server) + RoomEventContextServlet(hs).register(http_server) def register_servlets_for_client_rest_resource(hs, http_server): diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py index f14915d47ee7..6539655289c8 100644 --- a/synapse/rest/admin/rooms.py +++ b/synapse/rest/admin/rooms.py @@ -566,3 +566,56 @@ async def on_GET(self, request, room_identifier): extremities = await self.store.get_forward_extremities_for_room(room_id) return 200, {"count": len(extremities), "results": extremities} + +class RoomEventContextServlet(RestServlet): + PATTERNS = admin_patterns("/rooms/(?P[^/]*)/context/(?P[^/]*)$") + + def __init__(self, hs): + super().__init__() + self.clock = hs.get_clock() + self.room_context_handler = hs.get_room_context_handler() + self._event_serializer = hs.get_event_client_serializer() + self.auth = hs.get_auth() + + async def on_GET(self, request, room_id, event_id): + requester = await self.auth.get_user_by_req(request, allow_guest=True) + + limit = parse_integer(request, "limit", default=10) + + # picking the API shape for symmetry with /messages + filter_str = parse_string(request, b"filter", encoding="utf-8") + if filter_str: + filter_json = urlparse.unquote(filter_str) + event_filter = Filter( + json_decoder.decode(filter_json) + ) # type: Optional[Filter] + else: + event_filter = None + + results = await self.room_context_handler.get_event_context( + requester.user, + room_id, + event_id, + limit, + event_filter, + use_admin_priviledge=True, + ) + + if not results: + raise SynapseError(404, "Event not found.", errcode=Codes.NOT_FOUND) + + time_now = self.clock.time_msec() + results["events_before"] = await self._event_serializer.serialize_events( + results["events_before"], time_now + ) + results["event"] = await self._event_serializer.serialize_event( + results["event"], time_now + ) + results["events_after"] = await self._event_serializer.serialize_events( + results["events_after"], time_now + ) + results["state"] = await self._event_serializer.serialize_events( + results["state"], time_now + ) + + return 200, results diff --git a/synapse/visibility.py b/synapse/visibility.py index ec50e7e977dc..80c304562d04 100644 --- a/synapse/visibility.py +++ b/synapse/visibility.py @@ -53,6 +53,7 @@ async def filter_events_for_client( is_peeking=False, always_include_ids=frozenset(), filter_send_to_client=True, + use_admin_priviledge=False, ): """ Check which events a user is allowed to see. If the user can see the event but its @@ -71,6 +72,9 @@ async def filter_events_for_client( filter_send_to_client (bool): Whether we're checking an event that's going to be sent to a client. This might not always be the case since this function can also be called to check whether a user can see the state at a given point. + use_admin_priviledge: if `True`, return all events, regardless + of whether `user` has access to them. To be used **ONLY** + from the admin API. Returns: list[synapse.events.EventBase] @@ -79,15 +83,23 @@ async def filter_events_for_client( # to clients. events = [e for e in events if not e.internal_metadata.is_soft_failed()] - types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, user_id)) + types = None + if use_admin_priviledge: + # Administrators can access all events. + types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, None)) + else: + types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, user_id)) + event_id_to_state = await storage.state.get_state_for_events( frozenset(e.event_id for e in events), state_filter=StateFilter.from_types(types), ) - ignore_dict_content = await storage.main.get_global_account_data_by_type_for_user( - AccountDataTypes.IGNORED_USER_LIST, user_id - ) + ignore_dict_content = None + if not use_admin_priviledge: + ignore_dict_content = await storage.main.get_global_account_data_by_type_for_user( + AccountDataTypes.IGNORED_USER_LIST, user_id + ) ignore_list = frozenset() if ignore_dict_content: @@ -183,10 +195,12 @@ def allowed(event): if old_priority < new_priority: visibility = prev_visibility + membership = None + if use_admin_priviledge: + membership = Membership.JOIN # likewise, if the event is the user's own membership event, use # the 'most joined' membership - membership = None - if event.type == EventTypes.Member and event.state_key == user_id: + elif event.type == EventTypes.Member and event.state_key == user_id: membership = event.content.get("membership", None) if membership not in MEMBERSHIP_PRIORITY: membership = "leave" diff --git a/tests/rest/admin/test_room.py b/tests/rest/admin/test_room.py index a0f32c5512c5..7e89eb47939a 100644 --- a/tests/rest/admin/test_room.py +++ b/tests/rest/admin/test_room.py @@ -1430,6 +1430,54 @@ def test_join_private_room_if_owner(self): self.assertEquals(200, int(channel.result["code"]), msg=channel.result["body"]) self.assertEqual(private_room_id, channel.json_body["joined_rooms"][0]) + def test_context(self): + """ + Test that, as admin, we can find the context of an event without having joined the room. + """ + + # Create a room. We're not part of it. + user_id = self.register_user("test", "test") + user_tok = self.login("test", "test") + room_id = self.helper.create_room_as(user_id, tok=user_tok) + + # Populate the room with events. + events = [] + for i in range(30): + events.append( + self.helper.send_event( + room_id, "com.example.test", content={"index": i}, tok=user_tok + ) + ) + + # Now let's fetch the context for this room. + midway = (len(events) - 1) // 2 + channel = self.make_request( + "GET", + "/_synapse/admin/v1/rooms/%s/context/%s" + % (room_id, events[midway]["event_id"]), + access_token=self.admin_user_tok, + ) + self.assertEquals(200, int(channel.result["code"]), msg=channel.result["body"]) + self.assertEquals( + channel.json_body["event"]["event_id"], events[midway]["event_id"] + ) + + for i, found_event in enumerate(channel.json_body["events_before"]): + for j, posted_event in enumerate(events): + if found_event["event_id"] == posted_event["event_id"]: + self.assertTrue(j < midway) + break + else: + self.fail("Event %s from events_before not found" % j) + + for i, found_event in enumerate(channel.json_body["events_after"]): + for j, posted_event in enumerate(events): + if found_event["event_id"] == posted_event["event_id"]: + self.assertTrue(j > midway) + break + else: + self.fail("Event %s from events_after not found" % j) + class MakeRoomAdminTestCase(unittest.HomeserverTestCase): servlets = [ From fe52dae6bd8508bfb79ba5e534a384a9e5e96b5d Mon Sep 17 00:00:00 2001 From: David Teller Date: Fri, 22 Jan 2021 14:41:20 +0100 Subject: [PATCH 2/8] FIXUP: Documenting /_synapse/admin/v1/rooms//context/ --- docs/admin_api/rooms.md | 119 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/docs/admin_api/rooms.md b/docs/admin_api/rooms.md index f34cec1ff721..6d737c5be1cf 100644 --- a/docs/admin_api/rooms.md +++ b/docs/admin_api/rooms.md @@ -10,6 +10,7 @@ * [Undoing room shutdowns](#undoing-room-shutdowns) - [Make Room Admin API](#make-room-admin-api) - [Forward Extremities Admin API](#forward-extremities-admin-api) +- [Event Context API](#event-context-api) # List Room API @@ -564,3 +565,121 @@ that were deleted. "deleted": 1 } ``` + +# Event Context API + +This API lets a client find the context of an event. This is designed primarily to investigate abuse reports. + +``` +GET /_synapse/admin/v1/rooms//context/ +``` + +This API mimmicks [GET /_matrix/client/r0/rooms/{roomId}/context/{eventId}](https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-context-eventid). Please refer to the link for all details on parameters and reseponse. + +Example response: + +```json +{ + "end": "t29-57_2_0_2", + "events_after": [ + { + "content": { + "body": "This is an example text message", + "msgtype": "m.text", + "format": "org.matrix.custom.html", + "formatted_body": "This is an example text message" + }, + "type": "m.room.message", + "event_id": "$143273582443PhrSn:example.org", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + } + } + ], + "event": { + "content": { + "body": "filename.jpg", + "info": { + "h": 398, + "w": 394, + "mimetype": "image/jpeg", + "size": 31037 + }, + "url": "mxc://example.org/JWEIFJgwEIhweiWJE", + "msgtype": "m.image" + }, + "type": "m.room.message", + "event_id": "$f3h4d129462ha:example.com", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + } + }, + "events_before": [ + { + "content": { + "body": "something-important.doc", + "filename": "something-important.doc", + "info": { + "mimetype": "application/msword", + "size": 46144 + }, + "msgtype": "m.file", + "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe" + }, + "type": "m.room.message", + "event_id": "$143273582443PhrSn:example.org", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + } + } + ], + "start": "t27-54_2_0_2", + "state": [ + { + "content": { + "creator": "@example:example.org", + "room_version": "1", + "m.federate": true, + "predecessor": { + "event_id": "$something:example.org", + "room_id": "!oldroom:example.org" + } + }, + "type": "m.room.create", + "event_id": "$143273582443PhrSn:example.org", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + }, + "state_key": "" + }, + { + "content": { + "membership": "join", + "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", + "displayname": "Alice Margatroid" + }, + "type": "m.room.member", + "event_id": "$143273582443PhrSn:example.org", + "room_id": "!636q39766251:example.com", + "sender": "@example:example.org", + "origin_server_ts": 1432735824653, + "unsigned": { + "age": 1234 + }, + "state_key": "@alice:example.org" + } + ] +} +``` From de7f049527c64470a16b2633862a1f1b8f0da9c2 Mon Sep 17 00:00:00 2001 From: David Teller Date: Mon, 25 Jan 2021 18:02:35 +0100 Subject: [PATCH 3/8] FIXUP: Don't filter events at all for admin/v1/rooms/.../context/... --- synapse/handlers/room.py | 10 ++++------ synapse/visibility.py | 25 ++++++------------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index 15e90fdd4ed3..b02056dc63d0 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -52,7 +52,7 @@ create_requester, ) from synapse.util import stringutils -from synapse.util.async_helpers import Linearizer +from synapse.util.async_helpers import Linearizer, maybe_awaitable from synapse.util.caches.response_cache import ResponseCache from synapse.util.stringutils import parse_and_validate_server_name from synapse.visibility import filter_events_for_client @@ -1034,12 +1034,10 @@ async def get_event_context( is_peeking = user.to_string() not in users def filter_evts(events): + if use_admin_priviledge: + return maybe_awaitable(events) return filter_events_for_client( - self.storage, - user.to_string(), - events, - is_peeking=is_peeking, - use_admin_priviledge=use_admin_priviledge, + self.storage, user.to_string(), events, is_peeking=is_peeking ) event = await self.store.get_event( diff --git a/synapse/visibility.py b/synapse/visibility.py index 80c304562d04..2109e2f37fa1 100644 --- a/synapse/visibility.py +++ b/synapse/visibility.py @@ -53,7 +53,6 @@ async def filter_events_for_client( is_peeking=False, always_include_ids=frozenset(), filter_send_to_client=True, - use_admin_priviledge=False, ): """ Check which events a user is allowed to see. If the user can see the event but its @@ -72,9 +71,6 @@ async def filter_events_for_client( filter_send_to_client (bool): Whether we're checking an event that's going to be sent to a client. This might not always be the case since this function can also be called to check whether a user can see the state at a given point. - use_admin_priviledge: if `True`, return all events, regardless - of whether `user` has access to them. To be used **ONLY** - from the admin API. Returns: list[synapse.events.EventBase] @@ -83,23 +79,16 @@ async def filter_events_for_client( # to clients. events = [e for e in events if not e.internal_metadata.is_soft_failed()] - types = None - if use_admin_priviledge: - # Administrators can access all events. - types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, None)) - else: - types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, user_id)) + types = ((EventTypes.RoomHistoryVisibility, ""), (EventTypes.Member, user_id)) event_id_to_state = await storage.state.get_state_for_events( frozenset(e.event_id for e in events), state_filter=StateFilter.from_types(types), ) - ignore_dict_content = None - if not use_admin_priviledge: - ignore_dict_content = await storage.main.get_global_account_data_by_type_for_user( - AccountDataTypes.IGNORED_USER_LIST, user_id - ) + ignore_dict_content = await storage.main.get_global_account_data_by_type_for_user( + AccountDataTypes.IGNORED_USER_LIST, user_id + ) ignore_list = frozenset() if ignore_dict_content: @@ -195,12 +184,10 @@ def allowed(event): if old_priority < new_priority: visibility = prev_visibility - membership = None - if use_admin_priviledge: - membership = Membership.JOIN # likewise, if the event is the user's own membership event, use # the 'most joined' membership - elif event.type == EventTypes.Member and event.state_key == user_id: + membership = None + if event.type == EventTypes.Member and event.state_key == user_id: membership = event.content.get("membership", None) if membership not in MEMBERSHIP_PRIORITY: membership = "leave" From b859919acc3ad6c61ba26a3c9b1e36c75a30c3fe Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 28 Jan 2021 12:18:07 +0100 Subject: [PATCH 4/8] FIXUP: Now testing that the user is admin! --- changelog.d/9150.feature | 5 +---- synapse/rest/admin/rooms.py | 3 ++- tests/rest/admin/test_room.py | 36 ++++++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/changelog.d/9150.feature b/changelog.d/9150.feature index 86c4fd3d7260..48a8148dee70 100644 --- a/changelog.d/9150.feature +++ b/changelog.d/9150.feature @@ -1,4 +1 @@ -New API /_synapse/admin/rooms/{roomId}/context/{eventId} - -This API mirrors /_matrix/client/r0/rooms/{roomId}/context/{eventId} but lets administrators -inspect rooms. Designed to annotate abuse reports with context. +New API /_synapse/admin/rooms/{roomId}/context/{eventId}. diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py index 6539655289c8..439319754949 100644 --- a/synapse/rest/admin/rooms.py +++ b/synapse/rest/admin/rooms.py @@ -578,7 +578,8 @@ def __init__(self, hs): self.auth = hs.get_auth() async def on_GET(self, request, room_id, event_id): - requester = await self.auth.get_user_by_req(request, allow_guest=True) + requester = await self.auth.get_user_by_req(request, allow_guest=False) + await assert_user_is_admin(self.auth, requester.user) limit = parse_integer(request, "limit", default=10) diff --git a/tests/rest/admin/test_room.py b/tests/rest/admin/test_room.py index 7e89eb47939a..fd201993d311 100644 --- a/tests/rest/admin/test_room.py +++ b/tests/rest/admin/test_room.py @@ -1430,7 +1430,41 @@ def test_join_private_room_if_owner(self): self.assertEquals(200, int(channel.result["code"]), msg=channel.result["body"]) self.assertEqual(private_room_id, channel.json_body["joined_rooms"][0]) - def test_context(self): + def test_context_as_non_admin(self): + """ + Test that, without being admin, one cannot use the context admin API + """ + # Create a room. + user_id = self.register_user("test", "test") + user_tok = self.login("test", "test") + + self.register_user("test_2", "test") + user_tok_2 = self.login("test_2", "test") + + room_id = self.helper.create_room_as(user_id, tok=user_tok) + + # Populate the room with events. + events = [] + for i in range(30): + events.append( + self.helper.send_event( + room_id, "com.example.test", content={"index": i}, tok=user_tok + ) + ) + + # Now attempt to find the context using the admin API without being admin. + midway = (len(events) - 1) // 2 + for tok in [user_tok, user_tok_2]: + channel = self.make_request( + "GET", + "/_synapse/admin/v1/rooms/%s/context/%s" + % (room_id, events[midway]["event_id"]), + access_token=tok, + ) + self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"]) + self.assertEqual(Codes.FORBIDDEN, channel.json_body["errcode"]) + + def test_context_as_admin(self): """ Test that, as admin, we can find the context of an event without having joined the room. """ From a7648696231f3df7ec1f324a15dc308fbee2a985 Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 28 Jan 2021 12:19:39 +0100 Subject: [PATCH 5/8] FIXUP: Doc --- synapse/rest/admin/rooms.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py index 439319754949..50df60e02941 100644 --- a/synapse/rest/admin/rooms.py +++ b/synapse/rest/admin/rooms.py @@ -568,6 +568,12 @@ async def on_GET(self, request, room_identifier): return 200, {"count": len(extremities), "results": extremities} class RoomEventContextServlet(RestServlet): + """ + Provide the context for an event. + This API is designed to be used when system administrators wish to look at + an abuse report and understand what happened during and immediately prior + to this event. + """ PATTERNS = admin_patterns("/rooms/(?P[^/]*)/context/(?P[^/]*)$") def __init__(self, hs): From b755f60ce2fb651356d8d588dcd7864b022023cd Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 28 Jan 2021 12:23:19 +0100 Subject: [PATCH 6/8] FIXUP: Removing awaitable --- synapse/handlers/room.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index b02056dc63d0..c1034880764b 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1033,10 +1033,10 @@ async def get_event_context( users = await self.store.get_users_in_room(room_id) is_peeking = user.to_string() not in users - def filter_evts(events): + async def filter_evts(events): if use_admin_priviledge: - return maybe_awaitable(events) - return filter_events_for_client( + return events + return await filter_events_for_client( self.storage, user.to_string(), events, is_peeking=is_peeking ) From 93f84e037349cb3efddd8df5adf22512530a295c Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 28 Jan 2021 12:27:30 +0100 Subject: [PATCH 7/8] FIXUP: Making get_event_context a bit more paranoid --- synapse/handlers/room.py | 10 ++++++++-- synapse/rest/admin/rooms.py | 2 +- synapse/rest/client/v1/room.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index c1034880764b..e039cea024dd 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -38,6 +38,7 @@ from synapse.api.room_versions import KNOWN_ROOM_VERSIONS, RoomVersion from synapse.events import EventBase from synapse.events.utils import copy_power_levels_contents +from synapse.rest.admin._base import assert_user_is_admin from synapse.storage.state import StateFilter from synapse.types import ( JsonDict, @@ -997,13 +998,14 @@ async def _generate_room_id( class RoomContextHandler: def __init__(self, hs: "HomeServer"): self.hs = hs + self.auth = hs.get_auth() self.store = hs.get_datastore() self.storage = hs.get_storage() self.state_store = self.storage.state async def get_event_context( self, - user: UserID, + requester: Requester, room_id: str, event_id: str, limit: int, @@ -1014,7 +1016,7 @@ async def get_event_context( in a room. Args: - user + requester room_id event_id limit: The maximum number of events to return in total @@ -1027,6 +1029,10 @@ async def get_event_context( Returns: dict, or None if the event isn't found """ + user = requester.user + if use_admin_priviledge: + await assert_user_is_admin(self.auth, requester.user) + before_limit = math.floor(limit / 2.0) after_limit = limit - before_limit diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py index 50df60e02941..641e325581a4 100644 --- a/synapse/rest/admin/rooms.py +++ b/synapse/rest/admin/rooms.py @@ -600,7 +600,7 @@ async def on_GET(self, request, room_id, event_id): event_filter = None results = await self.room_context_handler.get_event_context( - requester.user, + requester, room_id, event_id, limit, diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py index f95627ee615a..90fd98c53e2f 100644 --- a/synapse/rest/client/v1/room.py +++ b/synapse/rest/client/v1/room.py @@ -650,7 +650,7 @@ async def on_GET(self, request, room_id, event_id): event_filter = None results = await self.room_context_handler.get_event_context( - requester.user, room_id, event_id, limit, event_filter + requester, room_id, event_id, limit, event_filter ) if not results: From 31d072aea0a37ad5408995359b89080b5280f57d Mon Sep 17 00:00:00 2001 From: David Teller Date: Thu, 28 Jan 2021 16:53:40 +0100 Subject: [PATCH 8/8] FIXUP: linter --- synapse/handlers/room.py | 2 +- synapse/rest/admin/rooms.py | 5 +++++ tests/rest/admin/test_room.py | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index e039cea024dd..99fd063084cb 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -53,7 +53,7 @@ create_requester, ) from synapse.util import stringutils -from synapse.util.async_helpers import Linearizer, maybe_awaitable +from synapse.util.async_helpers import Linearizer from synapse.util.caches.response_cache import ResponseCache from synapse.util.stringutils import parse_and_validate_server_name from synapse.visibility import filter_events_for_client diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py index 641e325581a4..c673ff07e737 100644 --- a/synapse/rest/admin/rooms.py +++ b/synapse/rest/admin/rooms.py @@ -15,9 +15,11 @@ import logging from http import HTTPStatus from typing import TYPE_CHECKING, List, Optional, Tuple +from urllib import parse as urlparse from synapse.api.constants import EventTypes, JoinRules, Membership from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError +from synapse.api.filtering import Filter from synapse.http.servlet import ( RestServlet, assert_params_in_dict, @@ -33,6 +35,7 @@ ) from synapse.storage.databases.main.room import RoomSortOrder from synapse.types import JsonDict, RoomAlias, RoomID, UserID, create_requester +from synapse.util import json_decoder if TYPE_CHECKING: from synapse.server import HomeServer @@ -567,6 +570,7 @@ async def on_GET(self, request, room_identifier): extremities = await self.store.get_forward_extremities_for_room(room_id) return 200, {"count": len(extremities), "results": extremities} + class RoomEventContextServlet(RestServlet): """ Provide the context for an event. @@ -574,6 +578,7 @@ class RoomEventContextServlet(RestServlet): an abuse report and understand what happened during and immediately prior to this event. """ + PATTERNS = admin_patterns("/rooms/(?P[^/]*)/context/(?P[^/]*)$") def __init__(self, hs): diff --git a/tests/rest/admin/test_room.py b/tests/rest/admin/test_room.py index fd201993d311..f4f5569a89f3 100644 --- a/tests/rest/admin/test_room.py +++ b/tests/rest/admin/test_room.py @@ -1461,7 +1461,9 @@ def test_context_as_non_admin(self): % (room_id, events[midway]["event_id"]), access_token=tok, ) - self.assertEquals(403, int(channel.result["code"]), msg=channel.result["body"]) + self.assertEquals( + 403, int(channel.result["code"]), msg=channel.result["body"] + ) self.assertEqual(Codes.FORBIDDEN, channel.json_body["errcode"]) def test_context_as_admin(self):