Update MSC3083 support per changes in the MSC. (#10189)

Adds a "type" field and generalize "space" to "room_id".
This commit is contained in:
Patrick Cloke 2021-06-17 12:53:27 -04:00 committed by GitHub
parent fcf3c7032b
commit 8c97d5863f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 31 deletions

1
changelog.d/10189.misc Normal file
View file

@ -0,0 +1 @@
Update MSC3083 support for modifications in the MSC.

View file

@ -65,6 +65,12 @@ class JoinRules:
MSC3083_RESTRICTED = "restricted" MSC3083_RESTRICTED = "restricted"
class RestrictedJoinRuleTypes:
"""Understood types for the allow rules in restricted join rules."""
ROOM_MEMBERSHIP = "m.room_membership"
class LoginType: class LoginType:
PASSWORD = "m.login.password" PASSWORD = "m.login.password"
EMAIL_IDENTITY = "m.login.email.identity" EMAIL_IDENTITY = "m.login.email.identity"

View file

@ -13,7 +13,12 @@
# limitations under the License. # limitations under the License.
from typing import TYPE_CHECKING, Collection, Optional 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.errors import AuthError
from synapse.api.room_versions import RoomVersion from synapse.api.room_versions import RoomVersion
from synapse.events import EventBase from synapse.events import EventBase
@ -42,7 +47,7 @@ class EventAuthHandler:
Check whether a user can join a room without an invite due to 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), 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: Args:
state_ids: The state of the room as it currently is. state_ids: The state of the room as it currently is.
@ -67,20 +72,20 @@ class EventAuthHandler:
if not await self.has_restricted_join_rules(state_ids, room_version): if not await self.has_restricted_join_rules(state_ids, room_version):
return 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. # in any of them.
allowed_spaces = await self.get_spaces_that_allow_join(state_ids) allowed_rooms = await self.get_rooms_that_allow_join(state_ids)
if not await self.is_user_in_rooms(allowed_spaces, user_id): if not await self.is_user_in_rooms(allowed_rooms, user_id):
raise AuthError( raise AuthError(
403, 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( async def has_restricted_join_rules(
self, state_ids: StateMap[str], room_version: RoomVersion self, state_ids: StateMap[str], room_version: RoomVersion
) -> bool: ) -> 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: Args:
state_ids: The state of the room as it currently is. state_ids: The state of the room as it currently is.
@ -102,17 +107,17 @@ class EventAuthHandler:
join_rules_event = await self._store.get_event(join_rules_event_id) join_rules_event = await self._store.get_event(join_rules_event_id)
return join_rules_event.content.get("join_rule") == JoinRules.MSC3083_RESTRICTED 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] self, state_ids: StateMap[str]
) -> Collection[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: 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: 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). # 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) join_rules_event_id = state_ids.get((EventTypes.JoinRules, ""), None)
@ -123,21 +128,25 @@ class EventAuthHandler:
join_rules_event = await self._store.get_event(join_rules_event_id) join_rules_event = await self._store.get_event(join_rules_event_id)
# If allowed is of the wrong form, then only allow invited users. # If allowed is of the wrong form, then only allow invited users.
allowed_spaces = join_rules_event.content.get("allow", []) allow_list = join_rules_event.content.get("allow", [])
if not isinstance(allowed_spaces, list): if not isinstance(allow_list, list):
return () return ()
# Pull out the other room IDs, invalid data gets filtered. # Pull out the other room IDs, invalid data gets filtered.
result = [] result = []
for space in allowed_spaces: for allow in allow_list:
if not isinstance(space, dict): if not isinstance(allow, dict):
continue continue
space_id = space.get("space") # If the type is unexpected, skip it.
if not isinstance(space_id, str): if allow.get("type") != RestrictedJoinRuleTypes.ROOM_MEMBERSHIP:
continue continue
result.append(space_id) room_id = allow.get("room_id")
if not isinstance(room_id, str):
continue
result.append(room_id)
return result return result

View file

@ -160,14 +160,14 @@ class SpaceSummaryHandler:
# Check if the user is a member of any of the allowed spaces # Check if the user is a member of any of the allowed spaces
# from the response. # from the response.
allowed_spaces = room.get("allowed_spaces") allowed_rooms = room.get("allowed_spaces")
if ( if (
not include_room not include_room
and allowed_spaces and allowed_rooms
and isinstance(allowed_spaces, list) and isinstance(allowed_rooms, list)
): ):
include_room = await self._event_auth_handler.is_user_in_rooms( 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 # Finally, if this isn't the requested room, check ourselves
@ -455,11 +455,11 @@ class SpaceSummaryHandler:
if self._event_auth_handler.has_restricted_join_rules( if self._event_auth_handler.has_restricted_join_rules(
state_ids, room_version state_ids, room_version
): ):
allowed_spaces = ( allowed_rooms = (
await self._event_auth_handler.get_spaces_that_allow_join(state_ids) await self._event_auth_handler.get_rooms_that_allow_join(state_ids)
) )
if await self._event_auth_handler.is_user_in_rooms( if await self._event_auth_handler.is_user_in_rooms(
allowed_spaces, requester allowed_rooms, requester
): ):
return True return True
@ -475,10 +475,10 @@ class SpaceSummaryHandler:
if await self._event_auth_handler.has_restricted_join_rules( if await self._event_auth_handler.has_restricted_join_rules(
state_ids, room_version state_ids, room_version
): ):
allowed_spaces = ( allowed_rooms = (
await self._event_auth_handler.get_spaces_that_allow_join(state_ids) 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): if await self._auth.check_host_in_room(space_id, origin):
return True return True
@ -512,11 +512,11 @@ class SpaceSummaryHandler:
) )
room_version = await self._store.get_room_version(room_id) 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( if await self._event_auth_handler.has_restricted_join_rules(
current_state_ids, room_version 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 current_state_ids
) )
@ -533,7 +533,7 @@ class SpaceSummaryHandler:
"guest_can_join": stats["guest_access"] == "can_join", "guest_can_join": stats["guest_access"] == "can_join",
"creation_ts": create_event.origin_server_ts, "creation_ts": create_event.origin_server_ts,
"room_type": create_event.content.get(EventContentFields.ROOM_TYPE), "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 # Filter out Nones rather omit the field altogether