"""Хранение настроек и push-подписок: app_settings (оверрайды .env) и
push_subscriptions (личные web-push подписки, см. docs/06).
"""
from datetime import datetime
from sqlalchemy import DateTime, Index, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class AppSetting(Base):
"""Оверрайд настройки из .env: {key: value} поверх registry-дефолтов."""
__tablename__ = "app_settings"
key: Mapped[str] = mapped_column(String(64), primary_key=True)
# Значение хранится строкой (коэрсия по типу в settings_registry);
# для секретов — в открытом виде, но write-only через API.
value: Mapped[str | None] = mapped_column(Text)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
)
class PushSubscription(Base):
"""Web-push подписка одного пользователя (одна строка на браузерное устройство).
Пользователь подписывается сам (личный раздел → «Настройки»); канал push
маршрутизации доставляет события тем, кто подписался на адресата события
(payload.user_id). Отключение = удаление строки + unsubscribe на клиенте.
"""
__tablename__ = "push_subscriptions"
__table_args__ = (
Index("ix_pushsubs_user", "user_id", "created_at"),
)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
# sub gnexus-auth — тот же адресат, что у канала user.
user_id: Mapped[str] = mapped_column(String(64))
endpoint: Mapped[str] = mapped_column(String(500), unique=True)
p256dh: Mapped[str] = mapped_column(String(255))
auth: Mapped[str] = mapped_column(String(255))
ua: Mapped[str | None] = mapped_column(String(255))
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), server_default=func.now()
)