Initial support for MSC3931: Room version push rule feature flags (#14520)
* Add support for MSC3931: Room Version Supports push rule condition * Create experimental flag for future work, and use it to gate MSC3931 * Changelog entrypull/14521/head
parent
8f10c8b054
commit
3da6450327
|
@ -0,0 +1 @@
|
||||||
|
Add unstable support for an Extensible Events room version (`org.matrix.msc1767.10`) via [MSC1767](https://github.com/matrix-org/matrix-spec-proposals/pull/1767), [MSC3931](https://github.com/matrix-org/matrix-spec-proposals/pull/3931), [MSC3932](https://github.com/matrix-org/matrix-spec-proposals/pull/3932), and [MSC3933](https://github.com/matrix-org/matrix-spec-proposals/pull/3933).
|
|
@ -29,6 +29,10 @@ use super::{
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Used to parse the `is` clause in the room member count condition.
|
/// Used to parse the `is` clause in the room member count condition.
|
||||||
static ref INEQUALITY_EXPR: Regex = Regex::new(r"^([=<>]*)([0-9]+)$").expect("valid regex");
|
static ref INEQUALITY_EXPR: Regex = Regex::new(r"^([=<>]*)([0-9]+)$").expect("valid regex");
|
||||||
|
|
||||||
|
/// Used to determine which MSC3931 room version feature flags are actually known to
|
||||||
|
/// the push evaluator.
|
||||||
|
static ref KNOWN_RVER_FLAGS: Vec<String> = vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allows running a set of push rules against a particular event.
|
/// Allows running a set of push rules against a particular event.
|
||||||
|
@ -57,6 +61,13 @@ pub struct PushRuleEvaluator {
|
||||||
|
|
||||||
/// If msc3664, push rules for related events, is enabled.
|
/// If msc3664, push rules for related events, is enabled.
|
||||||
related_event_match_enabled: bool,
|
related_event_match_enabled: bool,
|
||||||
|
|
||||||
|
/// If MSC3931 is applicable, the feature flags for the room version.
|
||||||
|
room_version_feature_flags: Vec<String>,
|
||||||
|
|
||||||
|
/// If MSC3931 (room version feature flags) is enabled. Usually controlled by the same
|
||||||
|
/// flag as MSC1767 (extensible events core).
|
||||||
|
msc3931_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
|
@ -70,6 +81,8 @@ impl PushRuleEvaluator {
|
||||||
notification_power_levels: BTreeMap<String, i64>,
|
notification_power_levels: BTreeMap<String, i64>,
|
||||||
related_events_flattened: BTreeMap<String, BTreeMap<String, String>>,
|
related_events_flattened: BTreeMap<String, BTreeMap<String, String>>,
|
||||||
related_event_match_enabled: bool,
|
related_event_match_enabled: bool,
|
||||||
|
room_version_feature_flags: Vec<String>,
|
||||||
|
msc3931_enabled: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let body = flattened_keys
|
let body = flattened_keys
|
||||||
.get("content.body")
|
.get("content.body")
|
||||||
|
@ -84,6 +97,8 @@ impl PushRuleEvaluator {
|
||||||
sender_power_level,
|
sender_power_level,
|
||||||
related_events_flattened,
|
related_events_flattened,
|
||||||
related_event_match_enabled,
|
related_event_match_enabled,
|
||||||
|
room_version_feature_flags,
|
||||||
|
msc3931_enabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +219,15 @@ impl PushRuleEvaluator {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
KnownCondition::RoomVersionSupports { feature } => {
|
||||||
|
if !self.msc3931_enabled {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let flag = feature.to_string();
|
||||||
|
KNOWN_RVER_FLAGS.contains(&flag)
|
||||||
|
&& self.room_version_feature_flags.contains(&flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
@ -362,6 +386,8 @@ fn push_rule_evaluator() {
|
||||||
BTreeMap::new(),
|
BTreeMap::new(),
|
||||||
BTreeMap::new(),
|
BTreeMap::new(),
|
||||||
true,
|
true,
|
||||||
|
vec![],
|
||||||
|
true,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,10 @@ pub enum KnownCondition {
|
||||||
SenderNotificationPermission {
|
SenderNotificationPermission {
|
||||||
key: Cow<'static, str>,
|
key: Cow<'static, str>,
|
||||||
},
|
},
|
||||||
|
#[serde(rename = "org.matrix.msc3931.room_version_supports")]
|
||||||
|
RoomVersionSupports {
|
||||||
|
feature: Cow<'static, str>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoPy<PyObject> for Condition {
|
impl IntoPy<PyObject> for Condition {
|
||||||
|
@ -491,6 +495,18 @@ fn test_deserialize_unstable_msc3664_condition() {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_unstable_msc3931_condition() {
|
||||||
|
let json =
|
||||||
|
r#"{"kind":"org.matrix.msc3931.room_version_supports","feature":"org.example.feature"}"#;
|
||||||
|
|
||||||
|
let condition: Condition = serde_json::from_str(json).unwrap();
|
||||||
|
assert!(matches!(
|
||||||
|
condition,
|
||||||
|
Condition::Known(KnownCondition::RoomVersionSupports { feature: _ })
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize_custom_condition() {
|
fn test_deserialize_custom_condition() {
|
||||||
let json = r#"{"kind":"custom_tag"}"#;
|
let json = r#"{"kind":"custom_tag"}"#;
|
||||||
|
|
|
@ -41,6 +41,8 @@ class PushRuleEvaluator:
|
||||||
notification_power_levels: Mapping[str, int],
|
notification_power_levels: Mapping[str, int],
|
||||||
related_events_flattened: Mapping[str, Mapping[str, str]],
|
related_events_flattened: Mapping[str, Mapping[str, str]],
|
||||||
related_event_match_enabled: bool,
|
related_event_match_enabled: bool,
|
||||||
|
room_version_feature_flags: list[str],
|
||||||
|
msc3931_enabled: bool,
|
||||||
): ...
|
): ...
|
||||||
def run(
|
def run(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# 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.
|
||||||
|
|
||||||
from typing import Callable, Dict, Optional
|
from typing import Callable, Dict, List, Optional
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
|
@ -91,6 +91,12 @@ class RoomVersion:
|
||||||
msc3787_knock_restricted_join_rule: bool
|
msc3787_knock_restricted_join_rule: bool
|
||||||
# MSC3667: Enforce integer power levels
|
# MSC3667: Enforce integer power levels
|
||||||
msc3667_int_only_power_levels: bool
|
msc3667_int_only_power_levels: bool
|
||||||
|
# MSC3931: Adds a push rule condition for "room version feature flags", making
|
||||||
|
# some push rules room version dependent. Note that adding a flag to this list
|
||||||
|
# is not enough to mark it "supported": the push rule evaluator also needs to
|
||||||
|
# support the flag. Unknown flags are ignored by the evaluator, making conditions
|
||||||
|
# fail if used.
|
||||||
|
msc3931_push_features: List[str]
|
||||||
|
|
||||||
|
|
||||||
class RoomVersions:
|
class RoomVersions:
|
||||||
|
@ -111,6 +117,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V2 = RoomVersion(
|
V2 = RoomVersion(
|
||||||
"2",
|
"2",
|
||||||
|
@ -129,6 +136,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V3 = RoomVersion(
|
V3 = RoomVersion(
|
||||||
"3",
|
"3",
|
||||||
|
@ -147,6 +155,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V4 = RoomVersion(
|
V4 = RoomVersion(
|
||||||
"4",
|
"4",
|
||||||
|
@ -165,6 +174,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V5 = RoomVersion(
|
V5 = RoomVersion(
|
||||||
"5",
|
"5",
|
||||||
|
@ -183,6 +193,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V6 = RoomVersion(
|
V6 = RoomVersion(
|
||||||
"6",
|
"6",
|
||||||
|
@ -201,6 +212,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
MSC2176 = RoomVersion(
|
MSC2176 = RoomVersion(
|
||||||
"org.matrix.msc2176",
|
"org.matrix.msc2176",
|
||||||
|
@ -219,6 +231,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V7 = RoomVersion(
|
V7 = RoomVersion(
|
||||||
"7",
|
"7",
|
||||||
|
@ -237,6 +250,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V8 = RoomVersion(
|
V8 = RoomVersion(
|
||||||
"8",
|
"8",
|
||||||
|
@ -255,6 +269,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V9 = RoomVersion(
|
V9 = RoomVersion(
|
||||||
"9",
|
"9",
|
||||||
|
@ -273,6 +288,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
MSC3787 = RoomVersion(
|
MSC3787 = RoomVersion(
|
||||||
"org.matrix.msc3787",
|
"org.matrix.msc3787",
|
||||||
|
@ -291,6 +307,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=True,
|
msc3787_knock_restricted_join_rule=True,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
V10 = RoomVersion(
|
V10 = RoomVersion(
|
||||||
"10",
|
"10",
|
||||||
|
@ -309,6 +326,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=False,
|
msc2716_redactions=False,
|
||||||
msc3787_knock_restricted_join_rule=True,
|
msc3787_knock_restricted_join_rule=True,
|
||||||
msc3667_int_only_power_levels=True,
|
msc3667_int_only_power_levels=True,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
MSC2716v4 = RoomVersion(
|
MSC2716v4 = RoomVersion(
|
||||||
"org.matrix.msc2716v4",
|
"org.matrix.msc2716v4",
|
||||||
|
@ -327,6 +345,7 @@ class RoomVersions:
|
||||||
msc2716_redactions=True,
|
msc2716_redactions=True,
|
||||||
msc3787_knock_restricted_join_rule=False,
|
msc3787_knock_restricted_join_rule=False,
|
||||||
msc3667_int_only_power_levels=False,
|
msc3667_int_only_power_levels=False,
|
||||||
|
msc3931_push_features=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -128,3 +128,6 @@ class ExperimentalConfig(Config):
|
||||||
|
|
||||||
# MSC3912: Relation-based redactions.
|
# MSC3912: Relation-based redactions.
|
||||||
self.msc3912_enabled: bool = experimental.get("msc3912_enabled", False)
|
self.msc3912_enabled: bool = experimental.get("msc3912_enabled", False)
|
||||||
|
|
||||||
|
# MSC1767 and friends: Extensible Events
|
||||||
|
self.msc1767_enabled: bool = experimental.get("msc1767_enabled", False)
|
||||||
|
|
|
@ -338,6 +338,10 @@ class BulkPushRuleEvaluator:
|
||||||
for user_id, level in notification_levels.items():
|
for user_id, level in notification_levels.items():
|
||||||
notification_levels[user_id] = int(level)
|
notification_levels[user_id] = int(level)
|
||||||
|
|
||||||
|
room_version_features = event.room_version.msc3931_push_features
|
||||||
|
if not room_version_features:
|
||||||
|
room_version_features = []
|
||||||
|
|
||||||
evaluator = PushRuleEvaluator(
|
evaluator = PushRuleEvaluator(
|
||||||
_flatten_dict(event),
|
_flatten_dict(event),
|
||||||
room_member_count,
|
room_member_count,
|
||||||
|
@ -345,6 +349,8 @@ class BulkPushRuleEvaluator:
|
||||||
notification_levels,
|
notification_levels,
|
||||||
related_events,
|
related_events,
|
||||||
self._related_event_match_enabled,
|
self._related_event_match_enabled,
|
||||||
|
room_version_features,
|
||||||
|
self.hs.config.experimental.msc1767_enabled, # MSC3931 flag
|
||||||
)
|
)
|
||||||
|
|
||||||
users = rules_by_user.keys()
|
users = rules_by_user.keys()
|
||||||
|
|
|
@ -62,6 +62,8 @@ class PushRuleEvaluatorTestCase(unittest.TestCase):
|
||||||
power_levels.get("notifications", {}),
|
power_levels.get("notifications", {}),
|
||||||
{} if related_events is None else related_events,
|
{} if related_events is None else related_events,
|
||||||
True,
|
True,
|
||||||
|
event.room_version.msc3931_push_features,
|
||||||
|
True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_display_name(self) -> None:
|
def test_display_name(self) -> None:
|
||||||
|
|
Loading…
Reference in New Issue