mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-10-06 20:07:32 +00:00
fix: Merge nex/fix-redactions-boogaloo-2
This commit is contained in:
+23
-2
@@ -6,7 +6,10 @@
|
||||
matrix::pdu::{PartialPdu, sticky},
|
||||
utils,
|
||||
};
|
||||
use ruma::{api::client::message::send_message_event, events::MessageLikeEventType};
|
||||
use ruma::{
|
||||
OwnedEventId, api::client::message::send_message_event, events::MessageLikeEventType,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::from_str;
|
||||
|
||||
use crate::{Ruma, client_ip::ClientIp};
|
||||
@@ -77,6 +80,13 @@ pub(crate) async fn send_message_event_route(
|
||||
|
||||
let content = from_str(body.body.body.json().get())
|
||||
.map_err(|e| err!(Request(BadJson("Invalid JSON body: {e}"))))?;
|
||||
let redacts = if body.body.event_type == MessageLikeEventType::RoomRedaction {
|
||||
from_str::<MaybeRedaction>(body.body.body.json().get())
|
||||
.ok()
|
||||
.and_then(|r| r.redacts)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let event_id = services
|
||||
.rooms
|
||||
@@ -92,11 +102,14 @@ pub(crate) async fn send_message_event_route(
|
||||
.flatten()
|
||||
.map(sticky::object),
|
||||
unsigned: Some(unsigned),
|
||||
timestamp: if body.identity.is_appservice() {
|
||||
timestamp: if body.identity.is_appservice()
|
||||
|| services.admin.user_is_admin(sender_user).await
|
||||
{
|
||||
body.timestamp
|
||||
} else {
|
||||
None
|
||||
},
|
||||
redacts,
|
||||
..Default::default()
|
||||
},
|
||||
sender_user,
|
||||
@@ -116,3 +129,11 @@ pub(crate) async fn send_message_event_route(
|
||||
|
||||
Ok(send_message_event::v3::Response::new(event_id))
|
||||
}
|
||||
|
||||
/// Struct containing exclusively the `redacts` field for MSC4169 compatible
|
||||
/// redaction moving.
|
||||
#[derive(Deserialize)]
|
||||
struct MaybeRedaction {
|
||||
#[serde(default)]
|
||||
redacts: Option<OwnedEventId>,
|
||||
}
|
||||
|
||||
@@ -56,7 +56,12 @@ pub(super) fn is_redacted<E: Event>(event: &E) -> bool {
|
||||
return false;
|
||||
};
|
||||
|
||||
unsigned.redacted_because.is_some()
|
||||
unsigned.redacted_by.is_some()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RedactionField {
|
||||
redacts: OwnedEventId,
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@@ -69,16 +74,104 @@ pub(super) fn redacts_id<E: Event>(
|
||||
}
|
||||
|
||||
if room_version_rules.redaction.content_field_redacts {
|
||||
event.redacts().map(ToOwned::to_owned)
|
||||
} else {
|
||||
event
|
||||
.get_content::<RoomRedactionEventContent>()
|
||||
.ok()?
|
||||
.redacts
|
||||
.get_content::<RedactionField>()
|
||||
.map(|r| r.redacts)
|
||||
.ok()
|
||||
} else {
|
||||
event.redacts().map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractRedactedBecause {
|
||||
redacted_because: Option<serde::de::IgnoredAny>,
|
||||
#[serde(rename = "org.continuwuity.redacted_by")]
|
||||
redacted_by: Option<serde::de::IgnoredAny>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruma::{UInt, events::TimelineEventType, room_version_rules::RoomVersionRules};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{Event, Pdu, pdu::EventHash};
|
||||
|
||||
#[test]
|
||||
fn v11_redacts_from_content() {
|
||||
let p = Pdu {
|
||||
event_id: ruma::owned_event_id!("$v11"),
|
||||
room_id: Some(ruma::owned_room_id!("!v11:example.com")),
|
||||
sender: ruma::owned_user_id!("@user:example.com"),
|
||||
origin: None,
|
||||
origin_server_ts: UInt::default(),
|
||||
kind: TimelineEventType::RoomRedaction,
|
||||
content: serde_json::value::to_raw_value(&json!({"redacts": "$content_redacts"}))
|
||||
.unwrap(),
|
||||
sticky: None,
|
||||
state_key: None,
|
||||
prev_events: vec![],
|
||||
depth: UInt::default(),
|
||||
auth_events: vec![],
|
||||
redacts: Some(ruma::owned_event_id!("$apex_redacts")),
|
||||
unsigned: None,
|
||||
hashes: EventHash { sha256: String::new() },
|
||||
signatures: None,
|
||||
};
|
||||
assert_eq!(
|
||||
p.redacts_id(&RoomVersionRules::V11),
|
||||
Some(ruma::owned_event_id!("$content_redacts"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v10_redacts_from_apex() {
|
||||
let p = Pdu {
|
||||
event_id: ruma::owned_event_id!("$v11"),
|
||||
room_id: Some(ruma::owned_room_id!("!v11:example.com")),
|
||||
sender: ruma::owned_user_id!("@user:example.com"),
|
||||
origin: None,
|
||||
origin_server_ts: UInt::default(),
|
||||
kind: TimelineEventType::RoomRedaction,
|
||||
content: serde_json::value::to_raw_value(&json!({"redacts": "$content_redacts"}))
|
||||
.unwrap(),
|
||||
sticky: None,
|
||||
state_key: None,
|
||||
prev_events: vec![],
|
||||
depth: UInt::default(),
|
||||
auth_events: vec![],
|
||||
redacts: Some(ruma::owned_event_id!("$apex_redacts")),
|
||||
unsigned: None,
|
||||
hashes: EventHash { sha256: String::new() },
|
||||
signatures: None,
|
||||
};
|
||||
assert_eq!(
|
||||
p.redacts_id(&RoomVersionRules::V10),
|
||||
Some(ruma::owned_event_id!("$apex_redacts"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redacts_ignores_non_redaction_event() {
|
||||
let p = Pdu {
|
||||
event_id: ruma::owned_event_id!("$v11"),
|
||||
room_id: Some(ruma::owned_room_id!("!v11:example.com")),
|
||||
sender: ruma::owned_user_id!("@user:example.com"),
|
||||
origin: None,
|
||||
origin_server_ts: UInt::default(),
|
||||
kind: TimelineEventType::RoomMessage,
|
||||
content: serde_json::value::to_raw_value(&json!({"redacts": "$content_redacts"}))
|
||||
.unwrap(),
|
||||
sticky: None,
|
||||
state_key: None,
|
||||
prev_events: vec![],
|
||||
depth: UInt::default(),
|
||||
auth_events: vec![],
|
||||
redacts: Some(ruma::owned_event_id!("$apex_redacts")),
|
||||
unsigned: None,
|
||||
hashes: EventHash { sha256: String::new() },
|
||||
signatures: None,
|
||||
};
|
||||
assert_eq!(p.redacts_id(&RoomVersionRules::V11), None);
|
||||
assert_eq!(p.redacts_id(&RoomVersionRules::V10), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,11 +183,6 @@ pub async fn create_event(
|
||||
.room_state_get(room_id, &event_type.clone().to_string().into(), state_key)
|
||||
.await
|
||||
{
|
||||
unsigned.insert("prev_content".to_owned(), prev_pdu.get_content_as_value());
|
||||
unsigned.insert(
|
||||
"prev_sender".to_owned(),
|
||||
serde_json::to_value(prev_pdu.sender())?,
|
||||
);
|
||||
unsigned.insert(
|
||||
"replaces_state".to_owned(),
|
||||
serde_json::to_value(prev_pdu.event_id())?,
|
||||
@@ -195,9 +190,17 @@ pub async fn create_event(
|
||||
}
|
||||
}
|
||||
}
|
||||
let redacts = match redacts {
|
||||
// If this isn't a real redaction event, there's no redacts field.
|
||||
| _ if event_type != TimelineEventType::RoomRedaction || state_key.is_some() => None,
|
||||
// If the redaction is itself in the event content, we don't set the top-level field.
|
||||
| Some(_) if room_version_rules.redaction.content_field_redacts => None,
|
||||
// Otherwise, we do if it's present
|
||||
| other => other,
|
||||
};
|
||||
|
||||
let pdu = PduEvent {
|
||||
event_id: ruma::event_id!("$thiswillbefilledinlater").into(),
|
||||
event_id: ruma::owned_event_id!("$thiswillbefilledinlater"),
|
||||
room_id: room_id.map(ToOwned::to_owned),
|
||||
sender: sender.to_owned(),
|
||||
origin: None,
|
||||
|
||||
Reference in New Issue
Block a user