feat(router): Steuerungs-Endpunkte blocken restricted-User (403)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jesko Anschütz 2026-03-27 21:32:40 +01:00
parent 18ba448f05
commit f1dcb4f1d3

View file

@ -141,6 +141,16 @@ func registerManageRoutes(mux *http.ServeMux, d RouterDeps) {
authScreen := func(h http.Handler) http.Handler { authScreen := func(h http.Handler) http.Handler {
return chain(h, RequireAuth(d.AuthStore), RequireScreenAccess(d.ScreenStore), setCSRF, csrf) return chain(h, RequireAuth(d.AuthStore), RequireScreenAccess(d.ScreenStore), setCSRF, csrf)
} }
// authScreenControl: wie authScreen, aber restricted-User werden mit 403 blockiert.
// Für Endpunkte, die restricted-User nicht nutzen dürfen (Display, Zeitplan, Override).
authScreenControl := func(h http.Handler) http.Handler {
return chain(h, RequireAuth(d.AuthStore), RequireScreenAccess(d.ScreenStore), RequireNotRestricted, setCSRF, csrf)
}
// authOnlyControl: wie authOnly, aber restricted-User werden mit 403 blockiert.
// Für globalen Override (kein spezifischer Screen).
authOnlyControl := func(h http.Handler) http.Handler {
return chain(h, RequireAuth(d.AuthStore), RequireNotRestricted, setCSRF, csrf)
}
// ── Admin UI ────────────────────────────────────────────────────────── // ── Admin UI ──────────────────────────────────────────────────────────
mux.Handle("GET /admin", mux.Handle("GET /admin",
@ -187,23 +197,23 @@ func registerManageRoutes(mux *http.ServeMux, d RouterDeps) {
// ── Display control ─────────────────────────────────────────────────── // ── Display control ───────────────────────────────────────────────────
mux.Handle("POST /api/v1/screens/{screenSlug}/display", mux.Handle("POST /api/v1/screens/{screenSlug}/display",
authScreen(http.HandlerFunc(manage.HandleDisplayCommand(notifier)))) authScreenControl(http.HandlerFunc(manage.HandleDisplayCommand(notifier))))
// ── Schedule control ────────────────────────────────────────────────── // ── Schedule control ──────────────────────────────────────────────────
mux.Handle("POST /api/v1/screens/{screenSlug}/schedule", mux.Handle("POST /api/v1/screens/{screenSlug}/schedule",
authScreen(http.HandlerFunc(manage.HandleUpdateSchedule(d.ScreenStore, d.ScheduleStore)))) authScreenControl(http.HandlerFunc(manage.HandleUpdateSchedule(d.ScreenStore, d.ScheduleStore))))
// ── Globaler Override ──────────────────────────────────────────────── // ── Globaler Override ────────────────────────────────────────────────
mux.Handle("GET /api/v1/global-override", mux.Handle("GET /api/v1/global-override",
authOnly(http.HandlerFunc(manage.HandleGetGlobalOverride(d.GlobalOverrideStore)))) authOnly(http.HandlerFunc(manage.HandleGetGlobalOverride(d.GlobalOverrideStore))))
mux.Handle("POST /api/v1/global-override", mux.Handle("POST /api/v1/global-override",
authOnly(http.HandlerFunc(manage.HandleSetGlobalOverride(d.GlobalOverrideStore, d.ScreenStore, notifier)))) authOnlyControl(http.HandlerFunc(manage.HandleSetGlobalOverride(d.GlobalOverrideStore, d.ScreenStore, notifier))))
mux.Handle("DELETE /api/v1/global-override", mux.Handle("DELETE /api/v1/global-override",
authOnly(http.HandlerFunc(manage.HandleDeleteGlobalOverride(d.GlobalOverrideStore)))) authOnlyControl(http.HandlerFunc(manage.HandleDeleteGlobalOverride(d.GlobalOverrideStore))))
// ── Per-Screen Override ─────────────────────────────────────────────── // ── Per-Screen Override ───────────────────────────────────────────────
mux.Handle("POST /api/v1/screens/{screenSlug}/override", mux.Handle("POST /api/v1/screens/{screenSlug}/override",
authScreen(http.HandlerFunc(manage.HandleSetScreenOverride(d.ScreenStore, d.ScheduleStore)))) authScreenControl(http.HandlerFunc(manage.HandleSetScreenOverride(d.ScreenStore, d.ScheduleStore))))
// ── JSON API — screens ──────────────────────────────────────────────── // ── JSON API — screens ────────────────────────────────────────────────
// Self-registration: no auth (player calls this on startup). // Self-registration: no auth (player calls this on startup).