Add the ability to filter by state event type on admin room state endpoint (#18035)

Adds a query param `type` to `/_synapse/admin/v1/rooms/{room_id}/state`
that filters the state event query by state event type.

---------

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
This commit is contained in:
Shay 2025-01-08 07:38:26 -08:00 committed by GitHub
parent beea39f000
commit e34fd1228d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 1 deletions

View file

@ -0,0 +1 @@
Add a unit test for the `type` parameter of the [Room State Admin API](https://element-hq.github.io/synapse/develop/admin_api/rooms.html#room-state-api).

View file

@ -385,6 +385,13 @@ The API is:
GET /_synapse/admin/v1/rooms/<room_id>/state
```
**Parameters**
The following query parameter is available:
* `type` - The type of room state event to filter by, eg "m.room.create". If provided, only state events
of this type will be returned (regardless of their `state_key` value).
A response body like the following is returned:
```json

View file

@ -23,6 +23,7 @@ from http import HTTPStatus
from typing import TYPE_CHECKING, List, Optional, Tuple, cast
import attr
from immutabledict import immutabledict
from synapse.api.constants import Direction, EventTypes, JoinRules, Membership
from synapse.api.errors import AuthError, Codes, NotFoundError, SynapseError
@ -463,7 +464,18 @@ class RoomStateRestServlet(RestServlet):
if not room:
raise NotFoundError("Room not found")
event_ids = await self._storage_controllers.state.get_current_state_ids(room_id)
state_filter = None
type = parse_string(request, "type")
if type:
state_filter = StateFilter(
types=immutabledict({type: None}),
include_others=False,
)
event_ids = await self._storage_controllers.state.get_current_state_ids(
room_id, state_filter
)
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)

View file

@ -2035,6 +2035,52 @@ class RoomTestCase(unittest.HomeserverTestCase):
# the create_room already does the right thing, so no need to verify that we got
# the state events it created.
def test_room_state_param(self) -> None:
"""Test that filtering by state event type works when requesting state"""
room_id = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)
channel = self.make_request(
"GET",
f"/_synapse/admin/v1/rooms/{room_id}/state?type=m.room.member",
access_token=self.admin_user_tok,
)
self.assertEqual(200, channel.code)
state = channel.json_body["state"]
# only one member has joined so there should be one membership event
self.assertEqual(1, len(state))
event = state[0]
self.assertEqual(event["type"], "m.room.member")
self.assertEqual(event["state_key"], self.admin_user)
def test_room_state_param_empty(self) -> None:
"""Test that passing an empty string as state filter param returns no state events"""
room_id = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)
channel = self.make_request(
"GET",
f"/_synapse/admin/v1/rooms/{room_id}/state?type=",
access_token=self.admin_user_tok,
)
self.assertEqual(200, channel.code)
state = channel.json_body["state"]
self.assertEqual(5, len(state))
def test_room_state_param_not_in_room(self) -> None:
"""
Test that passing a state filter param for a state event not in the room
returns no state events
"""
room_id = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)
channel = self.make_request(
"GET",
f"/_synapse/admin/v1/rooms/{room_id}/state?type=m.room.custom",
access_token=self.admin_user_tok,
)
self.assertEqual(200, channel.code)
state = channel.json_body["state"]
self.assertEqual(0, len(state))
def _set_canonical_alias(
self, room_id: str, test_alias: str, admin_user_tok: str
) -> None: