summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorKateřina Churanová <katerina.churanova@gmail.com>2022-09-28 14:31:53 +0200
committerGitHub <noreply@github.com>2022-09-28 12:31:53 +0000
commit6caa3030835f879724c003a5b0dc66a6285451d8 (patch)
tree9e33ccb6e4e086c19e211bd8dc7ab21a52f41496 /synapse
parentAdd instruction for running unit tests in parallel (#13928) (diff)
downloadsynapse-6caa3030835f879724c003a5b0dc66a6285451d8.tar.xz
fix: Push notifications for invite over federation (#13719)
Diffstat (limited to 'synapse')
-rw-r--r--synapse/events/__init__.py4
-rw-r--r--synapse/handlers/federation.py13
-rw-r--r--synapse/handlers/federation_event.py1
-rw-r--r--synapse/push/bulk_push_rule_evaluator.py10
-rw-r--r--synapse/push/push_rule_evaluator.py16
-rw-r--r--synapse/storage/controllers/persist_events.py10
-rw-r--r--synapse/storage/databases/main/events.py10
7 files changed, 41 insertions, 23 deletions
diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py
index b2c9119fd0..030c3ca408 100644
--- a/synapse/events/__init__.py
+++ b/synapse/events/__init__.py
@@ -289,6 +289,10 @@ class _EventInternalMetadata:
         """
         return self._dict.get("historical", False)
 
+    def is_notifiable(self) -> bool:
+        """Whether this event can trigger a push notification"""
+        return not self.is_outlier() or self.is_out_of_band_membership()
+
 
 class EventBase(metaclass=abc.ABCMeta):
     @property
diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index 74580f60df..8f847ff845 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -149,6 +149,7 @@ class FederationHandler:
         self.http_client = hs.get_proxied_blacklisted_http_client()
         self._replication = hs.get_replication_data_handler()
         self._federation_event_handler = hs.get_federation_event_handler()
+        self._bulk_push_rule_evaluator = hs.get_bulk_push_rule_evaluator()
 
         self._clean_room_for_join_client = ReplicationCleanRoomRestServlet.make_client(
             hs
@@ -956,9 +957,15 @@ class FederationHandler:
         )
 
         context = EventContext.for_outlier(self._storage_controllers)
-        await self._federation_event_handler.persist_events_and_notify(
-            event.room_id, [(event, context)]
-        )
+
+        await self._bulk_push_rule_evaluator.action_for_event_by_user(event, context)
+        try:
+            await self._federation_event_handler.persist_events_and_notify(
+                event.room_id, [(event, context)]
+            )
+        except Exception:
+            await self.store.remove_push_actions_from_staging(event.event_id)
+            raise
 
         return event
 
diff --git a/synapse/handlers/federation_event.py b/synapse/handlers/federation_event.py
index 2d7cde7506..3fac256881 100644
--- a/synapse/handlers/federation_event.py
+++ b/synapse/handlers/federation_event.py
@@ -2170,6 +2170,7 @@ class FederationEventHandler:
         if instance != self._instance_name:
             # Limit the number of events sent over replication. We choose 200
             # here as that is what we default to in `max_request_body_size(..)`
+            result = {}
             try:
                 for batch in batch_iter(event_and_contexts, 200):
                     result = await self._send_events(
diff --git a/synapse/push/bulk_push_rule_evaluator.py b/synapse/push/bulk_push_rule_evaluator.py
index 404379ef67..32313e3bcf 100644
--- a/synapse/push/bulk_push_rule_evaluator.py
+++ b/synapse/push/bulk_push_rule_evaluator.py
@@ -173,7 +173,11 @@ class BulkPushRuleEvaluator:
 
     async def _get_power_levels_and_sender_level(
         self, event: EventBase, context: EventContext
-    ) -> Tuple[dict, int]:
+    ) -> Tuple[dict, Optional[int]]:
+        # There are no power levels and sender levels possible to get from outlier
+        if event.internal_metadata.is_outlier():
+            return {}, None
+
         event_types = auth_types_for_event(event.room_version, event)
         prev_state_ids = await context.get_prev_state_ids(
             StateFilter.from_types(event_types)
@@ -250,8 +254,8 @@ class BulkPushRuleEvaluator:
         should increment the unread count, and insert the results into the
         event_push_actions_staging table.
         """
-        if event.internal_metadata.is_outlier():
-            # This can happen due to out of band memberships
+        if not event.internal_metadata.is_notifiable():
+            # Push rules for events that aren't notifiable can't be processed by this
             return
 
         # Disable counting as unread unless the experimental configuration is
diff --git a/synapse/push/push_rule_evaluator.py b/synapse/push/push_rule_evaluator.py
index 3c5632cd91..f8176c5a42 100644
--- a/synapse/push/push_rule_evaluator.py
+++ b/synapse/push/push_rule_evaluator.py
@@ -42,18 +42,18 @@ IS_GLOB = re.compile(r"[\?\*\[\]]")
 INEQUALITY_EXPR = re.compile("^([=<>]*)([0-9]*)$")
 
 
-def _room_member_count(
-    ev: EventBase, condition: Mapping[str, Any], room_member_count: int
-) -> bool:
+def _room_member_count(condition: Mapping[str, Any], room_member_count: int) -> bool:
     return _test_ineq_condition(condition, room_member_count)
 
 
 def _sender_notification_permission(
-    ev: EventBase,
     condition: Mapping[str, Any],
-    sender_power_level: int,
+    sender_power_level: Optional[int],
     power_levels: Dict[str, Union[int, Dict[str, int]]],
 ) -> bool:
+    if sender_power_level is None:
+        return False
+
     notif_level_key = condition.get("key")
     if notif_level_key is None:
         return False
@@ -129,7 +129,7 @@ class PushRuleEvaluatorForEvent:
         self,
         event: EventBase,
         room_member_count: int,
-        sender_power_level: int,
+        sender_power_level: Optional[int],
         power_levels: Dict[str, Union[int, Dict[str, int]]],
         relations: Dict[str, Set[Tuple[str, str]]],
         relations_match_enabled: bool,
@@ -198,10 +198,10 @@ class PushRuleEvaluatorForEvent:
         elif condition["kind"] == "contains_display_name":
             return self._contains_display_name(display_name)
         elif condition["kind"] == "room_member_count":
-            return _room_member_count(self._event, condition, self._room_member_count)
+            return _room_member_count(condition, self._room_member_count)
         elif condition["kind"] == "sender_notification_permission":
             return _sender_notification_permission(
-                self._event, condition, self._sender_power_level, self._power_levels
+                condition, self._sender_power_level, self._power_levels
             )
         elif (
             condition["kind"] == "org.matrix.msc3772.relation_match"
diff --git a/synapse/storage/controllers/persist_events.py b/synapse/storage/controllers/persist_events.py
index 709cb792ed..06e71a8053 100644
--- a/synapse/storage/controllers/persist_events.py
+++ b/synapse/storage/controllers/persist_events.py
@@ -423,16 +423,18 @@ class EventsPersistenceStorageController:
         for d in ret_vals:
             replaced_events.update(d)
 
-        events = []
+        persisted_events = []
         for event, _ in events_and_contexts:
             existing_event_id = replaced_events.get(event.event_id)
             if existing_event_id:
-                events.append(await self.main_store.get_event(existing_event_id))
+                persisted_events.append(
+                    await self.main_store.get_event(existing_event_id)
+                )
             else:
-                events.append(event)
+                persisted_events.append(event)
 
         return (
-            events,
+            persisted_events,
             self.main_store.get_room_max_token(),
         )
 
diff --git a/synapse/storage/databases/main/events.py b/synapse/storage/databases/main/events.py
index b59eb7478b..bb489b8189 100644
--- a/synapse/storage/databases/main/events.py
+++ b/synapse/storage/databases/main/events.py
@@ -2134,13 +2134,13 @@ class PersistEventsStore:
                 appear in events_and_context.
         """
 
-        # Only non outlier events will have push actions associated with them,
+        # Only notifiable events will have push actions associated with them,
         # so let's filter them out. (This makes joining large rooms faster, as
         # these queries took seconds to process all the state events).
-        non_outlier_events = [
+        notifiable_events = [
             event
             for event, _ in events_and_contexts
-            if not event.internal_metadata.is_outlier()
+            if event.internal_metadata.is_notifiable()
         ]
 
         sql = """
@@ -2153,7 +2153,7 @@ class PersistEventsStore:
             WHERE event_id = ?
         """
 
-        if non_outlier_events:
+        if notifiable_events:
             txn.execute_batch(
                 sql,
                 (
@@ -2163,7 +2163,7 @@ class PersistEventsStore:
                         event.depth,
                         event.event_id,
                     )
-                    for event in non_outlier_events
+                    for event in notifiable_events
                 ),
             )