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

Check for space membership during a local join of restricted rooms. #9735

Merged
merged 11 commits into from
Apr 8, 2021
25 changes: 14 additions & 11 deletions synapse/handlers/room_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,14 @@ async def ratelimit_invite(

await self._invites_per_user_limiter.ratelimit(requester, invitee_user_id)

async def _can_join_restricted_room(
async def _can_join_without_invite(
self, state_ids: StateMap[str], room_version: RoomVersion, user_id: str
) -> bool:
"""
Check whether a user can join a restricted room.
Check whether a user can join a room without an invite.

When joining a room with restricted joined rules (as defined in MSC3083),
the membership of spaces must be checked during join.

Args:
state_ids: The state of the room as it currently is.
Expand All @@ -207,10 +210,10 @@ async def _can_join_restricted_room(
if join_rules_event.content.get("join_rule") != JoinRules.MSC3083_RESTRICTED:
return True

# If allowed is of the wrong form, then ignore it (and treat the room as public).
# If allowed is of the wrong form, then only allows invites.
clokep marked this conversation as resolved.
Show resolved Hide resolved
allowed_spaces = join_rules_event.content.get("allow", [])
if not isinstance(allowed_spaces, list):
return True
return False

# Get the list of joined rooms and see if there's an overlap.
joined_rooms = await self.store.get_rooms_for_user(user_id)
Expand All @@ -220,13 +223,13 @@ async def _can_join_restricted_room(
if not isinstance(space, dict):
continue

soace_id = space.get("space")
if not isinstance(soace_id, str):
space_id = space.get("space")
if not isinstance(space_id, str):
continue

# The user was joined to one of the spaces specified, they can join
# this room!
if soace_id in joined_rooms:
if space_id in joined_rooms:
return True

# The user was not in any of the required spaces.
Expand Down Expand Up @@ -289,18 +292,18 @@ async def _local_membership_update(

if event.membership == Membership.JOIN:
newly_joined = True
is_invite = False
user_is_invited = False
if prev_member_event_id:
prev_member_event = await self.store.get_event(prev_member_event_id)
newly_joined = prev_member_event.membership != Membership.JOIN
is_invite = prev_member_event.membership == Membership.INVITE
user_is_invited = prev_member_event.membership == Membership.INVITE

# If the member is not already in the room and is not accepting an invite,
# check if they should be allowed access via membership in a space.
if (
newly_joined
and not is_invite
and not await self._can_join_restricted_room(
and not user_is_invited
and not await self._can_join_without_invite(
prev_state_ids, event.room_version, user_id
)
):
Expand Down