From 83aca3f0972cf062f71127eaab95dbf57584ce03 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Mon, 22 Sep 2025 15:50:52 +0200 Subject: [PATCH] Implement MSC4169: backwards-compatible redaction sending for rooms < v11 using the /send endpoint (#18898) Implement [MSC4169](https://github.com/matrix-org/matrix-spec-proposals/pull/4169) While there is a dedicated API endpoint for redactions, being able to send redactions using the normal send endpoint is useful when using [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140) for sending delayed redactions to replicate expiring messages. Currently this would only work on rooms >= v11 but fail with an internal server error on older room versions when setting the `redacts` field in the content, since older rooms would require that field to be outside of `content`. We can address this by copying it over if necessary. Relevant spec at https://spec.matrix.org/v1.8/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property --------- Co-authored-by: Tulir Asokan --- changelog.d/18898.feature | 1 + synapse/config/experimental.py | 3 +++ synapse/handlers/message.py | 27 +++++++++++++++++++++++++-- synapse/rest/client/versions.py | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 changelog.d/18898.feature diff --git a/changelog.d/18898.feature b/changelog.d/18898.feature new file mode 100644 index 000000000..bf31dd55d --- /dev/null +++ b/changelog.d/18898.feature @@ -0,0 +1 @@ +Support [MSC4169](https://github.com/matrix-org/matrix-spec-proposals/pull/4169) for backwards-compatible redaction sending using the `/send` endpoint. Contributed by @SpiritCroc @ Beeper. diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py index d086deab3..d7a3d6755 100644 --- a/synapse/config/experimental.py +++ b/synapse/config/experimental.py @@ -556,6 +556,9 @@ class ExperimentalConfig(Config): # MSC4133: Custom profile fields self.msc4133_enabled: bool = experimental.get("msc4133_enabled", False) + # MSC4169: Backwards-compatible redaction sending using `/send` + self.msc4169_enabled: bool = experimental.get("msc4169_enabled", False) + # MSC4210: Remove legacy mentions self.msc4210_enabled: bool = experimental.get("msc4210_enabled", False) diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index d850b617d..6db031a4b 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -1013,14 +1013,37 @@ class EventCreationHandler: await self.clock.sleep(random.randint(1, 10)) raise ShadowBanError() - if ratelimit: + room_version = None + + if ( + event_dict["type"] == EventTypes.Redaction + and "redacts" in event_dict["content"] + and self.hs.config.experimental.msc4169_enabled + ): room_id = event_dict["room_id"] try: room_version = await self.store.get_room_version(room_id) except NotFoundError: - # The room doesn't exist. raise AuthError(403, f"User {requester.user} not in room {room_id}") + if not room_version.updated_redaction_rules: + # Legacy room versions need the "redacts" field outside of the event's + # content. However clients may still send it within the content, so move + # the field if necessary for compatibility. + redacts = event_dict.get("redacts") or event_dict["content"].pop( + "redacts", None + ) + if redacts is not None and "redacts" not in event_dict: + event_dict["redacts"] = redacts + + if ratelimit: + if room_version is None: + room_id = event_dict["room_id"] + try: + room_version = await self.store.get_room_version(room_id) + except NotFoundError: + raise AuthError(403, f"User {requester.user} not in room {room_id}") + if room_version.updated_redaction_rules: redacts = event_dict["content"].get("redacts") else: diff --git a/synapse/rest/client/versions.py b/synapse/rest/client/versions.py index 1b8efd98c..20395430d 100644 --- a/synapse/rest/client/versions.py +++ b/synapse/rest/client/versions.py @@ -180,6 +180,8 @@ class VersionsRestServlet(RestServlet): "org.matrix.msc4155": self.config.experimental.msc4155_enabled, # MSC4306: Support for thread subscriptions "org.matrix.msc4306": self.config.experimental.msc4306_enabled, + # MSC4169: Backwards-compatible redaction sending using `/send` + "com.beeper.msc4169": self.config.experimental.msc4169_enabled, }, }, )