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/notificationsnejsou 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.
sendNotificationareminderDispatchervyhledávají rezervace v rámci firmy přihlášeného staff uživatele.