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

Add an admin API to get the current room state #9168

Merged
merged 4 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/9168.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an admin API for retrieving the current room state of a room.
30 changes: 30 additions & 0 deletions docs/admin_api/rooms.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,36 @@ Response:
}
```

# Room State API

The Room State admin API allows server admins to get a list of all state events in a room.

The response includes the following fields:

* `state` - The current state of the room at the time of request.

## Usage

A standard request:

```
GET /_synapse/admin/v1/rooms/<room_id>/state

{}
```

Response:

```json
{
"state": [
{"type": "m.room.create", "state_key": "", "etc": true},
{"type": "m.room.power_levels", "state_key": "", "etc": true},
{"type": "m.room.name", "state_key": "", "etc": true}
]
}
```

# Delete Room API

The Delete Room admin API allows server admins to remove rooms from server
Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ async def get_state_events(
raise NotFoundError("Can't find event for token %s" % (at_token,))

visible_events = await filter_events_for_client(
self.storage, user_id, last_events, filter_send_to_client=False
self.storage, user_id, last_events, filter_send_to_client=False,
)

event = last_events[0]
Expand Down
2 changes: 2 additions & 0 deletions synapse/rest/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MakeRoomAdminRestServlet,
RoomMembersRestServlet,
RoomRestServlet,
RoomStateRestServlet,
ShutdownRoomRestServlet,
)
from synapse.rest.admin.server_notice_servlet import SendServerNoticeServlet
Expand Down Expand Up @@ -209,6 +210,7 @@ def register_servlets(hs, http_server):
"""
register_servlets_for_client_rest_resource(hs, http_server)
ListRoomRestServlet(hs).register(http_server)
RoomStateRestServlet(hs).register(http_server)
RoomRestServlet(hs).register(http_server)
RoomMembersRestServlet(hs).register(http_server)
DeleteRoomRestServlet(hs).register(http_server)
Expand Down
39 changes: 39 additions & 0 deletions synapse/rest/admin/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,45 @@ async def on_GET(
return 200, ret


class RoomStateRestServlet(RestServlet):
"""
Get full state within a room.
"""

PATTERNS = admin_patterns("/rooms/(?P<room_id>[^/]+)/state")

def __init__(self, hs: "HomeServer"):
self.hs = hs
self.auth = hs.get_auth()
self.store = hs.get_datastore()
self.clock = hs.get_clock()
self._event_serializer = hs.get_event_client_serializer()

async def on_GET(
self, request: SynapseRequest, room_id: str
) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request)
await assert_user_is_admin(self.auth, requester.user)

ret = await self.store.get_room(room_id)
if not ret:
raise NotFoundError("Room not found")

event_ids = await self.store.get_current_state_ids(room_id)
events = await self.store.get_events(event_ids.values())
now = self.clock.time_msec()
room_state = await self._event_serializer.serialize_events(
events.values(),
now,
# We don't bother bundling aggregations in when asked for state
# events, as clients won't use them.
bundle_aggregations=False,
)
turt2live marked this conversation as resolved.
Show resolved Hide resolved
ret = {"state": room_state}

return 200, ret


class JoinRoomAliasServlet(RestServlet):

PATTERNS = admin_patterns("/join/(?P<room_identifier>[^/]*)")
Expand Down
15 changes: 15 additions & 0 deletions tests/rest/admin/test_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,21 @@ def test_room_members(self):
)
self.assertEqual(channel.json_body["total"], 3)

def test_room_state(self):
"""Test that room state can be requested correctly"""
# Create two test rooms
room_id = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)

url = "/_synapse/admin/v1/rooms/%s/state" % (room_id,)
channel = self.make_request(
"GET", url.encode("ascii"), access_token=self.admin_user_tok,
)
self.assertEqual(200, channel.code, msg=channel.json_body)
self.assertIn("state", channel.json_body)
# testing that the state events match is painful and not done here. We assume that
# the create_room already does the right thing, so no need to verify that we got
# the state events it created.


class JoinAliasRoomTestCase(unittest.HomeserverTestCase):

Expand Down