diff --git a/changelog.d/18898.feature b/changelog.d/18898.feature new file mode 100644 index 0000000000..bf31dd55d1 --- /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 5f2749886a..b45e96b0fa 100644 --- a/synapse/config/experimental.py +++ b/synapse/config/experimental.py @@ -552,6 +552,9 @@ def read_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 cb64df2d01..2931f3d9d3 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -1003,14 +1003,38 @@ async def create_and_send_nonmember_event( 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 copy + # 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 fa39eb9e6d..fed56976de 100644 --- a/synapse/rest/client/versions.py +++ b/synapse/rest/client/versions.py @@ -177,6 +177,8 @@ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]: "uk.tcpip.msc4133": self.config.experimental.msc4133_enabled, # MSC4155: Invite filtering "org.matrix.msc4155": self.config.experimental.msc4155_enabled, + # MSC4169: Backwards-compatible redaction sending using `/send` + "com.beeper.msc4169": self.config.experimental.msc4169_enabled, }, }, )