mirror of
https://github.com/element-hq/synapse.git
synced 2026-11-04 09:07:22 +00:00
Rescind a knock through the remembered server
MSC4233 "Rescinding the knock": with the feature on, `/leave` on a pending remote knock runs the `make_leave`/`send_leave` dance through the server the knock went through, so the room sees the knock end. Until now we only generated a local leave, and the knock stayed pending in the room for ever. The dance is the one we already do to reject an out-of-band invite, so this reuses `do_remotely_reject_invite` and documents that it serves both cases. With no remembered server, or if the dance fails for any reason, we fall back to the local leave. The handler catches every exception because MSC4233 makes the local leave the answer to any failure of the dance, DNS errors included. Fixes #18030. Co-authored-by: Quentin Gliech <quenting@element.io> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
a356f964ac
commit
dd5c807878
2 files changed
+46
-6
No files matched your search
@@ -1663,6 +1663,22 @@ class FederationHandler:
|
||||
async def do_remotely_reject_invite(
|
||||
self, target_hosts: Iterable[str], room_id: str, user_id: str, content: JsonDict
|
||||
) -> tuple[EventBase, int]:
|
||||
"""Leave a room we are not resident in, via the make_leave/send_leave dance.
|
||||
|
||||
Used both to reject an out-of-band invite and, under MSC4233, to
|
||||
rescind an out-of-band knock through the server the knock was
|
||||
fulfilled through: the two are the same federation dance and differ
|
||||
only in which hosts we are given.
|
||||
|
||||
Args:
|
||||
target_hosts: The servers to try, in order.
|
||||
room_id: The room to leave.
|
||||
user_id: The local user leaving.
|
||||
content: The content for the leave event.
|
||||
|
||||
Returns:
|
||||
The persisted leave event and its stream ID.
|
||||
"""
|
||||
origin, event, room_version = await self._make_and_verify_event(
|
||||
target_hosts, room_id, user_id, "leave", content=content
|
||||
)
|
||||
|
||||
@@ -2098,13 +2098,37 @@ class RoomMemberMasterHandler(RoomMemberHandler):
|
||||
|
||||
Implements RoomMemberHandler.remote_rescind_knock
|
||||
"""
|
||||
# TODO: We don't yet support rescinding knocks over federation
|
||||
# as we don't know which homeserver to send it to. An obvious
|
||||
# candidate is the remote homeserver we originally knocked through,
|
||||
# however we don't currently store that information.
|
||||
|
||||
# Just rescind the knock locally
|
||||
knock_event = await self.store.get_event(knock_event_id)
|
||||
|
||||
if self.hs.config.experimental.msc4233_enabled:
|
||||
# MSC4233: route the rescission through the server the knock was
|
||||
# fulfilled through, which we remembered at knock time.
|
||||
via_server = await self.store.get_local_knock_via_server(
|
||||
knock_event.state_key, knock_event.room_id, knock_event_id
|
||||
)
|
||||
if via_server is not None:
|
||||
try:
|
||||
(
|
||||
event,
|
||||
stream_id,
|
||||
) = await self.federation_handler.do_remotely_reject_invite(
|
||||
[via_server],
|
||||
knock_event.room_id,
|
||||
knock_event.state_key,
|
||||
content,
|
||||
)
|
||||
return event.event_id, stream_id
|
||||
except Exception as e:
|
||||
# MSC4233 makes the local rescission below the fallback
|
||||
# for any failure of the dance, from DNS errors upwards.
|
||||
logger.warning(
|
||||
"Failed to rescind knock on %s via %s: %s",
|
||||
knock_event.room_id,
|
||||
via_server,
|
||||
e,
|
||||
)
|
||||
|
||||
# Rescind the knock locally
|
||||
return await self._generate_local_out_of_band_leave(
|
||||
knock_event, txn_id, requester, content
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user