mirror of
https://github.com/element-hq/synapse.git
synced 2026-08-26 05:10:16 +00:00
feat: Include allowed_room_ids in the /summary client-server API response for rooms with restricted join rules, as required by Matrix 1.15. (#19762)
Currently the `/summary` endpoint on the client and federation APIs does not include the allowed_room_ids field, that is present on the /hierarchy API. This is required by the 1.15 spec and this is what this PR does. Complement test: https://github.com/matrix-org/complement/pull/873 Part of https://github.com/element-hq/synapse/issues/18731
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
Include `allowed_room_ids` in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15.
|
||||
Contributed by @FrenchGithubUser @Famedly.
|
||||
@@ -513,7 +513,7 @@ class RoomSummaryHandler:
|
||||
):
|
||||
return None
|
||||
|
||||
room_entry = await self._build_room_entry(room_id, for_federation=bool(origin))
|
||||
room_entry = await self._build_room_entry(room_id)
|
||||
|
||||
# If the room is not a space return just the room information.
|
||||
if room_entry.get("room_type") != RoomTypes.SPACE or not include_children:
|
||||
@@ -769,14 +769,12 @@ class RoomSummaryHandler:
|
||||
# pending invite, etc.
|
||||
return await self._is_local_room_accessible(room_id, requester)
|
||||
|
||||
async def _build_room_entry(self, room_id: str, for_federation: bool) -> JsonDict:
|
||||
async def _build_room_entry(self, room_id: str) -> JsonDict:
|
||||
"""
|
||||
Generate en entry summarising a single room.
|
||||
|
||||
Args:
|
||||
room_id: The room ID to summarize.
|
||||
for_federation: True if this is a summary requested over federation
|
||||
(which includes additional fields).
|
||||
|
||||
Returns:
|
||||
The JSON dictionary for the room.
|
||||
@@ -805,24 +803,30 @@ class RoomSummaryHandler:
|
||||
"encryption": stats.encryption,
|
||||
}
|
||||
|
||||
# Federation requests need to provide additional information so the
|
||||
# requested server is able to filter the response appropriately.
|
||||
if for_federation:
|
||||
current_state_ids = (
|
||||
await self._storage_controllers.state.get_current_state_ids(room_id)
|
||||
# Include allowed_room_ids for rooms with restricted join rules so that
|
||||
# clients can determine which memberships grant access.
|
||||
# Only the join rules event is needed for both has_restricted_join_rules
|
||||
# and get_rooms_that_allow_join, so avoid fetching full state.
|
||||
join_rules_state_ids = (
|
||||
await self._storage_controllers.state.get_current_state_ids(
|
||||
room_id,
|
||||
state_filter=StateFilter.from_types([(EventTypes.JoinRules, "")]),
|
||||
)
|
||||
room_version = await self._store.get_room_version(room_id)
|
||||
)
|
||||
|
||||
if await self._event_auth_handler.has_restricted_join_rules(
|
||||
current_state_ids, room_version
|
||||
):
|
||||
allowed_rooms = (
|
||||
await self._event_auth_handler.get_rooms_that_allow_join(
|
||||
current_state_ids
|
||||
)
|
||||
)
|
||||
if allowed_rooms:
|
||||
entry["allowed_room_ids"] = allowed_rooms
|
||||
try:
|
||||
room_version = await self._store.get_room_version(room_id)
|
||||
except UnsupportedRoomVersionError:
|
||||
room_version = None
|
||||
|
||||
if room_version and await self._event_auth_handler.has_restricted_join_rules(
|
||||
join_rules_state_ids, room_version
|
||||
):
|
||||
allowed_rooms = await self._event_auth_handler.get_rooms_that_allow_join(
|
||||
join_rules_state_ids
|
||||
)
|
||||
if allowed_rooms:
|
||||
entry["allowed_room_ids"] = allowed_rooms
|
||||
|
||||
# Filter out Nones – rather omit the field altogether
|
||||
room_entry = {k: v for k, v in entry.items() if v is not None}
|
||||
@@ -932,7 +936,6 @@ class RoomSummaryHandler:
|
||||
raise NotFoundError("Room not found or is not accessible")
|
||||
|
||||
room = dict(room_entry.room)
|
||||
room.pop("allowed_room_ids", None)
|
||||
|
||||
# If there was a requester, add their membership.
|
||||
# We keep the membership in the local membership table unless the
|
||||
|
||||
@@ -1219,6 +1219,60 @@ class RoomSummaryTestCase(unittest.HomeserverTestCase):
|
||||
result = self.get_success(self.handler.get_room_summary(user2, self.room))
|
||||
self.assertEqual(result.get("room_id"), self.room)
|
||||
|
||||
def test_allowed_room_ids_local(self) -> None:
|
||||
"""allowed_room_ids is returned for a local room with restricted join rules."""
|
||||
# Create a space that the restricted room will allow membership from.
|
||||
space = self.helper.create_room_as(
|
||||
self.user,
|
||||
tok=self.token,
|
||||
extra_content={
|
||||
"creation_content": {"type": RoomTypes.SPACE},
|
||||
"initial_state": [
|
||||
{
|
||||
"type": EventTypes.JoinRules,
|
||||
"state_key": "",
|
||||
"content": {"join_rule": JoinRules.PUBLIC},
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
# Create a room version 8 room with join_rule=restricted allowing members
|
||||
# of the space above.
|
||||
restricted_room = self.helper.create_room_as(
|
||||
self.user,
|
||||
room_version=RoomVersions.V8.identifier,
|
||||
tok=self.token,
|
||||
extra_content={
|
||||
"initial_state": [
|
||||
{
|
||||
"type": EventTypes.JoinRules,
|
||||
"state_key": "",
|
||||
"content": {
|
||||
"join_rule": JoinRules.RESTRICTED,
|
||||
"allow": [
|
||||
{
|
||||
"type": RestrictedJoinRuleTypes.ROOM_MEMBERSHIP,
|
||||
"room_id": space,
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
result = self.get_success(
|
||||
self.handler.get_room_summary(self.user, restricted_room)
|
||||
)
|
||||
self.assertEqual(result.get("room_id"), restricted_room)
|
||||
self.assertEqual(result.get("allowed_room_ids"), [space])
|
||||
|
||||
def test_allowed_room_ids_absent_without_restricted_join_rules(self) -> None:
|
||||
"""allowed_room_ids is absent for rooms that do not use restricted join rules."""
|
||||
result = self.get_success(self.handler.get_room_summary(self.user, self.room))
|
||||
self.assertNotIn("allowed_room_ids", result)
|
||||
|
||||
def test_fed(self) -> None:
|
||||
"""
|
||||
Return data over federation and ensure that it is handled properly.
|
||||
|
||||
Reference in New Issue
Block a user