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

Prevent 0-member/null room_version rooms from appearing in group room queries #7465

Merged
merged 10 commits into from
May 15, 2020
1 change: 1 addition & 0 deletions changelog.d/7465.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent rooms with 0 members or with invalid version strings from breaking group queries.
92 changes: 78 additions & 14 deletions synapse/storage/data_stores/main/group_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,78 @@ def get_invited_users_in_group(self, group_id):
desc="get_invited_users_in_group",
)

def get_rooms_in_group(self, group_id, include_private=False):
def get_rooms_in_group(self, group_id: str, include_private: bool = False):
"""Retrieve the rooms that belong to a given group. Does not return rooms that
lack members.

Args:
group_id: The ID of the group to query for rooms
include_private: Whether to return private rooms in results

Returns:
Deferred[List[Dict[str, str|bool]]]: A list of dictionaries, each in the
form of:

{
"room_id": "!a_room_id:example.com", # The ID of the room
"is_public": False # Whether this is a public room or not
}
"""
# TODO: Pagination

keyvalues = {"group_id": group_id}
if not include_private:
keyvalues["is_public"] = True
def _get_rooms_in_group_txn(txn):
sql = """
SELECT room_id, is_public FROM group_rooms
WHERE group_id = ?
AND room_id IN (
SELECT group_rooms.room_id FROM group_rooms
LEFT JOIN room_stats_current ON
group_rooms.room_id = room_stats_current.room_id
AND joined_members > 0
AND local_users_in_room > 0
LEFT JOIN rooms ON
group_rooms.room_id = rooms.room_id
AND (room_version <> '') = ?
)
"""
args = [group_id, False]

return self.db.simple_select_list(
table="group_rooms",
keyvalues=keyvalues,
retcols=("room_id", "is_public"),
desc="get_rooms_in_group",
)
if not include_private:
sql += " AND is_public = ?"
args += [True]

txn.execute(sql, args)

return [
{"room_id": room_id, "is_public": is_public}
for room_id, is_public in txn
]

def get_rooms_for_summary_by_category(self, group_id, include_private=False):
return self.db.runInteraction("get_rooms_in_group", _get_rooms_in_group_txn)

def get_rooms_for_summary_by_category(
self, group_id: str, include_private: bool = False,
):
"""Get the rooms and categories that should be included in a summary request

Returns ([rooms], [categories])
Args:
group_id: The ID of the group to query the summary for
include_private: Whether to return private rooms in results

Returns:
Deferred[Tuple[List, Dict]]: A tuple containing:

* A list of dictionaries with the keys:
* "room_id": str, the room ID
* "is_public": bool, whether the room is public
* "category_id": str|None, the category ID if set, else None
* "order": int, the sort order of rooms

* A dictionary with the key:
* category_id (str): a dictionary with the keys:
* "is_public": bool, whether the category is public
* "profile": str, the category profile
* "order": int, the sort order of rooms in this category
"""

def _get_rooms_for_summary_txn(txn):
Expand All @@ -97,13 +151,23 @@ def _get_rooms_for_summary_txn(txn):
SELECT room_id, is_public, category_id, room_order
FROM group_summary_rooms
WHERE group_id = ?
AND room_id IN (
SELECT group_rooms.room_id FROM group_rooms
LEFT JOIN room_stats_current ON
group_rooms.room_id = room_stats_current.room_id
AND joined_members > 0
AND local_users_in_room > 0
LEFT JOIN rooms ON
group_rooms.room_id = rooms.room_id
AND (room_version <> '') = ?
)
"""

if not include_private:
sql += " AND is_public = ?"
txn.execute(sql, (group_id, True))
txn.execute(sql, (group_id, False, True))
else:
txn.execute(sql, (group_id,))
txn.execute(sql, (group_id, False))

rooms = [
{
Expand Down