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