Non-reserializing redaction
This commit is contained in:
@@ -4,7 +4,6 @@ pub mod format;
|
||||
mod hashes;
|
||||
mod id;
|
||||
mod raw_id;
|
||||
mod redact;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod unsigned;
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
use ruma::{RoomVersionId, canonical_json::redact_content_in_place};
|
||||
use serde_json::{Value as JsonValue, json, value::to_raw_value};
|
||||
|
||||
use crate::{Error, Result, err, implement};
|
||||
|
||||
#[implement(super::Pdu)]
|
||||
pub fn redact(&mut self, room_version_id: &RoomVersionId, reason: JsonValue) -> Result {
|
||||
self.unsigned = None;
|
||||
|
||||
let mut content = serde_json::from_str(self.content.get())
|
||||
.map_err(|e| err!(Request(BadJson("Failed to deserialize content into type: {e}"))))?;
|
||||
|
||||
let room_version_rules = room_version_id.rules().ok_or_else(|| {
|
||||
err!(Request(UnsupportedRoomVersion(
|
||||
"Cannot redact event for unknown room version {room_version_id:?}."
|
||||
)))
|
||||
})?;
|
||||
|
||||
redact_content_in_place(&mut content, &room_version_rules.redaction, self.kind.to_string())
|
||||
.map_err(|e| Error::Redaction(self.sender.server_name().to_owned(), e))?;
|
||||
|
||||
let reason = serde_json::to_value(reason).expect("Failed to preserialize reason");
|
||||
|
||||
let redacted_because = json!({
|
||||
"redacted_because": reason,
|
||||
});
|
||||
|
||||
self.unsigned = to_raw_value(&redacted_because)
|
||||
.expect("Failed to serialize unsigned")
|
||||
.into();
|
||||
|
||||
self.content = to_raw_value(&content).expect("Failed to serialize content");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -218,32 +218,23 @@ async fn append_pdu_effects(
|
||||
.get_room_version(pdu.room_id())
|
||||
.await?;
|
||||
|
||||
match room_version_id {
|
||||
| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => {
|
||||
if let Some(redact_id) = pdu.redacts()
|
||||
&& self
|
||||
.services
|
||||
.state_accessor
|
||||
.user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false)
|
||||
.await?
|
||||
{
|
||||
self.redact_pdu(redact_id, pdu, shortroomid)
|
||||
.await?;
|
||||
}
|
||||
},
|
||||
let content: RoomRedactionEventContent;
|
||||
let event_id = match room_version_id {
|
||||
| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => pdu.redacts(),
|
||||
| _ => {
|
||||
let content: RoomRedactionEventContent = pdu.get_content()?;
|
||||
if let Some(redact_id) = &content.redacts
|
||||
&& self
|
||||
.services
|
||||
.state_accessor
|
||||
.user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false)
|
||||
.await?
|
||||
{
|
||||
self.redact_pdu(redact_id, pdu, shortroomid)
|
||||
.await?;
|
||||
}
|
||||
content = pdu.get_content()?;
|
||||
content.redacts.as_deref()
|
||||
},
|
||||
};
|
||||
if let Some(redact_id) = event_id
|
||||
&& self
|
||||
.services
|
||||
.state_accessor
|
||||
.user_can_redact(redact_id, pdu.sender(), pdu.room_id(), false)
|
||||
.await?
|
||||
{
|
||||
self.redact_pdu(redact_id, pdu, shortroomid)
|
||||
.await?;
|
||||
}
|
||||
},
|
||||
| TimelineEventType::SpaceChild =>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use ruma::EventId;
|
||||
use tuwunel_core::{
|
||||
Result, err, implement,
|
||||
matrix::event::Event,
|
||||
utils::{self},
|
||||
use ruma::{
|
||||
EventId, RoomId,
|
||||
canonical_json::{RedactedBecause, redact_in_place},
|
||||
};
|
||||
use tuwunel_core::{Result, err, implement, matrix::event::Event};
|
||||
|
||||
use super::ExtractBody;
|
||||
use crate::rooms::short::ShortRoomId;
|
||||
|
||||
/// Replace a PDU with the redacted form.
|
||||
@@ -17,39 +15,51 @@ pub async fn redact_pdu<Pdu: Event + Send + Sync>(
|
||||
reason: &Pdu,
|
||||
shortroomid: ShortRoomId,
|
||||
) -> Result {
|
||||
// TODO: Don't reserialize, keep original json
|
||||
let Ok(pdu_id) = self.get_pdu_id(event_id).await else {
|
||||
// If event does not exist, just noop
|
||||
// TODO this is actually wrong!
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let mut pdu = self
|
||||
.get_pdu_from_id(&pdu_id)
|
||||
.get_pdu_json_from_id(&pdu_id)
|
||||
.await
|
||||
.map(Event::into_pdu)
|
||||
.map_err(|e| {
|
||||
err!(Database(error!(?pdu_id, ?event_id, ?e, "PDU ID points to invalid PDU.")))
|
||||
})?;
|
||||
|
||||
if let Ok(content) = pdu.get_content::<ExtractBody>()
|
||||
&& let Some(body) = content.body
|
||||
{
|
||||
let body = pdu["content"]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.get("body")
|
||||
.and_then(|body| body.as_str());
|
||||
|
||||
if let Some(body) = body {
|
||||
self.services
|
||||
.search
|
||||
.deindex_pdu(shortroomid, &pdu_id, &body);
|
||||
.deindex_pdu(shortroomid, &pdu_id, body);
|
||||
}
|
||||
|
||||
let room_id = RoomId::parse(pdu["room_id"].as_str().unwrap()).unwrap();
|
||||
|
||||
let room_version_id = self
|
||||
.services
|
||||
.state
|
||||
.get_room_version(pdu.room_id())
|
||||
.get_room_version(room_id)
|
||||
.await?;
|
||||
|
||||
pdu.redact(&room_version_id, reason.to_value())?;
|
||||
|
||||
let obj = utils::to_canonical_object(&pdu).map_err(|e| {
|
||||
err!(Database(error!(?event_id, ?e, "Failed to convert PDU to canonical JSON")))
|
||||
let room_version_rules = room_version_id.rules().ok_or_else(|| {
|
||||
err!(Request(UnsupportedRoomVersion(
|
||||
"Cannot redact event for unknown room version {room_version_id:?}."
|
||||
)))
|
||||
})?;
|
||||
|
||||
self.replace_pdu(&pdu_id, &obj).await
|
||||
redact_in_place(
|
||||
&mut pdu,
|
||||
&room_version_rules.redaction,
|
||||
Some(RedactedBecause::from_json(reason.to_canonical_object())),
|
||||
)
|
||||
.map_err(|err| err!("invalid event: {err}"))?;
|
||||
|
||||
self.replace_pdu(&pdu_id, &pdu).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user