tuwunel_service/rooms/timeline/
redact.rs1use ruma::{
8 EventId, RoomId,
9 canonical_json::{RedactedBecause, redact_in_place},
10};
11use tuwunel_core::{Result, err, implement, matrix::event::Event};
12
13use crate::rooms::{short::ShortRoomId, timeline::RoomMutexGuard};
14
15#[implement(super::Service)]
22#[tracing::instrument(name = "redact", level = "debug", skip(self))]
23pub async fn redact_pdu<Pdu: Event + Send + Sync>(
24 &self,
25 event_id: &EventId,
26 reason: &Pdu,
27 shortroomid: ShortRoomId,
28 state_lock: &RoomMutexGuard,
29) -> Result {
30 let Ok(pdu_id) = self.get_pdu_id(event_id).await else {
31 return Ok(());
34 };
35
36 let mut pdu = self
37 .get_pdu_json_from_id(&pdu_id)
38 .await
39 .map_err(|e| {
40 err!(Database(error!(?pdu_id, ?event_id, ?e, "PDU ID points to invalid PDU.")))
41 })?;
42
43 self.services
44 .retention
45 .save_original_pdu(event_id, &pdu, state_lock)
46 .await;
47
48 let body = pdu["content"]
49 .as_object()
50 .and_then(|obj| obj.get("body"))
51 .and_then(|body| body.as_str());
52
53 if let Some(body) = body {
54 self.services
55 .search
56 .deindex_pdu(shortroomid, &pdu_id, body);
57 }
58
59 let room_id: &RoomId = pdu.get("room_id").try_into()?;
60
61 let room_version_id = self
62 .services
63 .state
64 .get_room_version(room_id)
65 .await?;
66
67 let room_version_rules = room_version_id.rules().ok_or_else(|| {
68 err!(Request(UnsupportedRoomVersion(
69 "Cannot redact event for unknown room version {room_version_id:?}."
70 )))
71 })?;
72
73 self.services
74 .pdu_metadata
75 .delete_typed_relation(&pdu_id, &pdu)
76 .await;
77
78 redact_in_place(
79 &mut pdu,
80 &room_version_rules.redaction,
81 Some(RedactedBecause::from_json(reason.to_canonical_object())),
82 )
83 .map_err(|err| err!("invalid event: {err}"))?;
84
85 self.replace_pdu(&pdu_id, &pdu).await
86}