push: Allow to deserialize PushCondition with unknown kind
This commit is contained in:
parent
9460702b00
commit
97fd0c3419
@ -9,6 +9,7 @@ Bug fixes:
|
||||
* Fix deserialization of `RoomMessageEventContent` and `RoomEncryptedEventContent` when there
|
||||
is no relation
|
||||
* Fix deserialization of `StateUnsigned` when the `prev_content` is redacted
|
||||
* Allow to deserialize `PushCondition` with unknown kind
|
||||
|
||||
Breaking changes:
|
||||
|
||||
|
@ -39,6 +39,7 @@ pub use self::{
|
||||
action::{Action, Tweak},
|
||||
condition::{
|
||||
ComparisonOperator, FlattenedJson, PushCondition, PushConditionRoomCtx, RoomMemberCountIs,
|
||||
_CustomPushCondition,
|
||||
},
|
||||
iter::{AnyPushRule, AnyPushRuleRef, RulesetIntoIter, RulesetIter},
|
||||
predefined::{
|
||||
|
@ -13,6 +13,7 @@ use crate::{power_levels::NotificationPowerLevels, serde::Raw, OwnedRoomId, Owne
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
use crate::{PrivOwnedStr, RoomVersionId};
|
||||
|
||||
mod push_condition_serde;
|
||||
mod room_member_count_is;
|
||||
|
||||
pub use room_member_count_is::{ComparisonOperator, RoomMemberCountIs};
|
||||
@ -57,9 +58,8 @@ impl RoomVersionFeature {
|
||||
}
|
||||
|
||||
/// A condition that must apply for an associated push rule's action to be taken.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum PushCondition {
|
||||
/// A glob pattern match on a field of the event.
|
||||
EventMatch {
|
||||
@ -95,11 +95,13 @@ pub enum PushCondition {
|
||||
|
||||
/// Apply the rule only to rooms that support a given feature.
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
#[serde(rename = "org.matrix.msc3931.room_version_supports")]
|
||||
RoomVersionSupports {
|
||||
/// The feature the room must support for the push rule to apply.
|
||||
feature: RoomVersionFeature,
|
||||
},
|
||||
|
||||
#[doc(hidden)]
|
||||
_Custom(_CustomPushCondition),
|
||||
}
|
||||
|
||||
pub(super) fn check_event_match(
|
||||
@ -168,10 +170,24 @@ impl PushCondition {
|
||||
}
|
||||
RoomVersionFeature::_Custom(_) => false,
|
||||
},
|
||||
Self::_Custom(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An unknown push condition.
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[allow(clippy::exhaustive_structs)]
|
||||
pub struct _CustomPushCondition {
|
||||
/// The kind of the condition.
|
||||
kind: String,
|
||||
|
||||
/// The additional fields that the condition contains.
|
||||
#[serde(flatten)]
|
||||
data: BTreeMap<String, JsonValue>,
|
||||
}
|
||||
|
||||
/// The context of the room associated to an event to be able to test all push conditions.
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(clippy::exhaustive_structs)]
|
||||
|
131
crates/ruma-common/src/push/condition/push_condition_serde.rs
Normal file
131
crates/ruma-common/src/push/condition/push_condition_serde.rs
Normal file
@ -0,0 +1,131 @@
|
||||
use serde::{de, Deserialize, Serialize, Serializer};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
use crate::serde::from_raw_json_value;
|
||||
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
use super::RoomVersionFeature;
|
||||
use super::{PushCondition, RoomMemberCountIs};
|
||||
|
||||
impl Serialize for PushCondition {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match self {
|
||||
PushCondition::_Custom(custom) => custom.serialize(serializer),
|
||||
_ => PushConditionSerDeHelper::from(self.clone()).serialize(serializer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for PushCondition {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let json = Box::<RawJsonValue>::deserialize(deserializer)?;
|
||||
let ExtractKind { kind } = from_raw_json_value(&json)?;
|
||||
|
||||
match kind.as_ref() {
|
||||
"event_match"
|
||||
| "contains_display_name"
|
||||
| "room_member_count"
|
||||
| "sender_notification_permission" => {
|
||||
let helper: PushConditionSerDeHelper = from_raw_json_value(&json)?;
|
||||
Ok(helper.into())
|
||||
}
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
"org.matrix.msc3931.room_version_supports" => {
|
||||
let helper: PushConditionSerDeHelper = from_raw_json_value(&json)?;
|
||||
Ok(helper.into())
|
||||
}
|
||||
_ => from_raw_json_value(&json).map(Self::_Custom),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractKind {
|
||||
kind: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
enum PushConditionSerDeHelper {
|
||||
/// A glob pattern match on a field of the event.
|
||||
EventMatch {
|
||||
/// The dot-separated field of the event to match.
|
||||
key: String,
|
||||
|
||||
/// The glob-style pattern to match against.
|
||||
///
|
||||
/// Patterns with no special glob characters should be treated as having asterisks
|
||||
/// prepended and appended when testing the condition.
|
||||
pattern: String,
|
||||
},
|
||||
|
||||
/// Matches unencrypted messages where `content.body` contains the owner's display name in that
|
||||
/// room.
|
||||
ContainsDisplayName,
|
||||
|
||||
/// Matches the current number of members in the room.
|
||||
RoomMemberCount {
|
||||
/// The condition on the current number of members in the room.
|
||||
is: RoomMemberCountIs,
|
||||
},
|
||||
|
||||
/// Takes into account the current power levels in the room, ensuring the sender of the event
|
||||
/// has high enough power to trigger the notification.
|
||||
SenderNotificationPermission {
|
||||
/// The field in the power level event the user needs a minimum power level for.
|
||||
///
|
||||
/// Fields must be specified under the `notifications` property in the power level event's
|
||||
/// `content`.
|
||||
key: String,
|
||||
},
|
||||
|
||||
/// Apply the rule only to rooms that support a given feature.
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
#[serde(rename = "org.matrix.msc3931.room_version_supports")]
|
||||
RoomVersionSupports {
|
||||
/// The feature the room must support for the push rule to apply.
|
||||
feature: RoomVersionFeature,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<PushConditionSerDeHelper> for PushCondition {
|
||||
fn from(value: PushConditionSerDeHelper) -> Self {
|
||||
match value {
|
||||
PushConditionSerDeHelper::EventMatch { key, pattern } => {
|
||||
Self::EventMatch { key, pattern }
|
||||
}
|
||||
PushConditionSerDeHelper::ContainsDisplayName => Self::ContainsDisplayName,
|
||||
PushConditionSerDeHelper::RoomMemberCount { is } => Self::RoomMemberCount { is },
|
||||
PushConditionSerDeHelper::SenderNotificationPermission { key } => {
|
||||
Self::SenderNotificationPermission { key }
|
||||
}
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
PushConditionSerDeHelper::RoomVersionSupports { feature } => {
|
||||
Self::RoomVersionSupports { feature }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PushCondition> for PushConditionSerDeHelper {
|
||||
fn from(value: PushCondition) -> Self {
|
||||
match value {
|
||||
PushCondition::EventMatch { key, pattern } => Self::EventMatch { key, pattern },
|
||||
PushCondition::ContainsDisplayName => Self::ContainsDisplayName,
|
||||
PushCondition::RoomMemberCount { is } => Self::RoomMemberCount { is },
|
||||
PushCondition::SenderNotificationPermission { key } => {
|
||||
Self::SenderNotificationPermission { key }
|
||||
}
|
||||
#[cfg(feature = "unstable-msc3931")]
|
||||
PushCondition::RoomVersionSupports { feature } => Self::RoomVersionSupports { feature },
|
||||
PushCondition::_Custom(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user