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