Add search by room ID and room alias to List Room admin API (#11099)

Fixes: #10874
Signed-off-by: Dirk Klimpel dirk@klimpel.org
This commit is contained in:
Dirk Klimpel 2021-11-02 11:01:13 +01:00 committed by GitHub
parent 46d0937447
commit 7537201840
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 53 deletions

View file

@ -0,0 +1 @@
Add search by room ID and room alias to List Room admin API.

View file

@ -38,9 +38,14 @@ The following query parameters are available:
- `history_visibility` - Rooms are ordered alphabetically by visibility of history of the room. - `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. - `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 * `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`. 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 * `search_term` - Filter rooms by their room name, canonical alias and room id.
part of the room name. Defaults to no filtering. Specifically, rooms are selected if the search term is contained in
- the room's name,
- the local part of the room's canonical alias, or
- the complete (local and server part) room's id (case sensitive).
Defaults to no filtering.
**Response** **Response**

View file

@ -412,22 +412,33 @@ class RoomWorkerStore(SQLBaseStore):
limit: maximum amount of rooms to retrieve limit: maximum amount of rooms to retrieve
order_by: the sort order of the returned list order_by: the sort order of the returned list
reverse_order: whether to reverse the room list reverse_order: whether to reverse the room list
search_term: a string to filter room names by search_term: a string to filter room names,
canonical alias and room ids by.
Room ID must match exactly. Canonical alias must match a substring of the local part.
Returns: Returns:
A list of room dicts and an integer representing the total number of A list of room dicts and an integer representing the total number of
rooms that exist given this query rooms that exist given this query
""" """
# Filter room names by a string # Filter room names by a string
where_statement = "" where_statement = ""
search_pattern = []
if search_term: if search_term:
where_statement = "WHERE LOWER(state.name) LIKE ?" where_statement = """
WHERE LOWER(state.name) LIKE ?
OR LOWER(state.canonical_alias) LIKE ?
OR state.room_id = ?
"""
# Our postgres db driver converts ? -> %s in SQL strings as that's the # Our postgres db driver converts ? -> %s in SQL strings as that's the
# placeholder for postgres. # placeholder for postgres.
# HOWEVER, if you put a % into your SQL then everything goes wibbly. # HOWEVER, if you put a % into your SQL then everything goes wibbly.
# To get around this, we're going to surround search_term with %'s # To get around this, we're going to surround search_term with %'s
# before giving it to the database in python instead # before giving it to the database in python instead
search_term = "%" + search_term.lower() + "%" search_pattern = [
"%" + search_term.lower() + "%",
"#%" + search_term.lower() + "%:%",
search_term,
]
# Set ordering # Set ordering
if RoomSortOrder(order_by) == RoomSortOrder.SIZE: if RoomSortOrder(order_by) == RoomSortOrder.SIZE:
@ -519,12 +530,9 @@ class RoomWorkerStore(SQLBaseStore):
) )
def _get_rooms_paginate_txn(txn): def _get_rooms_paginate_txn(txn):
# Execute the data query # Add the search term into the WHERE clause
sql_values = (limit, start) # and execute the data query
if search_term: txn.execute(info_sql, search_pattern + [limit, start])
# Add the search term into the WHERE clause
sql_values = (search_term,) + sql_values
txn.execute(info_sql, sql_values)
# Refactor room query data into a structured dictionary # Refactor room query data into a structured dictionary
rooms = [] rooms = []
@ -551,8 +559,7 @@ class RoomWorkerStore(SQLBaseStore):
# Execute the count query # Execute the count query
# Add the search term into the WHERE clause if present # Add the search term into the WHERE clause if present
sql_values = (search_term,) if search_term else () txn.execute(count_sql, search_pattern)
txn.execute(count_sql, sql_values)
room_count = txn.fetchone() room_count = txn.fetchone()
return rooms, room_count[0] return rooms, room_count[0]

View file

@ -680,36 +680,6 @@ class RoomTestCase(unittest.HomeserverTestCase):
reversing the order, etc. reversing the order, etc.
""" """
def _set_canonical_alias(room_id: str, test_alias: str, admin_user_tok: str):
# Create a new alias to this room
url = "/_matrix/client/r0/directory/room/%s" % (
urllib.parse.quote(test_alias),
)
channel = self.make_request(
"PUT",
url.encode("ascii"),
{"room_id": room_id},
access_token=admin_user_tok,
)
self.assertEqual(
200, int(channel.result["code"]), msg=channel.result["body"]
)
# Set this new alias as the canonical alias for this room
self.helper.send_state(
room_id,
"m.room.aliases",
{"aliases": [test_alias]},
tok=admin_user_tok,
state_key="test",
)
self.helper.send_state(
room_id,
"m.room.canonical_alias",
{"alias": test_alias},
tok=admin_user_tok,
)
def _order_test( def _order_test(
order_type: str, order_type: str,
expected_room_list: List[str], expected_room_list: List[str],
@ -781,9 +751,9 @@ class RoomTestCase(unittest.HomeserverTestCase):
) )
# Set room canonical room aliases # Set room canonical room aliases
_set_canonical_alias(room_id_1, "#A_alias:test", self.admin_user_tok) self._set_canonical_alias(room_id_1, "#A_alias:test", self.admin_user_tok)
_set_canonical_alias(room_id_2, "#B_alias:test", self.admin_user_tok) self._set_canonical_alias(room_id_2, "#B_alias:test", self.admin_user_tok)
_set_canonical_alias(room_id_3, "#C_alias:test", self.admin_user_tok) self._set_canonical_alias(room_id_3, "#C_alias:test", self.admin_user_tok)
# Set room member size in the reverse order. room 1 -> 1 member, 2 -> 2, 3 -> 3 # Set room member size in the reverse order. room 1 -> 1 member, 2 -> 2, 3 -> 3
user_1 = self.register_user("bob1", "pass") user_1 = self.register_user("bob1", "pass")
@ -850,7 +820,7 @@ class RoomTestCase(unittest.HomeserverTestCase):
room_id_2 = 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)
room_name_1 = "something" room_name_1 = "something"
room_name_2 = "else" room_name_2 = "LoremIpsum"
# Set the name for each room # Set the name for each room
self.helper.send_state( self.helper.send_state(
@ -866,6 +836,8 @@ class RoomTestCase(unittest.HomeserverTestCase):
tok=self.admin_user_tok, tok=self.admin_user_tok,
) )
self._set_canonical_alias(room_id_1, "#Room_Alias1:test", self.admin_user_tok)
def _search_test( def _search_test(
expected_room_id: Optional[str], expected_room_id: Optional[str],
search_term: str, search_term: str,
@ -914,24 +886,36 @@ class RoomTestCase(unittest.HomeserverTestCase):
r = rooms[0] r = rooms[0]
self.assertEqual(expected_room_id, r["room_id"]) self.assertEqual(expected_room_id, r["room_id"])
# Perform search tests # Test searching by room name
_search_test(room_id_1, "something") _search_test(room_id_1, "something")
_search_test(room_id_1, "thing") _search_test(room_id_1, "thing")
_search_test(room_id_2, "else") _search_test(room_id_2, "LoremIpsum")
_search_test(room_id_2, "se") _search_test(room_id_2, "lorem")
# Test case insensitive # Test case insensitive
_search_test(room_id_1, "SOMETHING") _search_test(room_id_1, "SOMETHING")
_search_test(room_id_1, "THING") _search_test(room_id_1, "THING")
_search_test(room_id_2, "ELSE") _search_test(room_id_2, "LOREMIPSUM")
_search_test(room_id_2, "SE") _search_test(room_id_2, "LOREM")
_search_test(None, "foo") _search_test(None, "foo")
_search_test(None, "bar") _search_test(None, "bar")
_search_test(None, "", expected_http_code=400) _search_test(None, "", expected_http_code=400)
# Test that the whole room id returns the room
_search_test(room_id_1, room_id_1)
# Test that the search by room_id is case sensitive
_search_test(None, room_id_1.lower())
# Test search part of local part of room id do not match
_search_test(None, room_id_1[1:10])
# Test that whole room alias return no result, because of domain
_search_test(None, "#Room_Alias1:test")
# Test search local part of alias
_search_test(room_id_1, "alias1")
def test_search_term_non_ascii(self): def test_search_term_non_ascii(self):
"""Test that searching for a room with non-ASCII characters works correctly""" """Test that searching for a room with non-ASCII characters works correctly"""
@ -1114,6 +1098,32 @@ class RoomTestCase(unittest.HomeserverTestCase):
# the create_room already does the right thing, so no need to verify that we got # the create_room already does the right thing, so no need to verify that we got
# the state events it created. # the state events it created.
def _set_canonical_alias(self, room_id: str, test_alias: str, admin_user_tok: str):
# Create a new alias to this room
url = "/_matrix/client/r0/directory/room/%s" % (urllib.parse.quote(test_alias),)
channel = self.make_request(
"PUT",
url.encode("ascii"),
{"room_id": room_id},
access_token=admin_user_tok,
)
self.assertEqual(200, int(channel.result["code"]), msg=channel.result["body"])
# Set this new alias as the canonical alias for this room
self.helper.send_state(
room_id,
"m.room.aliases",
{"aliases": [test_alias]},
tok=admin_user_tok,
state_key="test",
)
self.helper.send_state(
room_id,
"m.room.canonical_alias",
{"alias": test_alias},
tok=admin_user_tok,
)
class JoinAliasRoomTestCase(unittest.HomeserverTestCase): class JoinAliasRoomTestCase(unittest.HomeserverTestCase):