From 097cd58c0c57ac18f0d8f140150390bb2f76306e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Tue, 24 Mar 2026 00:10:50 +0100 Subject: [PATCH] docs: Dokumentation validiert und korrigiert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SCHEMA.md: screen_id in user_screen_permissions von uuid auf text korrigiert - SCHEMA.md: Phasen-Hinweis zur screens-Tabelle hinzugefügt (6 Spalten aktuell implementiert, erweiterte Phase 2-3) - SERVER-KONZEPT.md: RequireScreenAccess-Middleware dokumentiert inkl. Route-Gruppen und Verhaltens-Details - server/backend/README.md: Env-Variable DATABASE_URL → MORZ_INFOBOARD_DATABASE_URL korrigiert - DEVELOPMENT.md: Compose-Stack von "später" auf "existiert bereits" aktualisiert - API-ENDPOINTS.md: HandlePlayerPlaylist Response um fehlende Felder ergänzt (playlist_id, media_asset_id, order_index, created_at) - DEVELOPMENT.md: Architekturentscheidungen präzisiert (message_wall=implementiert, Kampagnen=geplant) Co-Authored-By: Klaus --- DEVELOPMENT.md | 6 ++--- docs/API-ENDPOINTS.md | 12 +++++++-- docs/SCHEMA.md | 4 ++- docs/SERVER-KONZEPT.md | 58 +++++++++++++++++++++++++++++++++------- server/backend/README.md | 2 +- 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index a69e8b9..cb8a485 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -26,7 +26,7 @@ Projektwurzel: - `server/backend/` fuer das zentrale Go-Backend - `player/agent/` fuer den Go-basierten Player-Agent - `ansible/` fuer Deployment und Provisionierung -- `compose/` spaeter fuer den zentralen Server-Stack +- `compose/` fuer den zentralen Server-Stack ## Aktueller Entwicklungsstand @@ -287,8 +287,8 @@ Das Playbook erledigt: ## Aktuelle Architekturentscheidungen mit direkter Auswirkung auf Entwicklung -- `message_wall` wird serverseitig in konkrete Screen-Szenen aufgeloest -- Kampagnengruppen werden serverseitig in konkrete Screen-Assignments expandiert +- `message_wall` wird serverseitig in konkrete Screen-Szenen aufgeloest (implementiert) +- Kampagnengruppen werden serverseitig in konkrete Screen-Assignments expandiert (geplant) - `playlist_items` haben im finalen Implementierungsschema keinen direkten `screen_id`-Fremdschluessel - Provisionierung wird worker-/jumphost-faehig geplant - API-Fehler sollen einen einheitlichen Fehlerumschlag nutzen diff --git a/docs/API-ENDPOINTS.md b/docs/API-ENDPOINTS.md index fcfeba4..dce74ab 100644 --- a/docs/API-ENDPOINTS.md +++ b/docs/API-ENDPOINTS.md @@ -204,23 +204,31 @@ Der Player ruft diesen Endpoint auf, um die aktuellen Inhalte zu laden. "items": [ { "id": "uuid...", + "playlist_id": "uuid...", + "media_asset_id": null, + "order_index": 0, "type": "web", "src": "http://example.com/page1", "title": "Startseite", "duration_seconds": 30, "enabled": true, "valid_from": null, - "valid_until": null + "valid_until": null, + "created_at": "2026-03-22T16:00:00Z" }, { "id": "uuid...", + "playlist_id": "uuid...", + "media_asset_id": "uuid...", + "order_index": 1, "type": "image", "src": "/uploads/banner.jpg", "title": "Werbebanner", "duration_seconds": 20, "enabled": true, "valid_from": null, - "valid_until": null + "valid_until": null, + "created_at": "2026-03-22T16:00:00Z" } ] } diff --git a/docs/SCHEMA.md b/docs/SCHEMA.md index f646213..17aaf99 100644 --- a/docs/SCHEMA.md +++ b/docs/SCHEMA.md @@ -76,7 +76,7 @@ Spalten: ```sql id uuid primary key user_id text not null references users(id) on delete cascade -screen_id uuid not null references screens(id) on delete cascade +screen_id text not null references screens(id) on delete cascade created_at timestamptz not null default now() unique(user_id, screen_id) ``` @@ -139,6 +139,8 @@ Zweck: - physische Displays bzw. Player-Geraete +**Hinweis:** Die Spalten unten beschreiben das geplante Schema (Phase 2-3). Der aktuelle Code (Migration `001_core.sql`) implementiert nur eine Teilmenge: `id`, `tenant_id`, `slug`, `name`, `orientation`, `created_at` (6 Spalten). Weitere Felder werden in späteren Phasen hinzugefügt. + Spalten: ```sql diff --git a/docs/SERVER-KONZEPT.md b/docs/SERVER-KONZEPT.md index 415252e..c459a45 100644 --- a/docs/SERVER-KONZEPT.md +++ b/docs/SERVER-KONZEPT.md @@ -291,24 +291,64 @@ Eingehende Anfrage ├─► RequireAdmin Prueft user.Role == "admin" │ → Fehler: 403 Forbidden │ - └─► RequireTenant Prueft user.TenantSlug == {tenantSlug} aus dem URL-Pfad. - Access Admins duerfen immer durch. - → Fehler: 403 Forbidden + ├─► RequireTenant Prueft user.TenantSlug == {tenantSlug} aus dem URL-Pfad. + │ Access Admins duerfen immer durch. + │ → Fehler: 403 Forbidden + │ + └─► RequireScreen Enforces per-screen access control. + Access Admins duerfen auf alle Screens zugreifen. + Screen-User brauchen expliziten Eintrag in `user_screen_permissions`. + Tenant-User duerfen auf alle Screens ihres Tenants zugreifen. + → Fehler: 404 Not Found (Screen) oder 403 Forbidden (kein Zugriff) ``` ### Route-Gruppen im Router -| Gruppe | Middleware | Beispielrouten | -|----------------|------------------------------------|---------------------------------------------| -| Oeffentlich | keine | `/healthz`, `/login`, `/api/v1/screens/register` | -| Auth-only | RequireAuth | `/manage/{screenSlug}/...` | -| Admin-only | RequireAuth + RequireAdmin | `/admin`, `/admin/screens/...` | -| Tenant-scoped | RequireAuth + RequireTenantAccess | `/tenant/{tenantSlug}/...`, `/api/v1/tenants/{tenantSlug}/...` | +| Gruppe | Middleware | Beispielrouten | +|----------------|----------------------------------------------------|---------------------------------------------| +| Oeffentlich | keine | `/healthz`, `/login`, `/api/v1/screens/register` | +| Auth-only | RequireAuth | `/api/v1/items/{itemId}`, `/api/v1/media/{id}` | +| Admin-only | RequireAuth + RequireAdmin | `/admin`, `/admin/screens/...` | +| Tenant-scoped | RequireAuth + RequireTenantAccess | `/tenant/{tenantSlug}/...`, `/api/v1/tenants/{tenantSlug}/...` | +| Screen-scoped | RequireAuth + RequireScreenAccess | `/manage/{screenSlug}/...`, `/api/v1/screens/{screenId}/playlist` | Der Hilfsfunktion `chain(middlewares...)` in `router.go` wrappet Handler von aussen nach innen. --- +## RequireScreenAccess Middleware + +Die Middleware `RequireScreenAccess` erzwingt Zugriffskontrolle auf Screen-Ressourcen und wird ausschliesslich fuer Routen verwendet, deren Handler screen-spezifische Operationen durchfuehren. + +**Verhalten:** + +- **Admin-User**: duerfen auf alle Screens zugreifen (Bypass). +- **Screen-User**: duerfen nur auf Screens zugreifen, fuer die sie einen expliziten Eintrag in `user_screen_permissions` haben. +- **Tenant-User**: duerfen auf alle Screens ihres Tenants zugreifen (noch nicht vollstaendig implementiert). + +**Implementierung:** + +Die Middleware extrahiert den `screenSlug` aus dem URL-Pfad-Parameter, schlaegt den Screen in der Datenbank auf und prueft via `ScreenStore.HasUserScreenAccess()`, ob der Nutzer Zugriff hat. Admins umgehen diese Pruefung. + +**Fehlerbehandlung:** + +- Screen nicht gefunden: `404 Not Found` +- Kein Zugriff auf Screen: `403 Forbidden` + +**Verwendung in Router:** + +Die `authScreen`-Middleware-Kombination wird fuer folgende Routes verwendet: + +- `GET /manage/{screenSlug}` — Playlist-Management-UI +- `POST /manage/{screenSlug}/upload` — Medium hochladen +- `POST /manage/{screenSlug}/items` — Item 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 + +--- + ## Tenant-Dashboard Das Tenant-Self-Service-Dashboard ist unter `/tenant/{tenantSlug}/dashboard` erreichbar. diff --git a/server/backend/README.md b/server/backend/README.md index 69e5a97..71f3927 100644 --- a/server/backend/README.md +++ b/server/backend/README.md @@ -132,7 +132,7 @@ Alle Werte per Umgebungsvariable: | Variable | Bedeutung | Standard | |-----------------------------------|----------------------------------------------------------|---------------| | `MORZ_INFOBOARD_HTTP_ADDR` | HTTP-Listen-Adresse | `:8080` | -| `DATABASE_URL` | PostgreSQL-Connection-String | — | +| `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 |