diff --git a/crates/ruma-signatures/src/functions.rs b/crates/ruma-signatures/src/functions.rs index 95e97021..31709f9d 100644 --- a/crates/ruma-signatures/src/functions.rs +++ b/crates/ruma-signatures/src/functions.rs @@ -736,29 +736,23 @@ pub fn redact_in_place( event: &mut CanonicalJsonObject, version: &RoomVersionId, ) -> Result<(), Error> { - let event_type_value = match event.get("type") { - Some(event_type_value) => event_type_value, + // Get the content keys here instead of the event type, because we cant teach rust that this is + // a disjoint borrow. + let allowed_content_keys: &[&str] = match event.get("type") { + Some(CanonicalJsonValue::String(event_type)) => { + allowed_content_keys_for(event_type, version) + } + Some(_) => return Err(JsonError::not_of_type("type", JsonType::String)), None => return Err(JsonError::field_missing_from_object("type")), }; - let allowed_content_keys = match event_type_value { - CanonicalJsonValue::String(event_type) => allowed_content_keys_for(event_type, version), - _ => return Err(JsonError::not_of_type("type", JsonType::String)), - }; - if let Some(content_value) = event.get_mut("content") { let content = match content_value { CanonicalJsonValue::Object(map) => map, _ => return Err(JsonError::not_of_type("content", JsonType::Object)), }; - let mut old_content = mem::take(content); - - for &key in allowed_content_keys { - if let Some(value) = old_content.remove(key) { - content.insert(key.to_owned(), value); - } - } + object_retain_keys(content, allowed_content_keys); } let mut old_event = mem::take(event); @@ -772,6 +766,27 @@ pub fn redact_in_place( Ok(()) } +/// Redacts event content using the rules specified in the Matrix client-server specification. +/// +/// Edits the `object` in-place. +pub fn redact_content_in_place( + object: &mut CanonicalJsonObject, + version: &RoomVersionId, + event_type: impl AsRef, +) { + object_retain_keys(object, allowed_content_keys_for(event_type.as_ref(), version)) +} + +fn object_retain_keys(object: &mut CanonicalJsonObject, keys: &[&str]) { + let mut old_content = mem::take(object); + + for &key in keys { + if let Some(value) = old_content.remove(key) { + object.insert(key.to_owned(), value); + } + } +} + /// Extracts the server names to check signatures for given event. /// /// It will return the sender's server (unless it's a third party invite) and the event id server diff --git a/crates/ruma-signatures/src/lib.rs b/crates/ruma-signatures/src/lib.rs index d725a6b4..f134f097 100644 --- a/crates/ruma-signatures/src/lib.rs +++ b/crates/ruma-signatures/src/lib.rs @@ -48,8 +48,8 @@ use ruma_serde::{AsRefStr, DisplayAsRefStr}; pub use error::{Error, JsonError, JsonType, ParseError, SplitError, VerificationError}; pub use functions::{ - canonical_json, content_hash, hash_and_sign_event, redact, reference_hash, sign_json, - verify_event, verify_json, + canonical_json, content_hash, hash_and_sign_event, redact, redact_content_in_place, + redact_in_place, reference_hash, sign_json, verify_event, verify_json, }; pub use keys::{Ed25519KeyPair, KeyPair, PublicKeyMap, PublicKeySet}; pub use ruma_serde::{CanonicalJsonError, CanonicalJsonObject, CanonicalJsonValue};