Skip to content

Commit a2bee2f

Browse files
kfivensandhose
andauthored
Add via param to hierarchy enpoint (#18070)
### Pull Request Checklist Implementation of [MSC4235](matrix-org/matrix-spec-proposals#4235) as per suggestion in [pull request 17750](#17750 (comment)). <!-- Please read https://element-hq.github.io/synapse/latest/development/contributing_guide.html before submitting your pull request --> * [x] Pull request is based on the develop branch * [x] Pull request includes a [changelog file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog). The entry should: - Be a short description of your change which makes sense to users. "Fixed a bug that prevented receiving messages from other servers." instead of "Moved X method from `EventStore` to `EventWorkerStore`.". - Use markdown where necessary, mostly for `code blocks`. - End with either a period (.) or an exclamation mark (!). - Start with a capital letter. - Feel free to credit yourself, by adding a sentence "Contributed by @github_username." or "Contributed by [Your Name]." to the end of the entry. * [x] [Code style](https://element-hq.github.io/synapse/latest/code_style.html) is correct (run the [linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters)) --------- Co-authored-by: Quentin Gliech <quenting@element.io>
1 parent 3878699 commit a2bee2f

5 files changed

Lines changed: 89 additions & 3 deletions

File tree

changelog.d/18070.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support for [MSC4235](https://github.com/matrix-org/matrix-spec-proposals/pull/4235): via query param for hierarchy endpoint. Contributed by Krishan (@kfiven).

synapse/config/experimental.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,9 @@ def read_config(
561561
# MSC4076: Add `disable_badge_count`` to pusher configuration
562562
self.msc4076_enabled: bool = experimental.get("msc4076_enabled", False)
563563

564+
# MSC4235: Add `via` param to hierarchy endpoint
565+
self.msc4235_enabled: bool = experimental.get("msc4235_enabled", False)
566+
564567
# MSC4263: Preventing MXID enumeration via key queries
565568
self.msc4263_limit_key_queries_to_users_who_share_rooms = experimental.get(
566569
"msc4263_limit_key_queries_to_users_who_share_rooms",

synapse/handlers/room_summary.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,15 @@ def __init__(self, hs: "HomeServer"):
111111
# If a user tries to fetch the same page multiple times in quick succession,
112112
# only process the first attempt and return its result to subsequent requests.
113113
self._pagination_response_cache: ResponseCache[
114-
Tuple[str, str, bool, Optional[int], Optional[int], Optional[str]]
114+
Tuple[
115+
str,
116+
str,
117+
bool,
118+
Optional[int],
119+
Optional[int],
120+
Optional[str],
121+
Optional[Tuple[str, ...]],
122+
]
115123
] = ResponseCache(
116124
hs.get_clock(),
117125
"get_room_hierarchy",
@@ -126,6 +134,7 @@ async def get_room_hierarchy(
126134
max_depth: Optional[int] = None,
127135
limit: Optional[int] = None,
128136
from_token: Optional[str] = None,
137+
remote_room_hosts: Optional[Tuple[str, ...]] = None,
129138
) -> JsonDict:
130139
"""
131140
Implementation of the room hierarchy C-S API.
@@ -143,6 +152,9 @@ async def get_room_hierarchy(
143152
limit: An optional limit on the number of rooms to return per
144153
page. Must be a positive integer.
145154
from_token: An optional pagination token.
155+
remote_room_hosts: An optional list of remote homeserver server names. If defined,
156+
each host will be used to try and fetch the room hierarchy. Must be a tuple so
157+
that it can be hashed by the `RoomSummaryHandler._pagination_response_cache`.
146158
147159
Returns:
148160
The JSON hierarchy dictionary.
@@ -162,6 +174,7 @@ async def get_room_hierarchy(
162174
max_depth,
163175
limit,
164176
from_token,
177+
remote_room_hosts,
165178
),
166179
self._get_room_hierarchy,
167180
requester.user.to_string(),
@@ -170,6 +183,7 @@ async def get_room_hierarchy(
170183
max_depth,
171184
limit,
172185
from_token,
186+
remote_room_hosts,
173187
)
174188

175189
async def _get_room_hierarchy(
@@ -180,6 +194,7 @@ async def _get_room_hierarchy(
180194
max_depth: Optional[int] = None,
181195
limit: Optional[int] = None,
182196
from_token: Optional[str] = None,
197+
remote_room_hosts: Optional[Tuple[str, ...]] = None,
183198
) -> JsonDict:
184199
"""See docstring for SpaceSummaryHandler.get_room_hierarchy."""
185200

@@ -199,7 +214,7 @@ async def _get_room_hierarchy(
199214

200215
if not local_room:
201216
room_hierarchy = await self._summarize_remote_room_hierarchy(
202-
_RoomQueueEntry(requested_room_id, ()),
217+
_RoomQueueEntry(requested_room_id, remote_room_hosts or ()),
203218
False,
204219
)
205220
root_room_entry = room_hierarchy[0]
@@ -240,7 +255,7 @@ async def _get_room_hierarchy(
240255
processed_rooms = set(pagination_session["processed_rooms"])
241256
else:
242257
# The queue of rooms to process, the next room is last on the stack.
243-
room_queue = [_RoomQueueEntry(requested_room_id, ())]
258+
room_queue = [_RoomQueueEntry(requested_room_id, remote_room_hosts or ())]
244259

245260
# Rooms we have already processed.
246261
processed_rooms = set()

synapse/rest/client/room.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,7 @@ def __init__(self, hs: "HomeServer"):
15381538
super().__init__()
15391539
self._auth = hs.get_auth()
15401540
self._room_summary_handler = hs.get_room_summary_handler()
1541+
self.msc4235_enabled = hs.config.experimental.msc4235_enabled
15411542

15421543
async def on_GET(
15431544
self, request: SynapseRequest, room_id: str
@@ -1547,13 +1548,23 @@ async def on_GET(
15471548
max_depth = parse_integer(request, "max_depth")
15481549
limit = parse_integer(request, "limit")
15491550

1551+
# twisted.web.server.Request.args is incorrectly defined as Optional[Any]
1552+
remote_room_hosts = None
1553+
if self.msc4235_enabled:
1554+
args: Dict[bytes, List[bytes]] = request.args # type: ignore
1555+
via_param = parse_strings_from_args(
1556+
args, "org.matrix.msc4235.via", required=False
1557+
)
1558+
remote_room_hosts = tuple(via_param or [])
1559+
15501560
return 200, await self._room_summary_handler.get_room_hierarchy(
15511561
requester,
15521562
room_id,
15531563
suggested_only=parse_boolean(request, "suggested_only", default=False),
15541564
max_depth=max_depth,
15551565
limit=limit,
15561566
from_token=parse_string(request, "from"),
1567+
remote_room_hosts=remote_room_hosts,
15571568
)
15581569

15591570

tests/handlers/test_room_summary.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,62 @@ async def get_room_hierarchy(
10801080
self.assertEqual(federation_requests, 2)
10811081
self._assert_hierarchy(result, expected)
10821082

1083+
def test_fed_remote_room_hosts(self) -> None:
1084+
"""
1085+
Test if requested room is available over federation using via's.
1086+
"""
1087+
fed_hostname = self.hs.hostname + "2"
1088+
fed_space = "#fed_space:" + fed_hostname
1089+
fed_subroom = "#fed_sub_room:" + fed_hostname
1090+
1091+
remote_room_hosts = tuple(fed_hostname)
1092+
1093+
requested_room_entry = _RoomEntry(
1094+
fed_space,
1095+
{
1096+
"room_id": fed_space,
1097+
"world_readable": True,
1098+
"join_rule": "public",
1099+
"room_type": RoomTypes.SPACE,
1100+
},
1101+
[
1102+
{
1103+
"type": EventTypes.SpaceChild,
1104+
"room_id": fed_space,
1105+
"state_key": fed_subroom,
1106+
"content": {"via": [fed_hostname]},
1107+
}
1108+
],
1109+
)
1110+
child_room = {
1111+
"room_id": fed_subroom,
1112+
"world_readable": True,
1113+
"join_rule": "public",
1114+
}
1115+
1116+
async def summarize_remote_room_hierarchy(
1117+
_self: Any, room: Any, suggested_only: bool
1118+
) -> Tuple[Optional[_RoomEntry], Dict[str, JsonDict], Set[str]]:
1119+
return requested_room_entry, {fed_subroom: child_room}, set()
1120+
1121+
expected = [
1122+
(fed_space, [fed_subroom]),
1123+
(fed_subroom, ()),
1124+
]
1125+
1126+
with mock.patch(
1127+
"synapse.handlers.room_summary.RoomSummaryHandler._summarize_remote_room_hierarchy",
1128+
new=summarize_remote_room_hierarchy,
1129+
):
1130+
result = self.get_success(
1131+
self.handler.get_room_hierarchy(
1132+
create_requester(self.user),
1133+
fed_space,
1134+
remote_room_hosts=remote_room_hosts,
1135+
)
1136+
)
1137+
self._assert_hierarchy(result, expected)
1138+
10831139

10841140
class RoomSummaryTestCase(unittest.HomeserverTestCase):
10851141
servlets = [

0 commit comments

Comments
 (0)