summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--changelog.d/7842.feature1
-rw-r--r--docs/admin_api/rooms.md34
-rw-r--r--synapse/rest/admin/__init__.py2
-rw-r--r--synapse/rest/admin/rooms.py25
-rw-r--r--tests/rest/admin/test_room.py46
5 files changed, 107 insertions, 1 deletions
diff --git a/changelog.d/7842.feature b/changelog.d/7842.feature
new file mode 100644
index 0000000000..727deb01c9
--- /dev/null
+++ b/changelog.d/7842.feature
@@ -0,0 +1 @@
+Add an admin API to list the users in a room. Contributed by Awesome Technologies Innovationslabor GmbH.
diff --git a/docs/admin_api/rooms.md b/docs/admin_api/rooms.md
index 3f26adc16c..15b83e9824 100644
--- a/docs/admin_api/rooms.md
+++ b/docs/admin_api/rooms.md
@@ -319,11 +319,43 @@ Response:
 }
 ```
 
+# Room Members API
+
+The Room Members admin API allows server admins to get a list of all members of a room.
+
+The response includes the following fields:
+
+* `members` - A list of all the members that are present in the room, represented by their ids.
+* `total` - Total number of members in the room.
+
+## Usage
+
+A standard request:
+
+```
+GET /_synapse/admin/v1/rooms/<room_id>/members
+
+{}
+```
+
+Response:
+
+```
+{
+  "members": [
+    "@foo:matrix.org",
+    "@bar:matrix.org",
+    "@foobar:matrix.org
+    ],
+  "total": 3
+}
+```
+
 # Delete Room API
 
 The Delete Room admin API allows server admins to remove rooms from server
 and block these rooms.
-It is a combination and improvement of "[Shutdown room](shutdown_room.md)" 
+It is a combination and improvement of "[Shutdown room](shutdown_room.md)"
 and "[Purge room](purge_room.md)" API.
 
 Shuts down a room. Moves all local users and room aliases automatically to a
diff --git a/synapse/rest/admin/__init__.py b/synapse/rest/admin/__init__.py
index dc373bc5a3..1c88c93f38 100644
--- a/synapse/rest/admin/__init__.py
+++ b/synapse/rest/admin/__init__.py
@@ -38,6 +38,7 @@ from synapse.rest.admin.rooms import (
     DeleteRoomRestServlet,
     JoinRoomAliasServlet,
     ListRoomRestServlet,
+    RoomMembersRestServlet,
     RoomRestServlet,
     ShutdownRoomRestServlet,
 )
@@ -201,6 +202,7 @@ def register_servlets(hs, http_server):
     register_servlets_for_client_rest_resource(hs, http_server)
     ListRoomRestServlet(hs).register(http_server)
     RoomRestServlet(hs).register(http_server)
+    RoomMembersRestServlet(hs).register(http_server)
     DeleteRoomRestServlet(hs).register(http_server)
     JoinRoomAliasServlet(hs).register(http_server)
     PurgeRoomServlet(hs).register(http_server)
diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py
index 544be47060..b8c95d045a 100644
--- a/synapse/rest/admin/rooms.py
+++ b/synapse/rest/admin/rooms.py
@@ -231,6 +231,31 @@ class RoomRestServlet(RestServlet):
         return 200, ret
 
 
+class RoomMembersRestServlet(RestServlet):
+    """
+    Get members list of a room.
+    """
+
+    PATTERNS = admin_patterns("/rooms/(?P<room_id>[^/]+)/members")
+
+    def __init__(self, hs):
+        self.hs = hs
+        self.auth = hs.get_auth()
+        self.store = hs.get_datastore()
+
+    async def on_GET(self, request, room_id):
+        await assert_requester_is_admin(self.auth, request)
+
+        ret = await self.store.get_room(room_id)
+        if not ret:
+            raise NotFoundError("Room not found")
+
+        members = await self.store.get_users_in_room(room_id)
+        ret = {"members": members, "total": len(members)}
+
+        return 200, ret
+
+
 class JoinRoomAliasServlet(RestServlet):
 
     PATTERNS = admin_patterns("/join/(?P<room_identifier>[^/]*)")
diff --git a/tests/rest/admin/test_room.py b/tests/rest/admin/test_room.py
index a80537c4fc..946f06d151 100644
--- a/tests/rest/admin/test_room.py
+++ b/tests/rest/admin/test_room.py
@@ -1136,6 +1136,52 @@ class RoomTestCase(unittest.HomeserverTestCase):
 

         self.assertEqual(room_id_1, channel.json_body["room_id"])

 

+    def test_room_members(self):

+        """Test that room members can be requested correctly"""

+        # Create two test rooms

+        room_id_1 = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)

+        room_id_2 = self.helper.create_room_as(self.admin_user, tok=self.admin_user_tok)

+

+        # Have another user join the room

+        user_1 = self.register_user("foo", "pass")

+        user_tok_1 = self.login("foo", "pass")

+        self.helper.join(room_id_1, user_1, tok=user_tok_1)

+

+        # Have another user join the room

+        user_2 = self.register_user("bar", "pass")

+        user_tok_2 = self.login("bar", "pass")

+        self.helper.join(room_id_1, user_2, tok=user_tok_2)

+        self.helper.join(room_id_2, user_2, tok=user_tok_2)

+

+        # Have another user join the room

+        user_3 = self.register_user("foobar", "pass")

+        user_tok_3 = self.login("foobar", "pass")

+        self.helper.join(room_id_2, user_3, tok=user_tok_3)

+

+        url = "/_synapse/admin/v1/rooms/%s/members" % (room_id_1,)

+        request, channel = self.make_request(

+            "GET", url.encode("ascii"), access_token=self.admin_user_tok,

+        )

+        self.render(request)

+        self.assertEqual(200, channel.code, msg=channel.json_body)

+

+        self.assertCountEqual(

+            ["@admin:test", "@foo:test", "@bar:test"], channel.json_body["members"]

+        )

+        self.assertEqual(channel.json_body["total"], 3)

+

+        url = "/_synapse/admin/v1/rooms/%s/members" % (room_id_2,)

+        request, channel = self.make_request(

+            "GET", url.encode("ascii"), access_token=self.admin_user_tok,

+        )

+        self.render(request)

+        self.assertEqual(200, channel.code, msg=channel.json_body)

+

+        self.assertCountEqual(

+            ["@admin:test", "@bar:test", "@foobar:test"], channel.json_body["members"]

+        )

+        self.assertEqual(channel.json_body["total"], 3)

+

 

 class JoinAliasRoomTestCase(unittest.HomeserverTestCase):