morz-infoboard/server/backend
2026-03-26 23:05:20 +01:00
..
cmd/api Security-Review + Phase 6: CSRF, Rate-Limiting, Tenant-Isolation, Screenshot, Ansible 2026-03-23 21:06:35 +01:00
internal feat(mqtt): SendDisplayCommand mit retained QoS 1 2026-03-26 23:05:20 +01:00
Dockerfile feat(screens): Screen-Übersicht mit On-Demand-Screenshots für Multi-Screen-User 2026-03-24 14:27:10 +01:00
go.mod Tenant-Feature Phase 1+2: Auth-Fundament + Login-Flow + UX-Textverbesserung 2026-03-23 15:46:14 +01:00
go.sum Tenant-Feature Phase 1+2: Auth-Fundament + Login-Flow + UX-Textverbesserung 2026-03-23 15:46:14 +01:00
README.md fix(csrf): CSRF-Token für User-Logout in Manage- und Tenant-Dashboard 2026-03-24 14:26:52 +01:00

Backend

Dieses Verzeichnis enthaelt das zentrale Go-Backend fuer das Info-Board-System.

Aufgaben

  • HTTP-API und serverseitige HTML-UI (Bulma)
  • PostgreSQL-Anbindung mit automatischen Migrationen
  • Session-basierte Authentifizierung und rollenbasierte Zugriffskontrolle
  • Medienverwaltung und Playlist-Management
  • Player-Status-Ingest und Diagnose
  • MQTT-Notifizierungen bei Playlist-Aenderungen

Unterstruktur

  • cmd/api/ — Startpunkt des Backends
  • internal/app/ — App-Initialisierung und Lifecycle
  • internal/config/ — Konfiguration via Umgebungsvariablen
  • internal/db/ — PostgreSQL-Anbindung und Migrations-Runner
  • internal/store/ — Datenbankzugriff (TenantStore, ScreenStore, MediaStore, PlaylistStore, AuthStore)
  • internal/fileutil/ — Upload-Hilfsfunktionen (SaveUploadedFile mit Tenant-Isolation)
  • internal/httpapi/ — HTTP-Routing, Middleware und Handler
  • internal/httpapi/csrf.go — Double-Submit-Cookie CSRF-Schutz
  • internal/httpapi/ratelimit.go — Rate-Limiting fuer /login (Brute-Force-Schutz)
  • internal/httpapi/uploads.go — Upload-Handler konsolidiert
  • internal/httpapi/screenshot.go — Handler fuer Player-Screenshot-Upload und Screenshot-Abruf
  • internal/httpapi/screenshot_store.go — In-Memory-Store fuer Screenshots (ScreenshotStore, thread-safe via sync.RWMutex)
  • internal/httpapi/manage/ — Admin-UI und Playlist-Management-UI
  • internal/httpapi/manage/csrf_helpers.go — CSRF-Token Helpers fuer Templates (manage-Package)
  • internal/httpapi/tenant/ — Tenant-Self-Service-Dashboard
  • internal/httpapi/tenant/csrf_helpers.go — CSRF-Token Helpers fuer Templates (tenant-Package, Import-Cycle-Isolation)
  • internal/mqttnotifier/ — MQTT-Notifizierungen (NotifyChanged, RequestScreenshot)
  • internal/reqcontext/ — Context-Keys fuer authentifizierten User

Datenbank-Stores

AuthStore (internal/store/auth.go)

Screen-User Management:

  • CreateScreenUser(ctx, tenantID, username, passwordHash) — neuen Screen-User anlegen
  • ListScreenUsers(ctx, tenantID) — alle Screen-User eines Tenants auflisten
  • DeleteUser(ctx, userID) — User und alle zugeordneten Permissions loeschen

Authentifizierung:

  • GetUserByUsername(ctx, username) — Nutzer per Username laden
  • CreateSession(ctx, userID, ttl) — neue Session anlegen
  • GetSessionUser(ctx, sessionID) — User zu gueltigem Session-Token laden
  • DeleteSession(ctx, sessionID) — Session loeschen (Logout)
  • CleanExpiredSessions(ctx) — abgelaufene Sessions bereinigen
  • EnsureAdminUser(ctx, tenantSlug, password) — Admin-User beim Start anlegen
  • VerifyPassword(ctx, userID, password) — Passwort gegen bcrypt-Hash pruefen

ScreenStore (internal/store/screen.go)

Screen-User Zugriffskontrolle:

  • GetAccessibleScreens(ctx, userID) — alle Screens, auf die der User Zugriff hat
  • HasUserScreenAccess(ctx, userID, screenID) — prueft ob User auf Screen zugreifen darf (boolean)
  • AddUserToScreen(ctx, userID, screenID) — User zu Screen hinzufuegen (Eintrag in user_screen_permissions)
  • RemoveUserFromScreen(ctx, userID, screenID) — User von Screen entfernen
  • GetScreenUsers(ctx, screenID) — alle User, die auf Screen Zugriff haben

Aktuelle Endpunkte

Oeffentlich (keine Auth)

Methode Pfad Beschreibung
GET /healthz Health-Check
GET /api/v1 API-Entrypoint
GET /api/v1/meta Metainformationen
POST /api/v1/player/status Status-Ingest vom Player-Agent
POST /api/v1/player/screenshot Screenshot-Upload vom Player-Agent
GET /api/v1/screens/status Uebersicht aller Screen-Status
GET /api/v1/screens/{screenId}/status Einzelner Screen-Status
DELETE /api/v1/screens/{screenId}/status Screen-Status loeschen
GET /api/v1/screens/{screenId}/playlist Playlist fuer Player (kein Auth)
POST /api/v1/screens/register Agent-Selbstregistrierung
POST /api/v1/tools/message-wall/resolve Message-Wall-Aufloesungsendpunkt
GET /status HTML-Diagnoseseite
GET /status/{screenId} HTML-Detailseite Einzelscreen
GET /uploads/{filename} Hochgeladene Dateien abrufen
GET /static/bulma.min.css Statisches CSS
GET /static/Sortable.min.js Statisches JS
GET /login Login-Formular
POST /login Login verarbeiten
POST /logout Session beenden

Nur eingeloggte Benutzer (RequireAuth)

Methode Pfad Beschreibung
GET /manage Screen-Uebersicht fuer screen_user
GET /manage/{screenSlug} Playlist-Management-UI
POST /manage/{screenSlug}/upload Medium fuer Screen hochladen
POST /manage/{screenSlug}/items Item zur Playlist hinzufuegen
POST /manage/{screenSlug}/items/{itemId} Item aktualisieren
POST /manage/{screenSlug}/items/{itemId}/delete Item loeschen
POST /manage/{screenSlug}/reorder Items reordnen
POST /manage/{screenSlug}/media/{mediaId}/delete Medium loeschen
GET /api/v1/playlists/{screenId} Playlist mit Metadaten abrufen
POST /api/v1/playlists/{playlistId}/items Item zur Playlist hinzufuegen (API)
PATCH /api/v1/items/{itemId} Item aktualisieren (API)
DELETE /api/v1/items/{itemId} Item loeschen (API)
PUT /api/v1/playlists/{playlistId}/order Items reordnen (API)
PATCH /api/v1/playlists/{playlistId}/duration Standard-Dauer setzen (API)
DELETE /api/v1/media/{id} Medium loeschen (API)
GET /api/v1/screens/{screenId}/screenshot Screenshot eines Screens abrufen

Nur Admins (RequireAuth + RequireAdmin)

Methode Pfad Beschreibung
GET /admin Admin-Uebersicht
POST /admin/screens/provision Provisionierungs-Job starten
POST /admin/screens Neuen Screen anlegen
POST /admin/screens/{screenId}/delete Screen loeschen
POST /admin/users Screen-User anlegen
POST /admin/users/{userID}/delete Screen-User loeschen
POST /admin/screens/{screenID}/users User zu Screen hinzufuegen
POST /admin/screens/{screenID}/users/{userID}/remove User von Screen entfernen

Tenant-scoped (RequireAuth + RequireTenantAccess)

Methode Pfad Beschreibung
GET /tenant/{tenantSlug}/dashboard Tenant-Self-Service-Dashboard
POST /tenant/{tenantSlug}/upload Medium hochladen
POST /tenant/{tenantSlug}/media/{mediaId}/delete Medium loeschen
GET /api/v1/tenants/{tenantSlug}/screens Screens eines Tenants auflisten
POST /api/v1/tenants/{tenantSlug}/screens Screen anlegen
GET /api/v1/tenants/{tenantSlug}/media Medien eines Tenants auflisten
POST /api/v1/tenants/{tenantSlug}/media Medium hochladen (API)

Konfiguration

Alle Werte per Umgebungsvariable:

Variable Bedeutung Standard
MORZ_INFOBOARD_HTTP_ADDR HTTP-Listen-Adresse :8080
MORZ_INFOBOARD_DATABASE_URL PostgreSQL-Connection-String
MORZ_INFOBOARD_UPLOAD_DIR Verzeichnis fuer hochgeladene Medien /tmp/morz-uploads
MORZ_INFOBOARD_STATUS_STORE_PATH Pfad zur JSON-Persistenz-Datei fuer Status-Store leer (in-memory)
MORZ_INFOBOARD_ADMIN_PASSWORD Passwort des initialen Admin-Users (leer = kein Anlegen) leer
MORZ_INFOBOARD_DEFAULT_TENANT Slug des Tenants, dem der Admin zugeordnet wird morz
MORZ_INFOBOARD_DEV_MODE true = Session-Cookie ohne Secure-Flag (nur lokal) false
MORZ_INFOBOARD_REGISTER_SECRET Pre-Shared-Secret fuer POST /api/v1/screens/register leer
MORZ_INFOBOARD_MQTT_BROKER MQTT-Broker-URL (leer = kein MQTT) leer
MORZ_INFOBOARD_MQTT_USERNAME MQTT-Benutzername leer
MORZ_INFOBOARD_MQTT_PASSWORD MQTT-Passwort leer

Detailliertere Beschreibung und lokale Startbeispiele: DEVELOPMENT.md.

Middleware

RequireScreenAccess

Middleware zur rollenbasierten Zugriffskontrolle auf Screen-Ressourcen.

Verhalten:

  • Admins duerfen auf alle Screens zugreifen
  • Screen-User duerfen nur auf Screens zugreifen, fuer die sie in user_screen_permissions eingetragen sind
  • Tenant-User duerfen auf alle Screens ihres Tenants zugreifen
  • Response: 403 Forbidden wenn keine Berechtigung

Verwendung:

  • GET /api/v1/screens/{screenId}/playlist
  • POST /manage/{screenSlug}/...
  • Alle privaten Screen-Endpunkte

Migrationen

  • 001_core.sql — initiales Schema (Tenants, Screens, Playlists, Media, etc.)
  • 002_auth.sql — Auth-Tabellen (users, sessions)
  • 003_user_screen_permissions.sql — Screen-User Management (user_screen_permissions)