mirror of
https://github.com/element-hq/synapse.git
synced 2025-03-14 09:45:51 +00:00
Merge 180b784d3c
into 929f19b472
This commit is contained in:
commit
859dfa9a87
5 changed files with 118 additions and 1 deletions
1
changelog.d/18040.feature
Normal file
1
changelog.d/18040.feature
Normal file
|
@ -0,0 +1 @@
|
|||
Add a query param `participant` to `/members` admin api to filter for room participants.
|
|
@ -358,6 +358,13 @@ The API is:
|
|||
GET /_synapse/admin/v1/rooms/<room_id>/members
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
The following query parameters are available:
|
||||
|
||||
* `participant` - Optional. If provided and set to true, only returns currently joined members who have
|
||||
also posted to the room. Defaults to false.
|
||||
|
||||
A response body like the following is returned:
|
||||
|
||||
```json
|
||||
|
|
|
@ -435,7 +435,12 @@ class RoomMembersRestServlet(RestServlet):
|
|||
if not room:
|
||||
raise NotFoundError("Room not found")
|
||||
|
||||
members = await self.store.get_users_in_room(room_id)
|
||||
participant = parse_boolean(request, "participant", False)
|
||||
|
||||
if participant:
|
||||
members = await self.store.get_participants_in_room(room_id)
|
||||
else:
|
||||
members = await self.store.get_users_in_room(room_id)
|
||||
ret = {"members": members, "total": len(members)}
|
||||
|
||||
return HTTPStatus.OK, ret
|
||||
|
|
|
@ -1606,6 +1606,34 @@ class RoomMemberWorkerStore(EventsWorkerStore, CacheInvalidationWorkerStore):
|
|||
from_ts,
|
||||
)
|
||||
|
||||
async def get_participants_in_room(self, room_id: str) -> Sequence[str]:
|
||||
"""
|
||||
Return a list of all currently joined room members who have posted
|
||||
in the given room.
|
||||
|
||||
Args:
|
||||
room_id: room ID of the room to search in
|
||||
"""
|
||||
|
||||
def _get_participants_in_room_txn(
|
||||
txn: LoggingTransaction, room_id: str
|
||||
) -> List[str]:
|
||||
sql = """
|
||||
SELECT DISTINCT c.state_key
|
||||
FROM current_state_events AS c
|
||||
INNER JOIN events AS e USING(room_id)
|
||||
WHERE room_id = ?
|
||||
AND c.membership = 'join'
|
||||
AND e.type = 'm.room.message'
|
||||
AND c.state_key = e.sender
|
||||
"""
|
||||
txn.execute(sql, (room_id,))
|
||||
return [r[0] for r in txn]
|
||||
|
||||
return await self.db_pool.runInteraction(
|
||||
"_get_participants_in_room_txn", _get_participants_in_room_txn, room_id
|
||||
)
|
||||
|
||||
|
||||
class RoomMemberBackgroundUpdateStore(SQLBaseStore):
|
||||
def __init__(
|
||||
|
|
|
@ -2021,6 +2021,82 @@ class RoomTestCase(unittest.HomeserverTestCase):
|
|||
)
|
||||
self.assertEqual(channel.json_body["total"], 3)
|
||||
|
||||
def test_room_members_participants_param(self) -> None:
|
||||
"""
|
||||
Test that /_synapse/admin/v1/rooms/{room_id}/members with a query param value of
|
||||
participant=true returns a list of currently joined users who have posted, and
|
||||
that the list does not contain room members who have not posted
|
||||
"""
|
||||
|
||||
participant = self.register_user("participant", "pass")
|
||||
participant_tok = self.login("participant", "pass")
|
||||
room_id = self.helper.create_room_as(participant, tok=participant_tok)
|
||||
|
||||
participant2 = self.register_user("participant2", "pass")
|
||||
participant2_tok = self.login("participant2", "pass")
|
||||
self.helper.join(room_id, participant2, tok=participant2_tok)
|
||||
|
||||
# have some lurkers join the room
|
||||
for i in range(5):
|
||||
user = self.register_user(f"user{i}", "pass")
|
||||
user_tok = self.login(f"user{i}", "pass")
|
||||
self.helper.join(room_id, user, tok=user_tok)
|
||||
|
||||
# double-check the room membership total, should be 7
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
f"/_synapse/admin/v1/rooms/{room_id}/members",
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code)
|
||||
self.assertEqual(channel.json_body["total"], 7)
|
||||
|
||||
# participants send messages
|
||||
self.helper.send_event(
|
||||
room_id,
|
||||
"m.room.message",
|
||||
content={
|
||||
"msgtype": "m.text",
|
||||
"body": "nefarious activity",
|
||||
},
|
||||
tok=participant_tok,
|
||||
)
|
||||
|
||||
self.helper.send_event(
|
||||
room_id,
|
||||
"m.room.message",
|
||||
content={
|
||||
"msgtype": "m.text",
|
||||
"body": "more nefarious activity",
|
||||
},
|
||||
tok=participant2_tok,
|
||||
)
|
||||
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
f"/_synapse/admin/v1/rooms/{room_id}/members?participant=true",
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code)
|
||||
participants = channel.json_body["members"]
|
||||
self.assertEqual(channel.json_body["total"], 2)
|
||||
self.assertIn(participant, participants)
|
||||
self.assertIn(participant2, participants)
|
||||
|
||||
# have participants leave room
|
||||
self.helper.leave(room_id, participant, tok=participant_tok)
|
||||
self.helper.leave(room_id, participant2, tok=participant2_tok)
|
||||
|
||||
# there should no longer be any active participants
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
f"/_synapse/admin/v1/rooms/{room_id}/members?participant=true",
|
||||
access_token=self.admin_user_tok,
|
||||
)
|
||||
self.assertEqual(200, channel.code)
|
||||
participants = channel.json_body["total"]
|
||||
self.assertEqual(participants, 0)
|
||||
|
||||
def test_room_state(self) -> None:
|
||||
"""Test that room state can be requested correctly"""
|
||||
# Create two test rooms
|
||||
|
|
Loading…
Add table
Reference in a new issue