Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/20154.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return `allowed_room_ids` in the client [`GET /_matrix/client/v1/rooms/{roomId}/hierarchy`](https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv1roomsroomidhierarchy) response, as required since Matrix 1.15.
18 changes: 4 additions & 14 deletions synapse/handlers/room_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ async def _get_room_hierarchy(
# inaccessible to the requesting user.
if room_entry:
# Add the room (including the stripped m.space.child events).
rooms_result.append(room_entry.as_json(for_client=True))
rooms_result.append(room_entry.as_json())

# If this room is not at the max-depth, check if there are any
# children to process.
Expand Down Expand Up @@ -872,7 +872,8 @@ async def get_room_summary(
remote_room_hosts: list[str] | None = None,
) -> JsonDict:
"""
Implementation of the room summary C-S API from MSC3266
Implementation of the room summary C-S API, see
https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv1room_summaryroomidoralias

Args:
requester: user id of the user making this request, will be None
Expand Down Expand Up @@ -980,25 +981,14 @@ class _RoomEntry:
# This may not include all children.
children_state_events: Sequence[JsonDict] = ()

def as_json(self, for_client: bool = False) -> JsonDict:
def as_json(self) -> JsonDict:
"""
Returns a JSON dictionary suitable for the room hierarchy endpoint.

It returns the room summary including the stripped m.space.child events
as a sub-key.

Args:
for_client: If true, any server-server only fields are stripped from
the result.

"""
result = dict(self.room)

# Before returning to the client, remove the allowed_room_ids key, if it
# exists.
if for_client:
result.pop("allowed_room_ids", False)

result["children_state"] = self.children_state_events
return result

Expand Down
49 changes: 46 additions & 3 deletions tests/handlers/test_room_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
JoinRules,
Membership,
RestrictedJoinRuleTypes,
RoomEncryptionAlgorithms,
RoomTypes,
)
from synapse.api.errors import AuthError, NotFoundError, SynapseError
Expand Down Expand Up @@ -184,9 +185,6 @@ def _assert_hierarchy(
result_room_ids = []
result_children_ids = []
for result_room in result["rooms"]:
# Ensure federation results are not leaking over the client-server API.
self.assertNotIn("allowed_room_ids", result_room)

result_room_ids.append(result_room["room_id"])
result_children_ids.append(
[
Expand Down Expand Up @@ -489,6 +487,44 @@ def test_filtering(self) -> None:
)
self._assert_hierarchy(result, expected)

def test_summary_fields(self) -> None:
"""
The room entries returned to clients include the `room_version`,
`encryption` and `allowed_room_ids` fields, added to the client
`/hierarchy` API in Matrix 1.15.

See https://spec.matrix.org/v1.19/client-server-api/#get_matrixclientv1roomsroomidhierarchy
"""
restricted_room = self._create_room_with_join_rule(
JoinRules.RESTRICTED,
room_version=RoomVersions.V8.identifier,
allow=[
{
"type": RestrictedJoinRuleTypes.ROOM_MEMBERSHIP,
"room_id": self.space,
"via": [self.hs.hostname],
}
],
)
self.helper.send_state(
restricted_room,
event_type=EventTypes.RoomEncryption,
body={"algorithm": RoomEncryptionAlgorithms.DEFAULT},
tok=self.token,
)

result = self.get_success(
self.handler.get_room_hierarchy(create_requester(self.user), self.space)
)
room_entries = {entry["room_id"]: entry for entry in result["rooms"]}
entry = room_entries[restricted_room]
self.assertEqual(entry["room_version"], RoomVersions.V8.identifier)
self.assertEqual(entry["encryption"], RoomEncryptionAlgorithms.DEFAULT)
self.assertEqual(entry["allowed_room_ids"], [self.space])

# Rooms without restricted join rules should not have the field at all.
self.assertNotIn("allowed_room_ids", room_entries[self.room])

def test_complex_space(self) -> None:
"""
Create a "complex" space to see how it handles things like loops and subspaces.
Expand Down Expand Up @@ -960,6 +996,13 @@ async def summarize_remote_room_hierarchy(
)
self._assert_hierarchy(result, expected)

# `allowed_room_ids` returned over federation should be passed through
# to the client.
room_entries = {entry["room_id"]: entry for entry in result["rooms"]}
self.assertEqual(
room_entries[restricted_accessible_room]["allowed_room_ids"], [self.room]
)

def test_fed_invited(self) -> None:
"""
A room which the user was invited to should be included in the response.
Expand Down
Loading