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

Commit

Permalink
Abstract out a method for checking if a remote room should be included.
Browse files Browse the repository at this point in the history
  • Loading branch information
clokep committed Aug 9, 2021
1 parent f8e86b7 commit 48c358f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 43 deletions.
1 change: 1 addition & 0 deletions changelog.d/10560.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add pagination to the spaces summary based on updates to [MSC2946](https://github.com/matrix-org/matrix-doc/pull/2946).
97 changes: 54 additions & 43 deletions synapse/handlers/space_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,48 +158,10 @@ async def get_space_summary(
room = room_entry.room
fed_room_id = room_entry.room_id

# The room should only be included in the summary if:
# a. the user is in the room;
# b. the room is world readable; or
# c. the user could join the room, e.g. the join rules
# are set to public or the user is in a space that
# has been granted access to the room.
#
# Note that we know the user is not in the root room (which is
# why the remote call was made in the first place), but the user
# could be in one of the children rooms and we just didn't know
# about the link.

# The API doesn't return the room version so assume that a
# join rule of knock is valid.
include_room = (
room.get("join_rules") in (JoinRules.PUBLIC, JoinRules.KNOCK)
or room.get("world_readable") is True
)

# Check if the user is a member of any of the allowed spaces
# from the response.
allowed_rooms = room.get("allowed_room_ids") or room.get(
"allowed_spaces"
)
if (
not include_room
and allowed_rooms
and isinstance(allowed_rooms, list)
):
include_room = await self._event_auth_handler.is_user_in_rooms(
allowed_rooms, requester
)

# Finally, if this isn't the requested room, check ourselves
# if we can access the room.
if not include_room and fed_room_id != queue_entry.room_id:
include_room = await self._is_room_accessible(
fed_room_id, requester, None
)

# The user can see the room, include it!
if include_room:
if await self._is_remote_room_accessible(
queue_entry.room_id, requester, fed_room_id, room
):
# Before returning to the client, remove the allowed_room_ids
# and allowed_spaces keys.
room.pop("allowed_room_ids", None)
Expand Down Expand Up @@ -336,7 +298,7 @@ async def _summarize_local_room(
Returns:
A room entry if the room should be returned. None, otherwise.
"""
if not await self._is_room_accessible(room_id, requester, origin):
if not await self._is_local_room_accessible(room_id, requester, origin):
return None

room_entry = await self._build_room_entry(room_id, for_federation=bool(origin))
Expand Down Expand Up @@ -438,7 +400,7 @@ async def _summarize_remote_room(

return results

async def _is_room_accessible(
async def _is_local_room_accessible(
self, room_id: str, requester: Optional[str], origin: Optional[str]
) -> bool:
"""
Expand Down Expand Up @@ -550,6 +512,55 @@ async def _is_room_accessible(
)
return False

async def _is_remote_room_accessible(
self, requested_room_id: str, requester: str, room_id: str, room: JsonDict
) -> bool:
"""
Calculate whether the room received over federation should be shown in the spaces summary.
It should be included if:
* The requester is joined or can join the room (per MSC3173).
* The history visibility is set to world readable.
Note that we know the user is not in the requested room (which is why the
remote call was made in the first place), but the user could be in one
of the children rooms and we just didn't know about the link.
Args:
requested_room_id: The room ID which was requested.
requester: The user requesting the summary.
room_id: The child room ID returned over federation.
room: The summary of the child room returned over federation.
Returns:
True if the room should be included in the spaces summary.
"""
# The API doesn't return the room version so assume that a
# join rule of knock is valid.
if (
room.get("join_rules") in (JoinRules.PUBLIC, JoinRules.KNOCK)
or room.get("world_readable") is True
):
return True

# Check if the user is a member of any of the allowed spaces
# from the response.
allowed_rooms = room.get("allowed_room_ids") or room.get("allowed_spaces")
if allowed_rooms and isinstance(allowed_rooms, list):
if await self._event_auth_handler.is_user_in_rooms(
allowed_rooms, requester
):
return True

# Finally, if this isn't the requested room, check ourselves
# if we can access the room.
if room_id != requested_room_id:
if await self._is_local_room_accessible(room_id, requester, None):
return True

return False

async def _build_room_entry(self, room_id: str, for_federation: bool) -> JsonDict:
"""
Generate en entry suitable for the 'rooms' list in the summary response.
Expand Down

0 comments on commit 48c358f

Please sign in to comment.