### Security-Fixes (K1–K6, W1–W4, W7, N1, N5–N6, V1, V5–V7)
- K1: CSRF-Schutz via Double-Submit-Cookie (httpapi/csrf.go + csrf_helpers.go)
- K2: requireScreenAccess() in allen manage-Handlern (Tenant-Isolation)
- K3: Tenant-Check bei DELETE /api/v1/media/{id}
- K4: requirePlaylistAccess() + GetByItemID() für JSON-API Playlist-Routen
- K5: Admin-Passwort nur noch als [gesetzt] geloggt
- K6: POST /api/v1/screens/register mit Pre-Shared-Secret (MORZ_INFOBOARD_REGISTER_SECRET)
- W1: Race Condition bei order_index behoben (atomare Subquery in AddItem)
- W2: Graceful Shutdown mit 15s Timeout auf SIGTERM/SIGINT
- W3: http.MaxBytesReader (512 MB) in allen Upload-Handlern
- W4: err.Error() nicht mehr an den Client
- W7: Template-Execution via bytes.Buffer (kein partial write bei Fehler)
- N1: Rate-Limiting auf /login (5 Versuche/Minute pro IP, httpapi/ratelimit.go)
- N5: Directory-Listing auf /uploads/ deaktiviert (neuteredFileSystem)
- N6: Uploads nach Tenant getrennt (uploads/{tenantSlug}/)
- V1: Upload-Logik konsolidiert in internal/fileutil/fileutil.go
- V5: Cookie-Name als Konstante reqcontext.SessionCookieName
- V6: Strukturiertes Logging mit log/slog + JSON-Handler
- V7: DB-Pool wird im Graceful-Shutdown geschlossen
### Phase 6: Screenshot-Erzeugung
- player/agent/internal/screenshot/screenshot.go erstellt
- Integration in app.go mit MORZ_INFOBOARD_SCREENSHOT_EVERY Config
### UX: PDF.js Integration
- pdf.min.js + pdf.worker.min.js als lokale Assets eingebettet
- Automatisches Seitendurchblättern im Player
### Ansible: Neue Rollen
- signage_base, signage_server, signage_provision erstellt
- inventory.yml und site.yml erweitert
### Konzept-Docs
- GRUPPEN-KONZEPT.md, KAMPAGNEN-AKTIVIERUNG.md, MONITORING-KONZEPT.md
- PROVISION-KONZEPT.md, TEMPLATE-EDITOR.md, WATCHDOG-KONZEPT.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| cmd/api | ||
| internal | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
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 Backendsinternal/app/— App-Initialisierung und Lifecycleinternal/config/— Konfiguration via Umgebungsvariableninternal/db/— PostgreSQL-Anbindung und Migrations-Runnerinternal/store/— Datenbankzugriff (TenantStore, ScreenStore, MediaStore, PlaylistStore, AuthStore)internal/fileutil/— Upload-Hilfsfunktionen (SaveUploadedFile mit Tenant-Isolation)internal/httpapi/— HTTP-Routing, Middleware und Handlerinternal/httpapi/csrf.go— Double-Submit-Cookie CSRF-Schutzinternal/httpapi/ratelimit.go— Rate-Limiting fuer /login (Brute-Force-Schutz)internal/httpapi/uploads.go— Upload-Handler konsolidiertinternal/httpapi/manage/— Admin-UI und Playlist-Management-UIinternal/httpapi/manage/csrf_helpers.go— CSRF-Token Helpers fuer Templatesinternal/httpapi/tenant/— Tenant-Self-Service-Dashboardinternal/mqttnotifier/— MQTT-Notifizierungeninternal/reqcontext/— Context-Keys fuer authentifizierten User
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 |
| 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/{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) |
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 |
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 |
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.