Přeskočit obsah

Notifikace

Entity: NotificationSettings, NotificationLog (tabulky notification_settings, notifications)

Funkce: sendNotification, reminderDispatcher

Prověřeno proti commitu: c1d5767 (5. 10. 2026)

Testy: backend/tests/Feature/Audit/NotifikaceAuditTest.php

Routy

Routa Perimetr Ochrana Controller
GET/POST/PUT/DELETE /api/notificationSettings interní oprávnění systémových nastavení EntityCrudController CRUD
GET /api/public/notificationSettings veřejný žádná EntityCrudController::publicList
GET/POST/PUT/DELETE /api/notifications interní oprávnění notifications NotificationController
POST /api/functions/sendNotification interní funkce staff role FunctionsController::invoke
POST /api/cron/functions/reminderDispatcher cron/staff funkce staff role FunctionsController::invoke
php bin/run-reminders.php --email=... CLI aktivní staff uživatel FunctionsController::runReminderDispatcherForUser

Kdo to volá z Reactu

pages/NotificationSettings.jsx čte a ukládá NotificationSettings. Calendar.jsx, Clients.jsx, components/calendar/EventDialog.jsx, components/calendar/PaymentMethodDialog.jsx a components/clients/ClientConsentsTab.jsx volají sendNotification. ClientBooking.jsx a components/clients/ClientBookingsTab.jsx čtou NotificationSettings i z veřejného perimetru.

Opravené nálezy

NOT-01 — SMS API klíč je dostupný veřejným listem nastavení notifikací (kritická)

Stav: opravený

Test: NOT-01: veřejný list nastavení notifikací nevrací SMS API klíč

Ověřený fakt — notificationSettings má v EntityCrudController.php public_list => true a public_filters => ['key']. Veřejný list používá obecný SELECT *, company_id AS company_account_id a veřejná sanitizace neodstraňuje sms_api_key.

Oprava — public sanitizace pro notificationSettings odstraňuje sms_api_key před odesláním odpovědi.

Dopad — anonymní požadavek na /api/public/notificationSettings?q={"key":"default"} může získat klíč pro SMS provider. Útočník by ho mohl použít pro odesílání SMS na účet provozovatele nebo k dalšímu pohybu vůči SMS službě.

Odvozeno — veřejná část potřebuje jen neškodná prezentační pole a šablony nutné pro UI. Tajné hodnoty typu sms_api_key nemají být v obecném public CRUD endpointu vůbec dostupné.

NOT-02 — Veřejný list nastavení notifikací vrací nastavení všech firem (vysoká)

Stav: opravený

Test: NOT-02: veřejný list nastavení notifikací nevrací nastavení jiné firmy

Ověřený fakt — notificationSettings nemá v konfiguraci public_company_scope ani jiný tenant filtr pro veřejný list. Bez staff nebo klientské session tak list skládá dotaz bez company_id omezení a filtruje jen povoleným filtrem key.

Oprava — notificationSettings má public_company_scope => true, takže veřejný list omezuje data na výchozí aktivní veřejnou firmu stejně jako ostatní veřejně scoped číselníky.

Dopad — anonymní klient dostane notifikační šablony, branding, kontaktní údaje a spolu s NOT-01 i SMS klíče všech firem, které mají stejný klíč nastavení.

Odvozeno — pokud má být část nastavení dostupná veřejně, musí být vázaná na vybranou firmu stejným způsobem jako veřejný rezervační perimetr a současně vracet jen explicitní allowlist polí.

Ověřené bez nálezu

  • Interní inbox endpointy /api/notifications nejsou dostupné anonymně.
  • List inbox notifikací filtruje podle firmy a příjemce přihlášeného uživatele.
  • Označení jako přečtené a smazání kontrolují, že notifikace patří přihlášenému uživateli.
  • sendNotification a reminderDispatcher vyhledávají rezervace v rámci firmy přihlášeného staff uživatele.