Resolve notification worker items to tenants

This commit is contained in:
2026-08-04 09:29:36 +02:00
parent 3c71422b90
commit bb59342b24
3 changed files with 25 additions and 1 deletions
@@ -12,6 +12,17 @@ class SqlNotificationDispatchProvider(NotificationDispatchProvider):
self._settings = context.settings self._settings = context.settings
self._registry = context.registry self._registry = context.registry
def tenant_id_for_notification(
self,
session: object,
*,
notification_id: str,
) -> str | None:
from govoplan_notifications.backend.db.models import NotificationMessage
notification = session.get(NotificationMessage, notification_id) # type: ignore[attr-defined]
return notification.tenant_id if notification is not None else None
def enqueue_notification( def enqueue_notification(
self, self,
session: object, session: object,
@@ -125,7 +125,7 @@ manifest = ModuleManifest(
id="notifications.delivery-operations", id="notifications.delivery-operations",
title="Operate notification delivery", title="Operate notification delivery",
summary="Notifications persists message intent and bounded per-channel attempts before workers dispatch optional delivery channels.", summary="Notifications persists message intent and bounded per-channel attempts before workers dispatch optional delivery channels.",
body="Producing modules emit notifications through the dispatch capability and do not own delivery credentials. In-product delivery is the baseline. Production email delivery is available only through an enabled Mail capability; file delivery remains development-only. Operators can inspect pending and failed attempts and retry only outcomes that are safe to repeat.", body="Producing modules emit notifications through the dispatch capability and do not own delivery credentials. In-product delivery is the baseline. Production email delivery is available only through an enabled Mail capability; file delivery remains development-only. Operators can inspect pending and failed attempts and retry only outcomes that are safe to repeat. Tenant module entitlement is checked before enqueue and again before worker delivery; disabling Notifications preserves accepted messages and exposes an operator action instead of silently consuming them.",
documentation_types=("admin",), documentation_types=("admin",),
audience=("tenant_admin", "operator", "module_admin"), audience=("tenant_admin", "operator", "module_admin"),
related_modules=("mail", "audit", "ops"), related_modules=("mail", "audit", "ops"),
+13
View File
@@ -467,6 +467,19 @@ class NotificationServiceTests(unittest.TestCase):
) )
self.assertEqual(payload["source_module"], "scheduling") self.assertEqual(payload["source_module"], "scheduling")
self.assertEqual(payload["status"], "pending") self.assertEqual(payload["status"], "pending")
self.assertEqual(
"tenant-1",
capability.tenant_id_for_notification(
session,
notification_id=str(payload["id"]),
),
)
self.assertIsNone(
capability.tenant_id_for_notification(
session,
notification_id="missing",
)
)
def test_summary_counts_unread_active_notifications(self) -> None: def test_summary_counts_unread_active_notifications(self) -> None:
with self.Session() as session: with self.Session() as session: