mirror of
https://git.anonymousland.org/anonymousland/synapse-product.git
synced 2024-12-11 14:04:19 -05:00
Do not accept pattern_type from user input in push rules. (#15088)
Internally the push rules module uses a `pattern_type` property for `event_match` conditions (and `related_event_match`) to mark the condition as matching the current user's Matrix ID or localpart. This is leaky to the Client-Server API where a user can successfully set a condition which provides `pattern_type` instead of `pattern` (note that there's no benefit to doing this -- the user can just use their own Matrix ID or localpart instead). When serializing back to the client the `pattern_type` property is converted into a proper `pattern`. The following changes are made to avoid this: * Separate the `KnownCondition::EventMatch` enum value into `EventMatch` and `EventMatchType`, each with their own expected properties. (Note that a similar change is made for `RelatedEventMatch`.) * Make it such that the `pattern_type` variants serialize to the same condition kind, but cannot be deserialized (since they're only provided by base rules). * As a final tweak, convert `user_id` vs. `user_localpart` values into an enum.
This commit is contained in:
parent
521026897c
commit
e746f80b4f
1
changelog.d/15088.bugfix
Normal file
1
changelog.d/15088.bugfix
Normal file
@ -0,0 +1 @@
|
|||||||
|
Fix a long-standing bug where Synapse handled an unspecced field on push rules.
|
@ -60,8 +60,7 @@ fn bench_match_exact(b: &mut Bencher) {
|
|||||||
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: "room_id".into(),
|
key: "room_id".into(),
|
||||||
pattern: Some("!room:server".into()),
|
pattern: "!room:server".into(),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -109,8 +108,7 @@ fn bench_match_word(b: &mut Bencher) {
|
|||||||
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: "content.body".into(),
|
key: "content.body".into(),
|
||||||
pattern: Some("test".into()),
|
pattern: "test".into(),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -158,8 +156,7 @@ fn bench_match_word_miss(b: &mut Bencher) {
|
|||||||
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
let condition = Condition::Known(synapse::push::KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: "content.body".into(),
|
key: "content.body".into(),
|
||||||
pattern: Some("foobar".into()),
|
pattern: "foobar".into(),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ use lazy_static::lazy_static;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use super::KnownCondition;
|
use super::KnownCondition;
|
||||||
use crate::push::Condition;
|
|
||||||
use crate::push::EventMatchCondition;
|
|
||||||
use crate::push::PushRule;
|
use crate::push::PushRule;
|
||||||
use crate::push::RelatedEventMatchCondition;
|
use crate::push::RelatedEventMatchTypeCondition;
|
||||||
use crate::push::SetTweak;
|
use crate::push::SetTweak;
|
||||||
use crate::push::TweakValue;
|
use crate::push::TweakValue;
|
||||||
use crate::push::{Action, ExactEventMatchCondition, SimpleJsonValue};
|
use crate::push::{Action, ExactEventMatchCondition, SimpleJsonValue};
|
||||||
|
use crate::push::{Condition, EventMatchTypeCondition};
|
||||||
|
use crate::push::{EventMatchCondition, EventMatchPatternType};
|
||||||
|
|
||||||
const HIGHLIGHT_ACTION: Action = Action::SetTweak(SetTweak {
|
const HIGHLIGHT_ACTION: Action = Action::SetTweak(SetTweak {
|
||||||
set_tweak: Cow::Borrowed("highlight"),
|
set_tweak: Cow::Borrowed("highlight"),
|
||||||
@ -72,8 +72,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("content.m.relates_to.rel_type"),
|
key: Cow::Borrowed("content.m.relates_to.rel_type"),
|
||||||
pattern: Some(Cow::Borrowed("m.replace")),
|
pattern: Cow::Borrowed("m.replace"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[]),
|
actions: Cow::Borrowed(&[]),
|
||||||
@ -86,8 +85,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("content.msgtype"),
|
key: Cow::Borrowed("content.msgtype"),
|
||||||
pattern: Some(Cow::Borrowed("m.notice")),
|
pattern: Cow::Borrowed("m.notice"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::DontNotify]),
|
actions: Cow::Borrowed(&[Action::DontNotify]),
|
||||||
@ -100,18 +98,15 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.member")),
|
pattern: Cow::Borrowed("m.room.member"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("content.membership"),
|
key: Cow::Borrowed("content.membership"),
|
||||||
pattern: Some(Cow::Borrowed("invite")),
|
pattern: Cow::Borrowed("invite"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatchType(EventMatchTypeCondition {
|
||||||
key: Cow::Borrowed("state_key"),
|
key: Cow::Borrowed("state_key"),
|
||||||
pattern: None,
|
pattern_type: Cow::Borrowed(&EventMatchPatternType::UserId),
|
||||||
pattern_type: Some(Cow::Borrowed("user_id")),
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION, SOUND_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION, SOUND_ACTION]),
|
||||||
@ -124,8 +119,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.member")),
|
pattern: Cow::Borrowed("m.room.member"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::DontNotify]),
|
actions: Cow::Borrowed(&[Action::DontNotify]),
|
||||||
@ -135,11 +129,10 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
PushRule {
|
PushRule {
|
||||||
rule_id: Cow::Borrowed("global/override/.im.nheko.msc3664.reply"),
|
rule_id: Cow::Borrowed("global/override/.im.nheko.msc3664.reply"),
|
||||||
priority_class: 5,
|
priority_class: 5,
|
||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::RelatedEventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::RelatedEventMatchType(
|
||||||
RelatedEventMatchCondition {
|
RelatedEventMatchTypeCondition {
|
||||||
key: Some(Cow::Borrowed("sender")),
|
key: Cow::Borrowed("sender"),
|
||||||
pattern: None,
|
pattern_type: Cow::Borrowed(&EventMatchPatternType::UserId),
|
||||||
pattern_type: Some(Cow::Borrowed("user_id")),
|
|
||||||
rel_type: Cow::Borrowed("m.in_reply_to"),
|
rel_type: Cow::Borrowed("m.in_reply_to"),
|
||||||
include_fallbacks: None,
|
include_fallbacks: None,
|
||||||
},
|
},
|
||||||
@ -189,8 +182,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
}),
|
}),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("content.body"),
|
key: Cow::Borrowed("content.body"),
|
||||||
pattern: Some(Cow::Borrowed("@room")),
|
pattern: Cow::Borrowed("@room"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION]),
|
||||||
@ -203,13 +195,11 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.tombstone")),
|
pattern: Cow::Borrowed("m.room.tombstone"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("state_key"),
|
key: Cow::Borrowed("state_key"),
|
||||||
pattern: Some(Cow::Borrowed("")),
|
pattern: Cow::Borrowed(""),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION]),
|
||||||
@ -222,8 +212,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.reaction")),
|
pattern: Cow::Borrowed("m.reaction"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[]),
|
actions: Cow::Borrowed(&[]),
|
||||||
@ -236,13 +225,11 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.server_acl")),
|
pattern: Cow::Borrowed("m.room.server_acl"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("state_key"),
|
key: Cow::Borrowed("state_key"),
|
||||||
pattern: Some(Cow::Borrowed("")),
|
pattern: Cow::Borrowed(""),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[]),
|
actions: Cow::Borrowed(&[]),
|
||||||
@ -255,8 +242,7 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc3381.poll.response")),
|
pattern: Cow::Borrowed("org.matrix.msc3381.poll.response"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[]),
|
actions: Cow::Borrowed(&[]),
|
||||||
@ -268,11 +254,10 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[
|
|||||||
pub const BASE_APPEND_CONTENT_RULES: &[PushRule] = &[PushRule {
|
pub const BASE_APPEND_CONTENT_RULES: &[PushRule] = &[PushRule {
|
||||||
rule_id: Cow::Borrowed("global/content/.m.rule.contains_user_name"),
|
rule_id: Cow::Borrowed("global/content/.m.rule.contains_user_name"),
|
||||||
priority_class: 4,
|
priority_class: 4,
|
||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatchType(
|
||||||
EventMatchCondition {
|
EventMatchTypeCondition {
|
||||||
key: Cow::Borrowed("content.body"),
|
key: Cow::Borrowed("content.body"),
|
||||||
pattern: None,
|
pattern_type: Cow::Borrowed(&EventMatchPatternType::UserLocalpart),
|
||||||
pattern_type: Some(Cow::Borrowed("user_localpart")),
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION, SOUND_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_ACTION, SOUND_ACTION]),
|
||||||
@ -287,8 +272,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.call.invite")),
|
pattern: Cow::Borrowed("m.call.invite"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, RING_ACTION, HIGHLIGHT_FALSE_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, RING_ACTION, HIGHLIGHT_FALSE_ACTION]),
|
||||||
@ -301,8 +285,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.message")),
|
pattern: Cow::Borrowed("m.room.message"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -318,8 +301,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.encrypted")),
|
pattern: Cow::Borrowed("m.room.encrypted"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -338,8 +320,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.encrypted")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.encrypted"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -363,8 +344,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.message")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.message"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -388,8 +368,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.file")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.file"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -413,8 +392,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.image")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.image"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -438,8 +416,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.video")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.video"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -463,8 +440,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc1767.audio")),
|
pattern: Cow::Borrowed("org.matrix.msc1767.audio"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::RoomMemberCount {
|
Condition::Known(KnownCondition::RoomMemberCount {
|
||||||
is: Some(Cow::Borrowed("2")),
|
is: Some(Cow::Borrowed("2")),
|
||||||
@ -485,8 +461,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.message")),
|
pattern: Cow::Borrowed("m.room.message"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
||||||
@ -499,8 +474,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("m.room.encrypted")),
|
pattern: Cow::Borrowed("m.room.encrypted"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
||||||
@ -514,8 +488,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.encrypted")),
|
pattern: Cow::Borrowed("m.encrypted"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -534,8 +507,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.message")),
|
pattern: Cow::Borrowed("m.message"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -554,8 +526,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.file")),
|
pattern: Cow::Borrowed("m.file"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -574,8 +545,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.image")),
|
pattern: Cow::Borrowed("m.image"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -594,8 +564,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.video")),
|
pattern: Cow::Borrowed("m.video"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -614,8 +583,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
// MSC3933: Type changed from template rule - see MSC.
|
// MSC3933: Type changed from template rule - see MSC.
|
||||||
pattern: Some(Cow::Borrowed("m.audio")),
|
pattern: Cow::Borrowed("m.audio"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
// MSC3933: Add condition on top of template rule - see MSC.
|
// MSC3933: Add condition on top of template rule - see MSC.
|
||||||
Condition::Known(KnownCondition::RoomVersionSupports {
|
Condition::Known(KnownCondition::RoomVersionSupports {
|
||||||
@ -633,18 +601,15 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[
|
conditions: Cow::Borrowed(&[
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("im.vector.modular.widgets")),
|
pattern: Cow::Borrowed("im.vector.modular.widgets"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("content.type"),
|
key: Cow::Borrowed("content.type"),
|
||||||
pattern: Some(Cow::Borrowed("jitsi")),
|
pattern: Cow::Borrowed("jitsi"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("state_key"),
|
key: Cow::Borrowed("state_key"),
|
||||||
pattern: Some(Cow::Borrowed("*")),
|
pattern: Cow::Borrowed("*"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, HIGHLIGHT_FALSE_ACTION]),
|
||||||
@ -660,8 +625,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
}),
|
}),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc3381.poll.start")),
|
pattern: Cow::Borrowed("org.matrix.msc3381.poll.start"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION]),
|
||||||
@ -674,8 +638,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc3381.poll.start")),
|
pattern: Cow::Borrowed("org.matrix.msc3381.poll.start"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify]),
|
actions: Cow::Borrowed(&[Action::Notify]),
|
||||||
@ -691,8 +654,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
}),
|
}),
|
||||||
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc3381.poll.end")),
|
pattern: Cow::Borrowed("org.matrix.msc3381.poll.end"),
|
||||||
pattern_type: None,
|
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION]),
|
actions: Cow::Borrowed(&[Action::Notify, SOUND_ACTION]),
|
||||||
@ -705,8 +667,7 @@ pub const BASE_APPEND_UNDERRIDE_RULES: &[PushRule] = &[
|
|||||||
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
conditions: Cow::Borrowed(&[Condition::Known(KnownCondition::EventMatch(
|
||||||
EventMatchCondition {
|
EventMatchCondition {
|
||||||
key: Cow::Borrowed("type"),
|
key: Cow::Borrowed("type"),
|
||||||
pattern: Some(Cow::Borrowed("org.matrix.msc3381.poll.end")),
|
pattern: Cow::Borrowed("org.matrix.msc3381.poll.end"),
|
||||||
pattern_type: None,
|
|
||||||
},
|
},
|
||||||
))]),
|
))]),
|
||||||
actions: Cow::Borrowed(&[Action::Notify]),
|
actions: Cow::Borrowed(&[Action::Notify]),
|
||||||
|
@ -12,9 +12,10 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
use crate::push::JsonValue;
|
use crate::push::{EventMatchPatternType, JsonValue};
|
||||||
use anyhow::{Context, Error};
|
use anyhow::{Context, Error};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
@ -23,8 +24,8 @@ use regex::Regex;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
utils::{get_glob_matcher, get_localpart_from_id, GlobMatchType},
|
utils::{get_glob_matcher, get_localpart_from_id, GlobMatchType},
|
||||||
Action, Condition, EventMatchCondition, ExactEventMatchCondition, FilteredPushRules,
|
Action, Condition, ExactEventMatchCondition, FilteredPushRules, KnownCondition,
|
||||||
KnownCondition, RelatedEventMatchCondition, SimpleJsonValue,
|
SimpleJsonValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -256,14 +257,58 @@ impl PushRuleEvaluator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let result = match known_condition {
|
let result = match known_condition {
|
||||||
KnownCondition::EventMatch(event_match) => {
|
KnownCondition::EventMatch(event_match) => self.match_event_match(
|
||||||
self.match_event_match(event_match, user_id)?
|
&self.flattened_keys,
|
||||||
|
&event_match.key,
|
||||||
|
&event_match.pattern,
|
||||||
|
)?,
|
||||||
|
KnownCondition::EventMatchType(event_match) => {
|
||||||
|
// The `pattern_type` can either be "user_id" or "user_localpart",
|
||||||
|
// either way if we don't have a `user_id` then the condition can't
|
||||||
|
// match.
|
||||||
|
let user_id = if let Some(user_id) = user_id {
|
||||||
|
user_id
|
||||||
|
} else {
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
let pattern = match &*event_match.pattern_type {
|
||||||
|
EventMatchPatternType::UserId => user_id,
|
||||||
|
EventMatchPatternType::UserLocalpart => get_localpart_from_id(user_id)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.match_event_match(&self.flattened_keys, &event_match.key, pattern)?
|
||||||
}
|
}
|
||||||
KnownCondition::ExactEventMatch(exact_event_match) => {
|
KnownCondition::ExactEventMatch(exact_event_match) => {
|
||||||
self.match_exact_event_match(exact_event_match)?
|
self.match_exact_event_match(exact_event_match)?
|
||||||
}
|
}
|
||||||
KnownCondition::RelatedEventMatch(event_match) => {
|
KnownCondition::RelatedEventMatch(event_match) => self.match_related_event_match(
|
||||||
self.match_related_event_match(event_match, user_id)?
|
&event_match.rel_type.clone(),
|
||||||
|
event_match.include_fallbacks,
|
||||||
|
event_match.key.clone(),
|
||||||
|
event_match.pattern.clone(),
|
||||||
|
)?,
|
||||||
|
KnownCondition::RelatedEventMatchType(event_match) => {
|
||||||
|
// The `pattern_type` can either be "user_id" or "user_localpart",
|
||||||
|
// either way if we don't have a `user_id` then the condition can't
|
||||||
|
// match.
|
||||||
|
let user_id = if let Some(user_id) = user_id {
|
||||||
|
user_id
|
||||||
|
} else {
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
let pattern = match &*event_match.pattern_type {
|
||||||
|
EventMatchPatternType::UserId => user_id,
|
||||||
|
EventMatchPatternType::UserLocalpart => get_localpart_from_id(user_id)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.match_related_event_match(
|
||||||
|
&event_match.rel_type.clone(),
|
||||||
|
event_match.include_fallbacks,
|
||||||
|
Some(event_match.key.clone()),
|
||||||
|
Some(Cow::Borrowed(pattern)),
|
||||||
|
)?
|
||||||
}
|
}
|
||||||
KnownCondition::ExactEventPropertyContains(exact_event_match) => {
|
KnownCondition::ExactEventPropertyContains(exact_event_match) => {
|
||||||
self.match_exact_event_property_contains(exact_event_match)?
|
self.match_exact_event_property_contains(exact_event_match)?
|
||||||
@ -325,32 +370,12 @@ impl PushRuleEvaluator {
|
|||||||
/// Evaluates a `event_match` condition.
|
/// Evaluates a `event_match` condition.
|
||||||
fn match_event_match(
|
fn match_event_match(
|
||||||
&self,
|
&self,
|
||||||
event_match: &EventMatchCondition,
|
flattened_event: &BTreeMap<String, JsonValue>,
|
||||||
user_id: Option<&str>,
|
key: &str,
|
||||||
|
pattern: &str,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let pattern = if let Some(pattern) = &event_match.pattern {
|
|
||||||
pattern
|
|
||||||
} else if let Some(pattern_type) = &event_match.pattern_type {
|
|
||||||
// The `pattern_type` can either be "user_id" or "user_localpart",
|
|
||||||
// either way if we don't have a `user_id` then the condition can't
|
|
||||||
// match.
|
|
||||||
let user_id = if let Some(user_id) = user_id {
|
|
||||||
user_id
|
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
match &**pattern_type {
|
|
||||||
"user_id" => user_id,
|
|
||||||
"user_localpart" => get_localpart_from_id(user_id)?,
|
|
||||||
_ => return Ok(false),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
let haystack = if let Some(JsonValue::Value(SimpleJsonValue::Str(haystack))) =
|
let haystack = if let Some(JsonValue::Value(SimpleJsonValue::Str(haystack))) =
|
||||||
self.flattened_keys.get(&*event_match.key)
|
flattened_event.get(key)
|
||||||
{
|
{
|
||||||
haystack
|
haystack
|
||||||
} else {
|
} else {
|
||||||
@ -359,7 +384,7 @@ impl PushRuleEvaluator {
|
|||||||
|
|
||||||
// For the content.body we match against "words", but for everything
|
// For the content.body we match against "words", but for everything
|
||||||
// else we match against the entire value.
|
// else we match against the entire value.
|
||||||
let match_type = if event_match.key == "content.body" {
|
let match_type = if key == "content.body" {
|
||||||
GlobMatchType::Word
|
GlobMatchType::Word
|
||||||
} else {
|
} else {
|
||||||
GlobMatchType::Whole
|
GlobMatchType::Whole
|
||||||
@ -395,8 +420,10 @@ impl PushRuleEvaluator {
|
|||||||
/// Evaluates a `related_event_match` condition. (MSC3664)
|
/// Evaluates a `related_event_match` condition. (MSC3664)
|
||||||
fn match_related_event_match(
|
fn match_related_event_match(
|
||||||
&self,
|
&self,
|
||||||
event_match: &RelatedEventMatchCondition,
|
rel_type: &str,
|
||||||
user_id: Option<&str>,
|
include_fallbacks: Option<bool>,
|
||||||
|
key: Option<Cow<str>>,
|
||||||
|
pattern: Option<Cow<str>>,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
// First check if related event matching is enabled...
|
// First check if related event matching is enabled...
|
||||||
if !self.related_event_match_enabled {
|
if !self.related_event_match_enabled {
|
||||||
@ -404,7 +431,7 @@ impl PushRuleEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the related event, fail if there is none.
|
// get the related event, fail if there is none.
|
||||||
let event = if let Some(event) = self.related_events_flattened.get(&*event_match.rel_type) {
|
let event = if let Some(event) = self.related_events_flattened.get(rel_type) {
|
||||||
event
|
event
|
||||||
} else {
|
} else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
@ -412,58 +439,18 @@ impl PushRuleEvaluator {
|
|||||||
|
|
||||||
// If we are not matching fallbacks, don't match if our special key indicating this is a
|
// If we are not matching fallbacks, don't match if our special key indicating this is a
|
||||||
// fallback relation is not present.
|
// fallback relation is not present.
|
||||||
if !event_match.include_fallbacks.unwrap_or(false)
|
if !include_fallbacks.unwrap_or(false) && event.contains_key("im.vector.is_falling_back") {
|
||||||
&& event.contains_key("im.vector.is_falling_back")
|
|
||||||
{
|
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have no key, accept the event as matching, if it existed without matching any
|
match (key, pattern) {
|
||||||
// fields.
|
// if we have no key, accept the event as matching.
|
||||||
let key = if let Some(key) = &event_match.key {
|
(None, _) => Ok(true),
|
||||||
key
|
// There was a key, so we *must* have a pattern to go with it.
|
||||||
} else {
|
(Some(_), None) => Ok(false),
|
||||||
return Ok(true);
|
// If there is a key & pattern, check if they're in the flattened event (given by rel_type).
|
||||||
};
|
(Some(key), Some(pattern)) => self.match_event_match(event, &key, &pattern),
|
||||||
|
|
||||||
let pattern = if let Some(pattern) = &event_match.pattern {
|
|
||||||
pattern
|
|
||||||
} else if let Some(pattern_type) = &event_match.pattern_type {
|
|
||||||
// The `pattern_type` can either be "user_id" or "user_localpart",
|
|
||||||
// either way if we don't have a `user_id` then the condition can't
|
|
||||||
// match.
|
|
||||||
let user_id = if let Some(user_id) = user_id {
|
|
||||||
user_id
|
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
match &**pattern_type {
|
|
||||||
"user_id" => user_id,
|
|
||||||
"user_localpart" => get_localpart_from_id(user_id)?,
|
|
||||||
_ => return Ok(false),
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
let haystack =
|
|
||||||
if let Some(JsonValue::Value(SimpleJsonValue::Str(haystack))) = event.get(&**key) {
|
|
||||||
haystack
|
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
// For the content.body we match against "words", but for everything
|
|
||||||
// else we match against the entire value.
|
|
||||||
let match_type = if key == "content.body" {
|
|
||||||
GlobMatchType::Word
|
|
||||||
} else {
|
|
||||||
GlobMatchType::Whole
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut compiled_pattern = get_glob_matcher(pattern, match_type)?;
|
|
||||||
compiled_pattern.is_match(haystack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates a `exact_event_property_contains` condition. (MSC3758)
|
/// Evaluates a `exact_event_property_contains` condition. (MSC3758)
|
||||||
|
@ -328,10 +328,16 @@ pub enum Condition {
|
|||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum KnownCondition {
|
pub enum KnownCondition {
|
||||||
EventMatch(EventMatchCondition),
|
EventMatch(EventMatchCondition),
|
||||||
|
// Identical to event_match but gives predefined patterns. Cannot be added by users.
|
||||||
|
#[serde(skip_deserializing, rename = "event_match")]
|
||||||
|
EventMatchType(EventMatchTypeCondition),
|
||||||
#[serde(rename = "com.beeper.msc3758.exact_event_match")]
|
#[serde(rename = "com.beeper.msc3758.exact_event_match")]
|
||||||
ExactEventMatch(ExactEventMatchCondition),
|
ExactEventMatch(ExactEventMatchCondition),
|
||||||
#[serde(rename = "im.nheko.msc3664.related_event_match")]
|
#[serde(rename = "im.nheko.msc3664.related_event_match")]
|
||||||
RelatedEventMatch(RelatedEventMatchCondition),
|
RelatedEventMatch(RelatedEventMatchCondition),
|
||||||
|
// Identical to related_event_match but gives predefined patterns. Cannot be added by users.
|
||||||
|
#[serde(skip_deserializing, rename = "im.nheko.msc3664.related_event_match")]
|
||||||
|
RelatedEventMatchType(RelatedEventMatchTypeCondition),
|
||||||
#[serde(rename = "org.matrix.msc3966.exact_event_property_contains")]
|
#[serde(rename = "org.matrix.msc3966.exact_event_property_contains")]
|
||||||
ExactEventPropertyContains(ExactEventMatchCondition),
|
ExactEventPropertyContains(ExactEventMatchCondition),
|
||||||
#[serde(rename = "org.matrix.msc3952.is_user_mention")]
|
#[serde(rename = "org.matrix.msc3952.is_user_mention")]
|
||||||
@ -362,14 +368,27 @@ impl<'source> FromPyObject<'source> for Condition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body of a [`Condition::EventMatch`]
|
/// The body of a [`Condition::EventMatch`] with a pattern.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct EventMatchCondition {
|
pub struct EventMatchCondition {
|
||||||
pub key: Cow<'static, str>,
|
pub key: Cow<'static, str>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
pub pattern: Cow<'static, str>,
|
||||||
pub pattern: Option<Cow<'static, str>>,
|
}
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub pattern_type: Option<Cow<'static, str>>,
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum EventMatchPatternType {
|
||||||
|
UserId,
|
||||||
|
UserLocalpart,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The body of a [`Condition::EventMatch`] that uses user_id or user_localpart as a pattern.
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct EventMatchTypeCondition {
|
||||||
|
pub key: Cow<'static, str>,
|
||||||
|
// During serialization, the pattern_type property gets replaced with a
|
||||||
|
// pattern property of the correct value in synapse.push.clientformat.format_push_rules_for_user.
|
||||||
|
pub pattern_type: Cow<'static, EventMatchPatternType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The body of a [`Condition::ExactEventMatch`]
|
/// The body of a [`Condition::ExactEventMatch`]
|
||||||
@ -386,8 +405,18 @@ pub struct RelatedEventMatchCondition {
|
|||||||
pub key: Option<Cow<'static, str>>,
|
pub key: Option<Cow<'static, str>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub pattern: Option<Cow<'static, str>>,
|
pub pattern: Option<Cow<'static, str>>,
|
||||||
|
pub rel_type: Cow<'static, str>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub pattern_type: Option<Cow<'static, str>>,
|
pub include_fallbacks: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The body of a [`Condition::RelatedEventMatch`] that uses user_id or user_localpart as a pattern.
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
pub struct RelatedEventMatchTypeCondition {
|
||||||
|
// This is only used if pattern_type exists (and thus key must exist), so is
|
||||||
|
// a bit simpler than RelatedEventMatchCondition.
|
||||||
|
pub key: Cow<'static, str>,
|
||||||
|
pub pattern_type: Cow<'static, EventMatchPatternType>,
|
||||||
pub rel_type: Cow<'static, str>,
|
pub rel_type: Cow<'static, str>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub include_fallbacks: Option<bool>,
|
pub include_fallbacks: Option<bool>,
|
||||||
@ -571,8 +600,7 @@ impl FilteredPushRules {
|
|||||||
fn test_serialize_condition() {
|
fn test_serialize_condition() {
|
||||||
let condition = Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
let condition = Condition::Known(KnownCondition::EventMatch(EventMatchCondition {
|
||||||
key: "content.body".into(),
|
key: "content.body".into(),
|
||||||
pattern: Some("coffee".into()),
|
pattern: "coffee".into(),
|
||||||
pattern_type: None,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let json = serde_json::to_string(&condition).unwrap();
|
let json = serde_json::to_string(&condition).unwrap();
|
||||||
@ -586,7 +614,33 @@ fn test_serialize_condition() {
|
|||||||
fn test_deserialize_condition() {
|
fn test_deserialize_condition() {
|
||||||
let json = r#"{"kind":"event_match","key":"content.body","pattern":"coffee"}"#;
|
let json = r#"{"kind":"event_match","key":"content.body","pattern":"coffee"}"#;
|
||||||
|
|
||||||
let _: Condition = serde_json::from_str(json).unwrap();
|
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||||
|
assert!(matches!(
|
||||||
|
condition,
|
||||||
|
Condition::Known(KnownCondition::EventMatch(_))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialize_event_match_condition_with_pattern_type() {
|
||||||
|
let condition = Condition::Known(KnownCondition::EventMatchType(EventMatchTypeCondition {
|
||||||
|
key: "content.body".into(),
|
||||||
|
pattern_type: Cow::Owned(EventMatchPatternType::UserId),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&condition).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
json,
|
||||||
|
r#"{"kind":"event_match","key":"content.body","pattern_type":"user_id"}"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cannot_deserialize_event_match_condition_with_pattern_type() {
|
||||||
|
let json = r#"{"kind":"event_match","key":"content.body","pattern_type":"user_id"}"#;
|
||||||
|
|
||||||
|
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||||
|
assert!(matches!(condition, Condition::Unknown(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -600,6 +654,37 @@ fn test_deserialize_unstable_msc3664_condition() {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialize_unstable_msc3664_condition_with_pattern_type() {
|
||||||
|
let condition = Condition::Known(KnownCondition::RelatedEventMatchType(
|
||||||
|
RelatedEventMatchTypeCondition {
|
||||||
|
key: "content.body".into(),
|
||||||
|
pattern_type: Cow::Owned(EventMatchPatternType::UserId),
|
||||||
|
rel_type: "m.in_reply_to".into(),
|
||||||
|
include_fallbacks: Some(true),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&condition).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
json,
|
||||||
|
r#"{"kind":"im.nheko.msc3664.related_event_match","key":"content.body","pattern_type":"user_id","rel_type":"m.in_reply_to","include_fallbacks":true}"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cannot_deserialize_unstable_msc3664_condition_with_pattern_type() {
|
||||||
|
let json = r#"{"kind":"im.nheko.msc3664.related_event_match","key":"content.body","pattern_type":"user_id","rel_type":"m.in_reply_to"}"#;
|
||||||
|
|
||||||
|
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||||
|
// Since pattern is optional on RelatedEventMatch it deserializes it to that
|
||||||
|
// instead of RelatedEventMatchType.
|
||||||
|
assert!(matches!(
|
||||||
|
condition,
|
||||||
|
Condition::Known(KnownCondition::RelatedEventMatch(_))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_unstable_msc3931_condition() {
|
fn test_deserialize_unstable_msc3931_condition() {
|
||||||
let json =
|
let json =
|
||||||
|
@ -401,6 +401,33 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
|
|||||||
"pattern should not match before a newline",
|
"pattern should not match before a newline",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_event_match_pattern(self) -> None:
|
||||||
|
"""Check that event_match conditions do not use a "pattern_type" from user data."""
|
||||||
|
|
||||||
|
# The pattern_type should not be deserialized into anything valid.
|
||||||
|
condition = {
|
||||||
|
"kind": "event_match",
|
||||||
|
"key": "content.value",
|
||||||
|
"pattern_type": "user_id",
|
||||||
|
}
|
||||||
|
self._assert_not_matches(
|
||||||
|
condition,
|
||||||
|
{"value": "@user:test"},
|
||||||
|
"should not be possible to pass a pattern_type in",
|
||||||
|
)
|
||||||
|
|
||||||
|
# This is an internal-only condition which shouldn't get deserialized.
|
||||||
|
condition = {
|
||||||
|
"kind": "event_match_type",
|
||||||
|
"key": "content.value",
|
||||||
|
"pattern_type": "user_id",
|
||||||
|
}
|
||||||
|
self._assert_not_matches(
|
||||||
|
condition,
|
||||||
|
{"value": "@user:test"},
|
||||||
|
"should not be possible to pass a pattern_type in",
|
||||||
|
)
|
||||||
|
|
||||||
def test_exact_event_match_string(self) -> None:
|
def test_exact_event_match_string(self) -> None:
|
||||||
"""Check that exact_event_match conditions work as expected for strings."""
|
"""Check that exact_event_match conditions work as expected for strings."""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user