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

Commit

Permalink
Update MSC3083 support per changes in the MSC. (#10189)
Browse files Browse the repository at this point in the history
Adds a "type" field and generalize "space" to "room_id".
  • Loading branch information
clokep authored Jun 17, 2021
1 parent fcf3c70 commit 8c97d58
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 31 deletions.
1 change: 1 addition & 0 deletions changelog.d/10189.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update MSC3083 support for modifications in the MSC.
6 changes: 6 additions & 0 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ class JoinRules:
MSC3083_RESTRICTED = "restricted"


class RestrictedJoinRuleTypes:
"""Understood types for the allow rules in restricted join rules."""

ROOM_MEMBERSHIP = "m.room_membership"


class LoginType:
PASSWORD = "m.login.password"
EMAIL_IDENTITY = "m.login.email.identity"
Expand Down
45 changes: 27 additions & 18 deletions synapse/handlers/event_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
# limitations under the License.
from typing import TYPE_CHECKING, Collection, Optional

from synapse.api.constants import EventTypes, JoinRules, Membership
from synapse.api.constants import (
EventTypes,
JoinRules,
Membership,
RestrictedJoinRuleTypes,
)
from synapse.api.errors import AuthError
from synapse.api.room_versions import RoomVersion
from synapse.events import EventBase
Expand Down Expand Up @@ -42,7 +47,7 @@ async def check_restricted_join_rules(
Check whether a user can join a room without an invite due to restricted join rules.
When joining a room with restricted joined rules (as defined in MSC3083),
the membership of spaces must be checked during a room join.
the membership of rooms must be checked during a room join.
Args:
state_ids: The state of the room as it currently is.
Expand All @@ -67,20 +72,20 @@ async def check_restricted_join_rules(
if not await self.has_restricted_join_rules(state_ids, room_version):
return

# Get the spaces which allow access to this room and check if the user is
# Get the rooms which allow access to this room and check if the user is
# in any of them.
allowed_spaces = await self.get_spaces_that_allow_join(state_ids)
if not await self.is_user_in_rooms(allowed_spaces, user_id):
allowed_rooms = await self.get_rooms_that_allow_join(state_ids)
if not await self.is_user_in_rooms(allowed_rooms, user_id):
raise AuthError(
403,
"You do not belong to any of the required spaces to join this room.",
"You do not belong to any of the required rooms to join this room.",
)

async def has_restricted_join_rules(
self, state_ids: StateMap[str], room_version: RoomVersion
) -> bool:
"""
Return if the room has the proper join rules set for access via spaces.
Return if the room has the proper join rules set for access via rooms.
Args:
state_ids: The state of the room as it currently is.
Expand All @@ -102,17 +107,17 @@ async def has_restricted_join_rules(
join_rules_event = await self._store.get_event(join_rules_event_id)
return join_rules_event.content.get("join_rule") == JoinRules.MSC3083_RESTRICTED

async def get_spaces_that_allow_join(
async def get_rooms_that_allow_join(
self, state_ids: StateMap[str]
) -> Collection[str]:
"""
Generate a list of spaces which allow access to a room.
Generate a list of rooms in which membership allows access to a room.
Args:
state_ids: The state of the room as it currently is.
state_ids: The current state of the room the user wishes to join
Returns:
A collection of spaces which provide membership to the room.
A collection of room IDs. Membership in any of the rooms in the list grants the ability to join the target room.
"""
# If there's no join rule, then it defaults to invite (so this doesn't apply).
join_rules_event_id = state_ids.get((EventTypes.JoinRules, ""), None)
Expand All @@ -123,21 +128,25 @@ async def get_spaces_that_allow_join(
join_rules_event = await self._store.get_event(join_rules_event_id)

# If allowed is of the wrong form, then only allow invited users.
allowed_spaces = join_rules_event.content.get("allow", [])
if not isinstance(allowed_spaces, list):
allow_list = join_rules_event.content.get("allow", [])
if not isinstance(allow_list, list):
return ()

# Pull out the other room IDs, invalid data gets filtered.
result = []
for space in allowed_spaces:
if not isinstance(space, dict):
for allow in allow_list:
if not isinstance(allow, dict):
continue

# If the type is unexpected, skip it.
if allow.get("type") != RestrictedJoinRuleTypes.ROOM_MEMBERSHIP:
continue

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

result.append(space_id)
result.append(room_id)

return result

Expand Down
26 changes: 13 additions & 13 deletions synapse/handlers/space_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ async def get_space_summary(

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

# Finally, if this isn't the requested room, check ourselves
Expand Down Expand Up @@ -455,11 +455,11 @@ async def _is_room_accessible(
if self._event_auth_handler.has_restricted_join_rules(
state_ids, room_version
):
allowed_spaces = (
await self._event_auth_handler.get_spaces_that_allow_join(state_ids)
allowed_rooms = (
await self._event_auth_handler.get_rooms_that_allow_join(state_ids)
)
if await self._event_auth_handler.is_user_in_rooms(
allowed_spaces, requester
allowed_rooms, requester
):
return True

Expand All @@ -475,10 +475,10 @@ async def _is_room_accessible(
if await self._event_auth_handler.has_restricted_join_rules(
state_ids, room_version
):
allowed_spaces = (
await self._event_auth_handler.get_spaces_that_allow_join(state_ids)
allowed_rooms = (
await self._event_auth_handler.get_rooms_that_allow_join(state_ids)
)
for space_id in allowed_spaces:
for space_id in allowed_rooms:
if await self._auth.check_host_in_room(space_id, origin):
return True

Expand Down Expand Up @@ -512,11 +512,11 @@ async def _build_room_entry(self, room_id: str) -> JsonDict:
)

room_version = await self._store.get_room_version(room_id)
allowed_spaces = None
allowed_rooms = None
if await self._event_auth_handler.has_restricted_join_rules(
current_state_ids, room_version
):
allowed_spaces = await self._event_auth_handler.get_spaces_that_allow_join(
allowed_rooms = await self._event_auth_handler.get_rooms_that_allow_join(
current_state_ids
)

Expand All @@ -533,7 +533,7 @@ async def _build_room_entry(self, room_id: str) -> JsonDict:
"guest_can_join": stats["guest_access"] == "can_join",
"creation_ts": create_event.origin_server_ts,
"room_type": create_event.content.get(EventContentFields.ROOM_TYPE),
"allowed_spaces": allowed_spaces,
"allowed_spaces": allowed_rooms,
}

# Filter out Nones – rather omit the field altogether
Expand Down

0 comments on commit 8c97d58

Please sign in to comment.