forked from MirrorHub/synapse
Update MSC3083 support per changes in the MSC. (#10189)
Adds a "type" field and generalize "space" to "room_id".
This commit is contained in:
parent
fcf3c7032b
commit
8c97d5863f
4 changed files with 47 additions and 31 deletions
1
changelog.d/10189.misc
Normal file
1
changelog.d/10189.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Update MSC3083 support for modifications in the MSC.
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue