Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
Канал Web Push для центра уведомлений (item 5). Ключи VAPID генерируются один раз
и хранятся в platform_settings (без ручной настройки секретов); публичный отдаётся
фронту. Таблица web_push_subscriptions (Phase42) + /api/web-push/{public-key,
subscribe,unsubscribe}. Отправка через web-push-csharp из фонового джоба минусов
(best-effort, протухшие подписки чистятся). SW: обработчики push/notificationclick
(am-v3→am-v4), клик открывает нужный путь. Кнопка «Вкл. push» в колокольчике.
Работает в т.ч. в iOS Safari для PWA на домашнем экране.
Тесты: integration — публичный ключ стабилен, подписка идемпотентна, 400/unsubscribe
(4/4 группы); unit 299/299.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
2.8 KiB
C#
46 lines
2.8 KiB
C#
using foodmarket.Domain.Common;
|
||
|
||
namespace foodmarket.Domain.Platform;
|
||
|
||
/// <summary>Платформенные настройки (singleton, single-row). Хранят SMTP-креды
|
||
/// для отправки писем (forgot-password, инвайты, нотификации). Не tenant-scoped —
|
||
/// общий конфиг для всей платформы, видны и меняются только Супер-администратором.
|
||
///
|
||
/// SmtpPassword хранится зашифрованным через DataProtection API
|
||
/// (`IDataProtectionProvider.CreateProtector("foodmarket.smtp")`); снаружи
|
||
/// (контроллер) — никогда не возвращается в открытом виде, только has-password флаг.</summary>
|
||
public class PlatformSettings : Entity
|
||
{
|
||
/// <summary>SMTP-сервер для отправки исходящей почты (НЕ IMAP — IMAP это
|
||
/// для чтения входящей).</summary>
|
||
public string? SmtpHost { get; set; }
|
||
public int? SmtpPort { get; set; }
|
||
|
||
/// <summary>Implicit TLS (SMTPS, обычно порт 465). Взаимоисключающий
|
||
/// со SmtpStartTls (587).</summary>
|
||
public bool SmtpUseSsl { get; set; }
|
||
|
||
/// <summary>STARTTLS upgrade (обычно порт 587). По дефолту true в большинстве
|
||
/// современных провайдеров (Gmail/Yandex/Mailgun).</summary>
|
||
public bool SmtpStartTls { get; set; } = true;
|
||
|
||
public string? SmtpUsername { get; set; }
|
||
|
||
/// <summary>Зашифрованный SmtpPassword (base64 через DataProtection).
|
||
/// Никогда не отдаётся в API-ответах. Установка только через PUT с
|
||
/// явно переданным new-password полем.</summary>
|
||
public string? SmtpPasswordEncrypted { get; set; }
|
||
|
||
public string? FromEmail { get; set; }
|
||
public string? FromName { get; set; }
|
||
|
||
// ── Web Push (VAPID) ──────────────────────────────────────────────────────
|
||
// Пара ключей VAPID генерируется один раз при первом обращении и хранится
|
||
// здесь (стабильна между рестартами). Публичный ключ отдаётся фронту для
|
||
// подписки; приватный — только серверу (в API-ответах не возвращается).
|
||
public string? WebPushVapidPublicKey { get; set; }
|
||
public string? WebPushVapidPrivateKey { get; set; }
|
||
/// <summary>VAPID subject — mailto:/URL контакта оператора push (по умолчанию mailto:).</summary>
|
||
public string? WebPushVapidSubject { get; set; }
|
||
}
|