Commit graph

94 commits

Author SHA1 Message Date
Jesko Anschütz
cc9ca2cd81 fix: nil-pointer in DeleteMediaUI, restricted delete-check in tenant handler, SCHEMA fix
- HandleDeleteMediaUI: check err after media.Get before using asset (prevents nil-pointer panic)
- HandleTenantDeleteMedia: add restricted-user ownership check (K3)
- HandleTenantDashboard: filter media list by ownerUserID for restricted users
- SCHEMA.md: correct created_by_user_id to 'text null ... on delete set null'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 09:18:12 +01:00
Jesko Anschütz
8bcb59468a feat(ui): Restricted-Medien Toggle + Besitzer-Badge + Kein-Besitzer-Badge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 09:13:07 +01:00
Jesko Anschütz
bfef6e25f5 feat(tenant): List/Create mit owner-Feld aktualisiert 2026-03-28 09:11:16 +01:00
Jesko Anschütz
7b0b132169 feat(ui): manage-Handler — restricted-aware List/Create/Delete 2026-03-28 09:09:59 +01:00
Jesko Anschütz
865c5e7ca8 feat(manage): canDeleteMedia + role-aware handlers für restricted users
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 09:07:13 +01:00
Jesko Anschütz
b4d0a24320 fix(auth): restricted-User landen nach Login auf eigenen Screens (nicht Tenant-Dashboard)
Login und already-logged-in-Check verwendeten default-Branch für restricted-Rolle,
der zum Tenant-Dashboard mit allen Screens führte. Jetzt wie screen_user behandelt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:59:32 +01:00
Jesko Anschütz
787287b328 fix(restricted): Display-Box ausblenden; Sidebar zeigt nur eigene Screens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:43:51 +01:00
Jesko Anschütz
c943df4663 feat(ui): restricted-User sehen keine Steuerungs-UI (An/Aus, Zeitplan, Override)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:38:37 +01:00
Jesko Anschütz
e35c3cfdbd feat(ui): Admin-Formular: Rolle-Dropdown + Badge in User-Liste
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:35:52 +01:00
Jesko Anschütz
03ea3edb8b feat(handler): HandleCreateScreenUser liest role; UserRole ans Template übergeben
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:34:21 +01:00
Jesko Anschütz
f1dcb4f1d3 feat(router): Steuerungs-Endpunkte blocken restricted-User (403)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:32:40 +01:00
Jesko Anschütz
700567071b feat(auth): RequireNotRestricted middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 21:29:26 +01:00
Jesko Anschütz
958090cb00 feat(admin): Link zu Monitor-Steuerung im Admin-Navbar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:55:50 +01:00
Jesko Anschütz
bb30a75f5a fix(ui): Admin sieht /manage mit allen Screens statt Redirect 2026-03-27 20:53:23 +01:00
Jesko Anschütz
2bf82eed53 fix: Upsert löscht override_on_until nicht mehr; README + Auth-Kommentar
- ScreenScheduleStore.Upsert: override_on_until aus INSERT und ON CONFLICT
  entfernt — verhindert stillen Datenverlust beim Speichern eines Zeitplans.
  SetOverrideOnUntil bleibt alleinig zuständig für diese Spalte.
- README.md: GlobalOverrideStore, vier neue API-Routen, Wochenend-Sperre
  und Migration 006_override.sql dokumentiert.
- override.go: Auth-Scope-Kommentar über HandleSetGlobalOverride ergänzt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:30:52 +01:00
Jesko Anschütz
fc94f56162 feat(ui): per-Screen-Override in Übersichtskarte und Detailseite
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:24:21 +01:00
Jesko Anschütz
c263d97cca feat(ui): Übersichtsseite – globaler Override-Banner
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:21:06 +01:00
Jesko Anschütz
9aabf18aa2 feat(wiring): GlobalOverrideStore in Router, App und Scheduler-Goroutinen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:19:03 +01:00
Jesko Anschütz
42458e68ff feat(manage): Handler für globalen + per-Screen-Override
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:17:20 +01:00
Jesko Anschütz
88e10d1e67 fix(ui): saveSchedule nutzt SCREEN_SLUG statt printf %q 2026-03-27 17:57:31 +01:00
Jesko Anschütz
e7776720c8 fix(ui): sendDisplayCmd nutzt SCREEN_SLUG statt printf %q (URL-Escaping-Bug) 2026-03-27 17:56:46 +01:00
Jesko Anschütz
588045ac04 feat(ui): Zeitplan-Formular in Playlist-Verwaltung 2026-03-27 07:23:38 +01:00
Jesko Anschütz
6cabaeca58 feat(manage): Schedule in ManageUI-Template-Daten 2026-03-27 07:23:07 +01:00
Jesko Anschütz
fc5587c171 fix: Zeitformat-Validierung + pgx.ErrNoRows in ScreenScheduleStore.Get
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 07:21:01 +01:00
Jesko Anschütz
83af005fad feat(api): POST /api/v1/screens/{slug}/schedule + Scheduler verdrahtet
ScheduleStore in RouterDeps, HandleUpdateSchedule-Handler, Scheduler-Goroutine
in app.Run(), ScreenStore.GetByID hinzugefügt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 07:17:45 +01:00
Jesko Anschütz
bdd99d10bd feat(ui): Display-Buttons und Sammelschalter in Screen-Übersicht
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 07:10:40 +01:00
Jesko Anschütz
68fc0bf4cf feat(ui): Display-Steuerbox in Playlist-Verwaltung
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 07:10:23 +01:00
Jesko Anschütz
2a312cd61a feat(manage): DisplayState je Screen in ScreenOverview 2026-03-27 07:05:06 +01:00
Jesko Anschütz
c4f15d862c feat(manage): DisplayState in ManageUI-Template-Daten 2026-03-27 07:04:54 +01:00
Jesko Anschütz
79fcc20b79 fix(display): screen UUID lookup, authScreen middleware, JSON encoding
- playerstatus: look up screen by slug before UpsertDisplayState to pass UUID (not slug) and avoid FK violation
- router: switch display command route from authOnly to authScreen for proper permission enforcement
- display.go: remove redundant GetBySlug + requireScreenAccess (now handled by authScreen middleware), drop store dependency
- notifier: replace fmt.Sprintf %q with json.Marshal for correct JSON encoding of display command payload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 23:35:05 +01:00
Jesko Anschütz
f985a99ea1 feat(api): display_state im Player-Status-Report persistieren 2026-03-26 23:05:25 +01:00
Jesko Anschütz
fbcda1e2b8 feat(api): POST /api/v1/screens/{slug}/display 2026-03-26 23:05:22 +01:00
Jesko Anschütz
052cf199ae fix(manage): HandleReorder gibt 400 bei Mismatch zurück, slog für 500-Fehler 2026-03-26 22:29:48 +01:00
Jesko Anschütz
4fab5fe28a fix(manage): HandleReorderUI gibt 400 bei Mismatch zurück 2026-03-26 22:27:07 +01:00
Jesko Anschütz
8025946ab7 fix: orientationLabel in Tenant-Template registrieren + mosquitto-Abhängigkeit entfernen
- Template-Funktion `orientationLabel` in tenant/tenant.go ergänzt (fehlte nach UI-Refactoring)
- `depends_on: mosquitto` aus compose/server-stack.yml entfernt (Service ist auskommentiert)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 09:47:11 +01:00
Alwin
e077473bf0 feat(ui): Tenant-Dashboard neu gestaltet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 08:30:07 +00:00
Alwin
8bf142b5b1 feat(ui): Screen-Übersicht neu gestaltet 2026-03-25 08:27:18 +00:00
Alwin
0aedf61569 feat(ui): Playlist-Editor neu gestaltet (Karten, Inline-Edit, Zwei-Spalten)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 08:23:38 +00:00
Alwin
a691186d9a feat(ui): Admin-Dashboard neu gestaltet (Karten-Grid, Tabs, Modals)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 07:54:42 +00:00
Alwin
41e12d1235 feat(ui): Provision-Wizard neu gestaltet 2026-03-25 07:44:48 +00:00
Alwin
10a495c13c feat(ui): Login-Seite neu gestaltet 2026-03-25 07:40:28 +00:00
Alwin
e1506d5d2c fix(manage): HandleUpdateItemUI returns 204 for fetch callers 2026-03-25 07:32:18 +00:00
Jesko Anschütz
6084712800 feat(mqtt): MQTT-Config per Heartbeat-Response vom Server an Agents übertragen
Server gibt bei POST /api/v1/player/status jetzt mqtt-Block zurück (broker,
username, password) wenn MORZ_INFOBOARD_MQTT_BROKER gesetzt ist. Agents
parsen die Response und verbinden sich bei Config-Änderung automatisch neu
(applyMQTTConfig mit Reconnect-Logik, thread-safe via Mutex).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 15:03:15 +01:00
Jesko Anschütz
b73da77835 feat(screens): Screen-Übersicht mit On-Demand-Screenshots für Multi-Screen-User
- GET /manage: neue Übersichtsseite mit Bulma-Karten für screen_user mit ≥2 Screens
- handleScreenUserRedirect leitet bei ≥2 Screens auf /manage statt auf ersten Screen
- On-Demand-Screenshot-Flow via MQTT:
  - Backend publiziert signage/screen/{slug}/screenshot-request beim Seitenaufruf
  - Player-Agent empfängt Topic, ruft TakeAndSendOnce() auf
  - Player POST /api/v1/player/screenshot → Backend speichert in ScreenshotStore (RAM)
  - GET /api/v1/screens/{screenId}/screenshot liefert gespeichertes Bild (authOnly)
- ScreenshotStore: In-Memory, thread-safe, kein Persistenz-Overhead
- JS-Retry nach 4s in Templates (Screenshot braucht 1-3s für MQTT-Roundtrip)
- manageTmpl zeigt Screenshot-Thumbnail beim Einzelscreen-Aufruf
- Doku: neue Endpoints, MQTT-Topics, Screenshot-Flow in SERVER-KONZEPT.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 14:27:10 +01:00
Jesko Anschütz
47f65da228 fix(csrf): CSRF-Token für User-Logout in Manage- und Tenant-Dashboard
- HandleManageUI übergibt CSRFToken korrekt ans Template (leeres Hidden-Field
  blockierte JS-Inject-Snippet)
- HandleTenantDashboard setzt CSRF-Cookie und befüllt CSRFToken in Template-Daten
- tenant/csrf_helpers.go: setCSRFCookie im tenant-Package (Import-Cycle-Isolation)
- Logout-Formular in tenantDashTmpl hat jetzt statisches CSRF-Hidden-Field
- Doku: POST /logout und POST /login mit CSRF-Anforderungen dokumentiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 14:26:52 +01:00
Jesko Anschütz
bb35594211 fix(backend): Screen-ID mit doppelten Quotes in User-Zuordnung
printf "%q" im Go-Template erzeugte Go-quoted Strings ("..."), die als
Teil der screen_id an die DB übergeben wurden. FK-Constraint schlug fehl,
weil die ID mit eingebetteten Quotes keiner screens-Zeile entsprach.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 00:02:42 +01:00
Jesko Anschütz
c470ec532b fix(backend): Error-Logging in Screen-User-Handlern + Tenant-Lookup-Refactoring
Fehlende slog.Error-Aufrufe in HandleAddUserToScreen, HandleCreateScreenUser,
HandleDeleteScreenUser und HandleRemoveUserFromScreen ergänzt — DB-Fehler
wurden bisher komplett geschluckt und waren nicht diagnostizierbar.

Tenant-Lookup in EnsureAdminUser und CreateScreenUser aus SQL-Subqueries
in eigene Queries extrahiert für bessere Fehlermeldungen bei fehlendem Tenant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 23:41:16 +01:00
Jesko Anschütz
73c3d74098 fix(csrf): CSRF-Token in Login-Fehlerseite fehlt — macht Retry-Versuch unmöglich
HandleLoginPost renderte Fehlerseiten (falsches Passwort, leere Felder) ohne
CSRFToken in den Template-Daten. Das hidden field <csrf_token> war leer, sodass
jeder weitere Submit-Versuch mit "Ungültiger CSRF-Token" scheiterte.

Fix: setCSRFCookie am Anfang des Handlers aufrufen und das Token in allen
renderError-Pfaden an das Template übergeben.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 22:22:58 +01:00
Jesko Anschütz
d1d86126c8 Feature: Screen-User-Verwaltung mit rollenbasiertem Zugriff
Neue Rolle screen_user: User können sich einloggen und nur ihre
zugeordneten Bildschirme verwalten. Admins behalten vollen Zugriff.

- Migration 003: users.role-Spalte + user_screen_permissions (M:N)
- Store: CreateScreenUser, ListScreenUsers, DeleteUser,
         GetAccessibleScreens, HasUserScreenAccess,
         AddUserToScreen, RemoveUserFromScreen, GetScreenUsers
- Middleware: RequireScreenAccess enforces screen-level access
  für alle /manage/{screenSlug}-Routen
- 4 neue Admin-Handler: CreateScreenUser, DeleteScreenUser,
  AddUserToScreen, RemoveUserFromScreen (+4 Routes)
- Admin-UI: Tab "Benutzer" (anlegen/löschen) + Screen-User-Modal
  (User zuordnen/entfernen) direkt in der Bildschirm-Tabelle
- Login: screen_user wird nach Login zum ersten zugänglichen Screen
  weitergeleitet; kein Zugang zu /admin

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-23 22:06:05 +01:00
Jesko Anschütz
1e90bbbbc0 fix(auth): redirect tenant users to /tenant/{slug}/dashboard after login
Admin users continue to redirect to /manage/ as before. Tenant users
now land on their own dashboard at /tenant/{slug}/dashboard instead of
the incorrect /manage/{slug} path. The fix applies to both the
already-logged-in check in HandleLoginUI and the post-login switch in
HandleLoginPost.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-23 21:32:12 +01:00