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

Extend room admin api with additional attributes #7225

Merged
merged 11 commits into from
Apr 22, 2020
1 change: 1 addition & 0 deletions changelog.d/7225.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Extend room admin api (`GET /_synapse/admin/v1/rooms`) with additional attributes.
87 changes: 80 additions & 7 deletions docs/admin_api/rooms.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ The following query parameters are available:
* `from` - Offset in the returned list. Defaults to `0`.
* `limit` - Maximum amount of rooms to return. Defaults to `100`.
* `order_by` - The method in which to sort the returned list of rooms. Valid values are:
- `alphabetical` - Rooms are ordered alphabetically by room name. This is the default.
- `size` - Rooms are ordered by the number of members. Largest to smallest.
- `alphabetical` - Same like `name`. This is deprecated.
- `size` - Same like `joined_members`. This is deprecated.
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `name` - Rooms are ordered alphabetically by room name. This is the default.
- `canonical_alias` - Rooms are ordered alphabetically by main alias address of the room.
- `joined_members` - Rooms are ordered by the number of members. Largest to smallest.
- `joined_local_members` - Rooms are ordered by the number of local members. Largest to smallest.
- `version` - Rooms are ordered by room version. Largest to smallest.
- `creator` - Rooms are ordered alphabetically by creator of the room.
- `encryption` - Rooms are ordered by encryption of the room.
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
- `federatable` - Rooms are ordered by federatable option of the room.
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `public` - Rooms are ordered by visibility in room list.
- `join_rules` - Rooms are ordered alphabetically by join rules of the room.
- `guest_access` - Rooms are ordered by guest access option of the room.
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `history_visibility` - Rooms are ordered alphabetically by visibility of history of the room.
- `state_events` - Rooms are ordered by number of state events. Largest to smallest.
* `dir` - Direction of room order. Either `f` for forwards or `b` for backwards. Setting
this value to `b` will reverse the above sort order. Defaults to `f`.
* `search_term` - Filter rooms by their room name. Search term can be contained in any
Expand All @@ -26,6 +39,16 @@ The following fields are possible in the JSON response body:
- `name` - The name of the room.
- `canonical_alias` - The canonical (main) alias address of the room.
- `joined_members` - How many users are currently in the room.
- `joined_local_members` - How many local users are currently in the room.
- `version` - Version of the room.
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `creator` - The `user_id` of the room creator..
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `encryption` - Algorithm of end-to-end encryption of messages. Is `null` if encryption is not active.
- `federatable` - Whether users on other servers can join this room.
- `public` - If rooms is public or not on the server. Visibility in room directory.
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `join_rules` - The type of rules used for users wishing to join this room. One of: ["public", "knock", "invite", "private"]
- `guest_access` - Whether guests can join the room. One of: ["can_join", "forbidden"]
- `history_visibility` - Who can see the room history. One of: ["invited", "joined", "shared", "world_readable"]
dklimpel marked this conversation as resolved.
Show resolved Hide resolved
- `state_events` - Total number of state_events of a room. Complexity of the room.
* `offset` - The current pagination offset in rooms. This parameter should be
used instead of `next_token` for room offset as `next_token` is
not intended to be parsed.
Expand Down Expand Up @@ -60,14 +83,34 @@ Response:
"room_id": "!OGEhHVWSdvArJzumhm:matrix.org",
"name": "Matrix HQ",
"canonical_alias": "#matrix:matrix.org",
"joined_members": 8326
"joined_members": 8326,
"joined_local_members": 2,
"version": "1",
"creator": "@foo:matrix.org",
"encryption": null,
"federatable": true,
"public": true,
"join_rules": "invite",
"guest_access": null,
"history_visibility": "shared",
"state_events": 93534
},
... (8 hidden items) ...
{
"room_id": "!xYvNcQPhnkrdUmYczI:matrix.org",
"name": "This Week In Matrix (TWIM)",
"canonical_alias": "#twim:matrix.org",
"joined_members": 314
"joined_members": 314,
"joined_local_members": 20,
"version": "4",
"creator": "@foo:matrix.org",
"encryption": "m.megolm.v1.aes-sha2",
"federatable": true,
"public": false,
"join_rules": "invite",
"guest_access": null,
"history_visibility": "shared",
"state_events": 8345
}
],
"offset": 0,
Expand All @@ -92,7 +135,17 @@ Response:
"room_id": "!xYvNcQPhnkrdUmYczI:matrix.org",
"name": "This Week In Matrix (TWIM)",
"canonical_alias": "#twim:matrix.org",
"joined_members": 314
"joined_members": 314,
"joined_local_members": 20,
"version": "4",
"creator": "@foo:matrix.org",
"encryption": "m.megolm.v1.aes-sha2",
"federatable": true,
"public": false,
"join_rules": "invite",
"guest_access": null,
"history_visibility": "shared",
"state_events": 8
}
],
"offset": 0,
Expand All @@ -117,14 +170,34 @@ Response:
"room_id": "!OGEhHVWSdvArJzumhm:matrix.org",
"name": "Matrix HQ",
"canonical_alias": "#matrix:matrix.org",
"joined_members": 8326
"joined_members": 8326,
"joined_local_members": 2,
"version": "1",
"creator": "@foo:matrix.org",
"encryption": null,
"federatable": true,
"public": true,
"join_rules": "invite",
"guest_access": null,
"history_visibility": "shared",
"state_events": 93534
},
... (98 hidden items) ...
{
"room_id": "!xYvNcQPhnkrdUmYczI:matrix.org",
"name": "This Week In Matrix (TWIM)",
"canonical_alias": "#twim:matrix.org",
"joined_members": 314
"joined_members": 314,
"joined_local_members": 20,
"version": "4",
"creator": "@foo:matrix.org",
"encryption": "m.megolm.v1.aes-sha2",
"federatable": true,
"public": false,
"join_rules": "invite",
"guest_access": null,
"history_visibility": "shared",
"state_events": 8345
}
],
"offset": 0,
Expand Down
15 changes: 14 additions & 1 deletion synapse/rest/admin/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,23 @@ async def on_GET(self, request):
# Extract query parameters
start = parse_integer(request, "from", default=0)
limit = parse_integer(request, "limit", default=100)
order_by = parse_string(request, "order_by", default="alphabetical")
order_by = parse_string(request, "order_by", default=RoomSortOrder.NAME.value)
if order_by not in (
RoomSortOrder.ALPHABETICAL.value,
RoomSortOrder.SIZE.value,
RoomSortOrder.NAME.value,
RoomSortOrder.CANONICAL_ALIAS.value,
RoomSortOrder.JOINED_MEMBERS.value,
RoomSortOrder.JOINED_LOCAL_MEMBERS.value,
RoomSortOrder.VERSION.value,
RoomSortOrder.CREATOR.value,
RoomSortOrder.ENCRYPTION.value,
RoomSortOrder.FEDERATABLE.value,
RoomSortOrder.PUBLIC.value,
RoomSortOrder.JOIN_RULES.value,
RoomSortOrder.GUEST_ACCESS.value,
RoomSortOrder.HISTORY_VISIBILITY.value,
RoomSortOrder.STATE_EVENTS.value,
):
raise SynapseError(
400,
Expand Down
68 changes: 67 additions & 1 deletion synapse/storage/data_stores/main/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ class RoomSortOrder(Enum):

ALPHABETICAL = "alphabetical"
anoadragon453 marked this conversation as resolved.
Show resolved Hide resolved
SIZE = "size"
NAME = "name"
CANONICAL_ALIAS = "canonical_alias"
JOINED_MEMBERS = "joined_members"
JOINED_LOCAL_MEMBERS = "joined_local_members"
VERSION = "version"
CREATOR = "creator"
ENCRYPTION = "encryption"
FEDERATABLE = "federatable"
PUBLIC = "public"
JOIN_RULES = "join_rules"
GUEST_ACCESS = "guest_access"
HISTORY_VISIBILITY = "history_visibility"
STATE_EVENTS = "state_events"


class RoomWorkerStore(SQLBaseStore):
Expand Down Expand Up @@ -335,6 +348,45 @@ async def get_rooms_paginate(
# Sort alphabetically
order_by_column = "state.name"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.NAME:
order_by_column = "state.name"
order_by_asc = True
clokep marked this conversation as resolved.
Show resolved Hide resolved
elif RoomSortOrder(order_by) == RoomSortOrder.CANONICAL_ALIAS:
order_by_column = "state.canonical_alias"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.JOINED_MEMBERS:
order_by_column = "curr.joined_members"
order_by_asc = False
elif RoomSortOrder(order_by) == RoomSortOrder.JOINED_LOCAL_MEMBERS:
order_by_column = "curr.local_users_in_room"
order_by_asc = False
elif RoomSortOrder(order_by) == RoomSortOrder.VERSION:
order_by_column = "rooms.room_version"
order_by_asc = False
elif RoomSortOrder(order_by) == RoomSortOrder.CREATOR:
order_by_column = "rooms.creator"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.ENCRYPTION:
order_by_column = "state.encryption"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.FEDERATABLE:
order_by_column = "state.is_federatable"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.PUBLIC:
order_by_column = "rooms.is_public"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.JOIN_RULES:
order_by_column = "state.join_rules"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.GUEST_ACCESS:
order_by_column = "state.guest_access"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.HISTORY_VISIBILITY:
order_by_column = "state.history_visibility"
order_by_asc = True
elif RoomSortOrder(order_by) == RoomSortOrder.STATE_EVENTS:
order_by_column = "curr.current_state_events"
order_by_asc = False
else:
raise StoreError(
500, "Incorrect value for order_by provided: %s" % order_by
Expand All @@ -349,9 +401,13 @@ async def get_rooms_paginate(
# for, and another query for getting the total number of events that could be
# returned. Thus allowing us to see if there are more events to paginate through
info_sql = """
SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members
SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members,
curr.local_users_in_room, rooms.room_version, rooms.creator,
state.encryption, state.is_federatable, rooms.is_public, state.join_rules,
state.guest_access, state.history_visibility, curr.current_state_events
FROM room_stats_state state
INNER JOIN room_stats_current curr USING (room_id)
INNER JOIN rooms USING (room_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea if there are performance impacts to joining rooms here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know it. I am not a SQL specialist.

Copy link
Member

@anoadragon453 anoadragon453 Apr 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explain for the previous version with some example values:

synapse=# explain SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members
synapse-# FROM room_stats_state state
synapse-# INNER JOIN room_stats_current curr USING (room_id)
synapse-# ORDER BY state.name
synapse-# LIMIT 200
synapse-# OFFSET 5;
                                             QUERY PLAN                                             
----------------------------------------------------------------------------------------------------
 Limit  (cost=255.31..255.81 rows=200 width=90)
   ->  Sort  (cost=255.30..260.44 rows=2058 width=90)
         Sort Key: state.name
         ->  Hash Join  (cost=76.99..165.99 rows=2058 width=90)
               Hash Cond: (state.room_id = curr.room_id)
               ->  Seq Scan on room_stats_state state  (cost=0.00..83.58 rows=2058 width=86)
               ->  Hash  (cost=50.33..50.33 rows=2133 width=36)
                     ->  Seq Scan on room_stats_current curr  (cost=0.00..50.33 rows=2133 width=36)
(8 rows)

synapse=# 

and with the new version:

synapse=# explain SELECT state.room_id, state.name, state.canonical_alias, curr.joined_members,
synapse-# curr.local_users_in_room, rooms.room_version, rooms.creator,
synapse-# state.encryption, state.is_federatable, rooms.is_public, state.join_rules,
synapse-# state.guest_access, state.history_visibility, curr.current_state_events
synapse-# FROM room_stats_state state
synapse-# INNER JOIN room_stats_current curr USING (room_id)
synapse-# INNER JOIN rooms USING (room_id)
synapse-# ORDER BY rooms.room_version
synapse-# LIMIT 200
synapse-# OFFSET 5;
                                             QUERY PLAN                                             
----------------------------------------------------------------------------------------------------
 Limit  (cost=331.68..332.18 rows=200 width=162)
   ->  Sort  (cost=331.67..336.44 rows=1907 width=162)
         Sort Key: rooms.room_version
         ->  Hash Join  (cost=154.90..248.91 rows=1907 width=162)
               Hash Cond: (state.room_id = curr.room_id)
               ->  Hash Join  (cost=77.91..166.90 rows=1907 width=182)
                     Hash Cond: (state.room_id = rooms.room_id)
                     ->  Seq Scan on room_stats_state state  (cost=0.00..83.58 rows=2058 width=131)
                     ->  Hash  (cost=54.07..54.07 rows=1907 width=51)
                           ->  Seq Scan on rooms  (cost=0.00..54.07 rows=1907 width=51)
               ->  Hash  (cost=50.33..50.33 rows=2133 width=44)
                     ->  Seq Scan on room_stats_current curr  (cost=0.00..50.33 rows=2133 width=44)
(12 rows)

synapse=# 

So a ~30% increase on the upper bound, but this query is currently only run by the admin API, and as we're getting much more information as a result of it I don't think this is too much of an issue.

%s
ORDER BY %s %s
LIMIT ?
Expand Down Expand Up @@ -389,6 +445,16 @@ def _get_rooms_paginate_txn(txn):
"name": room[1],
"canonical_alias": room[2],
"joined_members": room[3],
"joined_local_members": room[4],
"version": room[5],
"creator": room[6],
"encryption": room[7],
"federatable": room[8],
"public": room[9],
"join_rules": room[10],
"guest_access": room[11],
"history_visibility": room[12],
"state_events": room[13],
}
)

Expand Down
Loading