From 3c12c2b6ca5df828dbd57b51263bbd71a73c3333 Mon Sep 17 00:00:00 2001
From: strawberry <strawberry@puppygock.gay>
Date: Tue, 27 Feb 2024 22:39:03 -0500
Subject: [PATCH] fix: add top level "redacts" key for v11 redactions

at least with Element Web: they still rely on the
"redacts" top level key. it was reported that
federated redactions were not working for v11 rooms
with conduwuit. after adding back the top level
key when appending a PDU to the timeline, they
now work again.

spec below says to continue adding the top level
key for compatibility with older clients.

https://spec.matrix.org/v1.9/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property

Signed-off-by: strawberry <strawberry@puppygock.gay>
---
 src/service/rooms/timeline/mod.rs | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs
index 38b038e06..7cebaf304 100644
--- a/src/service/rooms/timeline/mod.rs
+++ b/src/service/rooms/timeline/mod.rs
@@ -318,6 +318,28 @@ pub async fn append_pdu<'a>(
         let mut pdu_id = shortroomid.to_be_bytes().to_vec();
         pdu_id.extend_from_slice(&count2.to_be_bytes());
 
+        // https://spec.matrix.org/v1.9/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property
+        // For backwards-compatibility with older clients,
+        // servers should add a redacts property to the top level of m.room.redaction events in when serving such events over the Client-Server API.
+        if pdu.kind == TimelineEventType::RoomRedaction
+            && services().rooms.state.get_room_version(&pdu.room_id)? == RoomVersionId::V11
+        {
+            #[derive(Deserialize)]
+            struct Redaction {
+                redacts: Option<OwnedEventId>,
+            }
+
+            let content = serde_json::from_str::<Redaction>(pdu.content.get())
+                .map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?;
+
+            if let Some(redact_id) = &content.redacts {
+                pdu_json.insert(
+                    "redacts".to_owned(),
+                    CanonicalJsonValue::String(redact_id.to_string()),
+                );
+            }
+        }
+
         // Insert pdu
         self.db.append_pdu(&pdu_id, pdu, &pdu_json, count2)?;
 
-- 
GitLab