diff --git a/server/backend/internal/app/app.go b/server/backend/internal/app/app.go index 0d73925..5bb3f68 100644 --- a/server/backend/internal/app/app.go +++ b/server/backend/internal/app/app.go @@ -26,8 +26,9 @@ type App struct { server *http.Server notifier *mqttnotifier.Notifier authStore *store.AuthStore - scheduleStore *store.ScreenScheduleStore - screenStore *store.ScreenStore + scheduleStore *store.ScreenScheduleStore + globalOverrideStore *store.GlobalOverrideStore + screenStore *store.ScreenStore dbPool *db.Pool // V7: für db.Close() im Shutdown logger *log.Logger } @@ -62,6 +63,7 @@ func New() (*App, error) { playlists := store.NewPlaylistStore(pool.Pool) authStore := store.NewAuthStore(pool.Pool) schedules := store.NewScreenScheduleStore(pool.Pool) + globalOverrides := store.NewGlobalOverrideStore(pool.Pool) // Ensure admin user exists — generate a random password if none is configured. adminPassword := cfg.AdminPassword @@ -100,8 +102,9 @@ func New() (*App, error) { AuthStore: authStore, Notifier: notifier, ScreenshotStore: ss, - ScheduleStore: schedules, - Config: cfg, + ScheduleStore: schedules, + GlobalOverrideStore: globalOverrides, + Config: cfg, UploadDir: cfg.UploadDir, Logger: logger, }) @@ -111,8 +114,9 @@ func New() (*App, error) { server: &http.Server{Addr: cfg.HTTPAddress, Handler: handler}, notifier: notifier, authStore: authStore, - scheduleStore: schedules, - screenStore: screens, + scheduleStore: schedules, + globalOverrideStore: globalOverrides, + screenStore: screens, dbPool: pool, // V7: Referenz für Shutdown logger: logger, }, nil @@ -145,8 +149,8 @@ func (a *App) Run() error { }() // Display-Zeitplan-Scheduler - go scheduler.Run(ctx, a.scheduleStore, a.screenStore, a.notifier) - go scheduler.Reconcile(ctx, a.scheduleStore, a.screenStore, a.screenStore, a.notifier) + go scheduler.Run(ctx, a.scheduleStore, a.screenStore, a.globalOverrideStore, a.notifier) + go scheduler.Reconcile(ctx, a.scheduleStore, a.screenStore, a.screenStore, a.globalOverrideStore, a.notifier) // W2: Signal-Handler für Graceful Shutdown. sigCh := make(chan os.Signal, 1) diff --git a/server/backend/internal/httpapi/router.go b/server/backend/internal/httpapi/router.go index 753571e..4dac8c3 100644 --- a/server/backend/internal/httpapi/router.go +++ b/server/backend/internal/httpapi/router.go @@ -21,8 +21,9 @@ type RouterDeps struct { AuthStore *store.AuthStore Notifier *mqttnotifier.Notifier ScreenshotStore *ScreenshotStore - ScheduleStore *store.ScreenScheduleStore - Config config.Config + ScheduleStore *store.ScreenScheduleStore + GlobalOverrideStore *store.GlobalOverrideStore + Config config.Config UploadDir string Logger *log.Logger } @@ -192,6 +193,18 @@ func registerManageRoutes(mux *http.ServeMux, d RouterDeps) { mux.Handle("POST /api/v1/screens/{screenSlug}/schedule", authScreen(http.HandlerFunc(manage.HandleUpdateSchedule(d.ScreenStore, d.ScheduleStore)))) + // ── Globaler Override ──────────────────────────────────────────────── + mux.Handle("GET /api/v1/global-override", + authOnly(http.HandlerFunc(manage.HandleGetGlobalOverride(d.GlobalOverrideStore)))) + mux.Handle("POST /api/v1/global-override", + authOnly(http.HandlerFunc(manage.HandleSetGlobalOverride(d.GlobalOverrideStore, d.ScreenStore, notifier)))) + mux.Handle("DELETE /api/v1/global-override", + authOnly(http.HandlerFunc(manage.HandleDeleteGlobalOverride(d.GlobalOverrideStore)))) + + // ── Per-Screen Override ─────────────────────────────────────────────── + mux.Handle("POST /api/v1/screens/{screenSlug}/override", + authScreen(http.HandlerFunc(manage.HandleSetScreenOverride(d.ScreenStore, d.ScheduleStore)))) + // ── JSON API — screens ──────────────────────────────────────────────── // Self-registration: no auth (player calls this on startup). mux.HandleFunc("POST /api/v1/screens/register",