push: Escape dots and backslashes in field name for event_match condition

According to MSC3873
This commit is contained in:
Kévin Commaille 2023-04-06 16:42:23 +02:00 committed by Kévin Commaille
parent 66f417c3f2
commit ef374ea6b0
2 changed files with 20 additions and 2 deletions

View File

@ -18,6 +18,7 @@ Improvements:
- Add `AsRef<[u8]>` implementations for identifier types - Add `AsRef<[u8]>` implementations for identifier types
- Add `InitialStateEvent::{new, to_raw, to_raw_any}` - Add `InitialStateEvent::{new, to_raw, to_raw_any}`
- Add a convenience method to construct `RoomEncryptionEventContent` with the recommended defaults. - Add a convenience method to construct `RoomEncryptionEventContent` with the recommended defaults.
- `PushCondition::EventMatch` and `FlattenedJson` now use escaped dotted paths, according to MSC3873
# 0.11.3 # 0.11.3

View File

@ -63,7 +63,10 @@ impl RoomVersionFeature {
pub enum PushCondition { pub enum PushCondition {
/// A glob pattern match on a field of the event. /// A glob pattern match on a field of the event.
EventMatch { EventMatch {
/// The dot-separated field of the event to match. /// The dot-separated path of the property of the event to match. See [MSC3873] for its
/// format.
///
/// [MSC3873]: https://github.com/matrix-org/matrix-spec-proposals/pull/3873
key: String, key: String,
/// The glob-style pattern to match against. /// The glob-style pattern to match against.
@ -428,6 +431,7 @@ impl FlattenedJson {
match value { match value {
JsonValue::Object(fields) => { JsonValue::Object(fields) => {
for (key, value) in fields { for (key, value) in fields {
let key = escape_key(&key);
let path = if path.is_empty() { key } else { format!("{path}.{key}") }; let path = if path.is_empty() { key } else { format!("{path}.{key}") };
self.flatten_value(value, path); self.flatten_value(value, path);
} }
@ -447,6 +451,13 @@ impl FlattenedJson {
} }
} }
/// Escape a key for path matching.
///
/// This escapes the dots (`.`) and backslashes (`\`) in the key with a backslash.
fn escape_key(key: &str) -> String {
key.replace('\\', r"\\").replace('.', r"\.")
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -808,10 +819,13 @@ mod tests {
let raw = serde_json::from_str::<Raw<JsonValue>>( let raw = serde_json::from_str::<Raw<JsonValue>>(
r#"{ r#"{
"desc": "Level 0", "desc": "Level 0",
"desc.bis": "Level 0 bis",
"up": { "up": {
"desc": "Level 1", "desc": "Level 1",
"desc.bis": "Level 1 bis",
"up": { "up": {
"desc": "Level 2" "desc": "Level 2",
"desc\\bis": "Level 2 bis"
} }
} }
}"#, }"#,
@ -823,8 +837,11 @@ mod tests {
flattened.map, flattened.map,
btreemap! { btreemap! {
"desc".into() => "Level 0".into(), "desc".into() => "Level 0".into(),
r"desc\.bis".into() => "Level 0 bis".into(),
"up.desc".into() => "Level 1".into(), "up.desc".into() => "Level 1".into(),
r"up.desc\.bis".into() => "Level 1 bis".into(),
"up.up.desc".into() => "Level 2".into(), "up.up.desc".into() => "Level 2".into(),
r"up.up.desc\\bis".into() => "Level 2 bis".into(),
}, },
); );
} }