diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py index b20d949689ec..cc417e2fbf9b 100644 --- a/synapse/config/experimental.py +++ b/synapse/config/experimental.py @@ -84,3 +84,6 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None: # MSC3786 (Add a default push rule to ignore m.room.server_acl events) self.msc3786_enabled: bool = experimental.get("msc3786_enabled", False) + + # MSC3772: A push rule for mutual relations. + self.msc3772_enabled: bool = experimental.get("msc3772_enabled", False) diff --git a/synapse/push/bulk_push_rule_evaluator.py b/synapse/push/bulk_push_rule_evaluator.py index a59161ffd730..5122d7fe1061 100644 --- a/synapse/push/bulk_push_rule_evaluator.py +++ b/synapse/push/bulk_push_rule_evaluator.py @@ -120,6 +120,9 @@ def __init__(self, hs: "HomeServer"): resizable=False, ) + # Whether to support MSC3772 is supported. + self._relations_match_enabled = self.hs.config.experimental.msc3772_enabled + async def _get_rules_for_event( self, event: EventBase, context: EventContext ) -> Dict[str, List[Dict[str, Any]]]: @@ -214,7 +217,12 @@ async def action_for_event_by_user( relations = await self.store.get_mutual_event_relations(event) evaluator = PushRuleEvaluatorForEvent( - event, len(room_members), sender_power_level, power_levels, relations + event, + len(room_members), + sender_power_level, + power_levels, + relations, + self._relations_match_enabled, ) # If the event is not a state event check if any users ignore the sender. diff --git a/synapse/push/push_rule_evaluator.py b/synapse/push/push_rule_evaluator.py index 18516fae7ec5..182c4f6cf1f4 100644 --- a/synapse/push/push_rule_evaluator.py +++ b/synapse/push/push_rule_evaluator.py @@ -121,12 +121,14 @@ def __init__( sender_power_level: int, power_levels: Dict[str, Union[int, Dict[str, int]]], relations: Set[Tuple[str, str, str]], + relations_match_enabled: bool, ): self._event = event self._room_member_count = room_member_count self._sender_power_level = sender_power_level self._power_levels = power_levels self._relations = relations + self._relations_match_enabled = relations_match_enabled # Maps strings of e.g. 'content.body' -> event["content"]["body"] self._value_cache = _flatten_dict(event) @@ -190,7 +192,10 @@ def matches( return _sender_notification_permission( self._event, condition, self._sender_power_level, self._power_levels ) - elif condition["kind"] == "org.matrix.msc3772.relation_match": + elif ( + condition["kind"] == "org.matrix.msc3772.relation_match" + and self._relations_match_enabled + ): return self._relation_match(condition, user_id) else: return True diff --git a/synapse/storage/databases/main/push_rule.py b/synapse/storage/databases/main/push_rule.py index 4ed913e24879..708cc84da279 100644 --- a/synapse/storage/databases/main/push_rule.py +++ b/synapse/storage/databases/main/push_rule.py @@ -54,6 +54,11 @@ def _is_experimental_rule_enabled( and not experimental_config.msc3786_enabled ): return False + if ( + rule_id == "global/underride/.org.matrix.msc3772.thread_reply" + and not experimental_config.msc3772_enabled + ): + return False return True diff --git a/tests/push/test_push_rule_evaluator.py b/tests/push/test_push_rule_evaluator.py index 8980836bd1a7..d25dc49a3b1a 100644 --- a/tests/push/test_push_rule_evaluator.py +++ b/tests/push/test_push_rule_evaluator.py @@ -27,7 +27,10 @@ class PushRuleEvaluatorTestCase(unittest.TestCase): def _get_evaluator( - self, content: JsonDict, relations: Optional[Set[Tuple[str, str, str]]] = None + self, + content: JsonDict, + relations: Optional[Set[Tuple[str, str, str]]] = None, + relations_match_enabled: bool = False, ) -> PushRuleEvaluatorForEvent: event = FrozenEvent( { @@ -49,6 +52,7 @@ def _get_evaluator( sender_power_level, power_levels, relations or set(), + relations_match_enabled, ) def test_display_name(self) -> None: @@ -285,9 +289,19 @@ def test_tweaks_for_actions(self) -> None: def test_relation_match(self) -> None: """Test the relation_match push rule kind.""" + + # Check if the experimental feature is disabled. evaluator = self._get_evaluator( {}, {("m.annotation", "@user:test", "m.reaction")} ) + condition = {"kind": "relation_match"} + # Oddly, an unknown condition always matches. + self.assertTrue(evaluator.matches(condition, "@user:test", "foo")) + + # A push rule evaluator with the experimental rule enabled. + evaluator = self._get_evaluator( + {}, {("m.annotation", "@user:test", "m.reaction")}, True + ) # Check just relation type. condition = {