feat: Seaca mobile API, enrollment, FCM push and admin UI (0.9.0)

Adds mobile device registration by admin codes, refresh tokens, push channel
in notification policy, and Settings section for managing Seaca clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
PTah
2026-06-10 13:19:14 +10:00
parent 86c602cf07
commit 563b836acc
32 changed files with 1916 additions and 45 deletions
+13 -3
View File
@@ -17,7 +17,8 @@ from app.services.notification_settings import (
VALID_SEVERITIES,
)
DEFAULT_CHANNELS = frozenset({CHANNEL_TELEGRAM, CHANNEL_WEBHOOK, CHANNEL_EMAIL})
CHANNEL_MOBILE = "mobile"
DEFAULT_CHANNELS = frozenset({CHANNEL_TELEGRAM, CHANNEL_WEBHOOK, CHANNEL_EMAIL, CHANNEL_MOBILE})
@dataclass(frozen=True)
@@ -26,6 +27,7 @@ class NotificationPolicyConfig:
use_telegram: bool
use_webhook: bool
use_email: bool
use_mobile: bool
source: str # env | db
def allows_channel(self, channel: str) -> bool:
@@ -35,21 +37,24 @@ class NotificationPolicyConfig:
return self.use_webhook
if channel == CHANNEL_EMAIL:
return self.use_email
if channel == CHANNEL_MOBILE:
return self.use_mobile
return False
def _parse_channels_csv(value: str) -> tuple[bool, bool, bool]:
def _parse_channels_csv(value: str) -> tuple[bool, bool, bool, bool]:
parts = {p.strip().lower() for p in value.split(",") if p.strip()}
return (
CHANNEL_TELEGRAM in parts or "tg" in parts,
CHANNEL_WEBHOOK in parts,
CHANNEL_EMAIL in parts or "mail" in parts or "smtp" in parts,
CHANNEL_MOBILE in parts or "push" in parts or "fcm" in parts,
)
def _policy_from_env() -> NotificationPolicyConfig:
settings = get_settings()
use_tg, use_wh, use_em = _parse_channels_csv(settings.notify_channels)
use_tg, use_wh, use_em, use_mob = _parse_channels_csv(settings.notify_channels)
min_sev = settings.notify_min_severity.strip() or "warning"
if min_sev not in VALID_SEVERITIES:
min_sev = "warning"
@@ -58,6 +63,7 @@ def _policy_from_env() -> NotificationPolicyConfig:
use_telegram=use_tg,
use_webhook=use_wh,
use_email=use_em,
use_mobile=use_mob,
source="env",
)
@@ -86,6 +92,7 @@ def get_effective_notification_policy(db: Session | None = None) -> Notification
use_telegram=bool(row.use_telegram),
use_webhook=bool(row.use_webhook),
use_email=bool(row.use_email),
use_mobile=bool(getattr(row, "use_mobile", False)),
source="db",
)
@@ -104,6 +111,7 @@ def upsert_notification_policy(
use_telegram: bool,
use_webhook: bool,
use_email: bool,
use_mobile: bool = False,
) -> NotificationPolicyConfig:
if min_severity not in VALID_SEVERITIES:
raise ValueError(f"invalid min_severity: {min_severity}")
@@ -116,6 +124,7 @@ def upsert_notification_policy(
use_telegram=use_telegram,
use_webhook=use_webhook,
use_email=use_email,
use_mobile=use_mobile,
)
db.add(row)
else:
@@ -123,6 +132,7 @@ def upsert_notification_policy(
row.use_telegram = use_telegram
row.use_webhook = use_webhook
row.use_email = use_email
row.use_mobile = use_mobile
_sync_channel_min_severity(db, min_severity)
db.commit()