From 8e0501a0122f85cbbff8e0a36f906eb2d187d55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Mon, 23 Mar 2026 22:07:32 +0100 Subject: [PATCH] Doku: Screen-Usserverwaltung (Phase 8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aktualisiert Dokumentation für Screen-User Management nach Backy's Implementierung: docs/SCHEMA.md: - users.role erweitert: 'admin' | 'screen_user' | 'tenant' - Neue Tabelle: user_screen_permissions (user_id, screen_id, created_at, unique constraint, FK mit CASCADE) - AuthStore: CreateScreenUser, ListScreenUsers, DeleteUser - ScreenStore: GetAccessibleScreens, HasUserScreenAccess, AddUserToScreen, RemoveUserFromScreen, GetScreenUsers docs/API-ENDPOINTS.md: - POST /admin/users — Screen-User anlegen - POST /admin/users/{userID}/delete — Screen-User löschen - POST /admin/screens/{screenID}/users — User zu Screen hinzufügen - POST /admin/screens/{screenID}/users/{userID}/remove — User von Screen entfernen server/backend/README.md: - AuthStore und ScreenStore Methoden dokumentiert - Middleware RequireScreenAccess erklärt - Migration 003_user_screen_permissions.sql erwähnt DEVELOPMENT.md: - users.role Werte dokumentiert (admin, screen_user, tenant) Co-Authored-By: Backy (Screen-User Implementation) --- DEVELOPMENT.md | 5 +++ docs/API-ENDPOINTS.md | 88 ++++++++++++++++++++++++++++++++++++++++ docs/SCHEMA.md | 38 ++++++++++++++++- server/backend/README.md | 66 +++++++++++++++++++++++++++--- 4 files changed, 190 insertions(+), 7 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index e3ebf6f..a69e8b9 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -164,6 +164,11 @@ Konfigurierbar ueber: - `MORZ_INFOBOARD_REGISTER_SECRET` – Pre-Shared-Secret fuer POST /api/v1/screens/register; leer = offen fuer alle - `MORZ_INFOBOARD_DEV_MODE` – wenn `true`: Session-Cookie wird ohne `Secure`-Flag gesetzt (nur fuer lokale Entwicklung) +**Hinweis zu `users.role`:** +- `admin` — hat Zugriff auf alle Admin-Funktionen und Screens +- `screen_user` — hat Zugriff nur auf Screens, fuer die explizit ein Eintrag in `user_screen_permissions` existiert +- `tenant` — hat Zugriff auf alle Screens seines Tenants (veraltet, noch nicht vollstaendig implementiert) + Beispiele: ```bash diff --git a/docs/API-ENDPOINTS.md b/docs/API-ENDPOINTS.md index 4c7a078..fcfeba4 100644 --- a/docs/API-ENDPOINTS.md +++ b/docs/API-ENDPOINTS.md @@ -694,6 +694,89 @@ Rückleitung zur Admin-Seite. --- +## Screen-User Management (Admin) + +### POST /admin/users + +Erstellt einen neuen Screen-User für einen Tenant (Admin-Formular). + +**Request-Body (Form-Encoded):** +``` +username=screenuser1&password=geheim +``` + +**Verhalten:** +- Neuer User mit `role = 'screen_user'` wird angelegt +- Passwort wird per bcrypt gehasht +- User wird dem aktuellen Tenant zugeordnet + +**Status:** +- `200 OK` oder `201 Created` — Screen-User erstellt +- `400 Bad Request` — Fehlende oder ungültige Parameter, Username bereits vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite. + +--- + +### POST /admin/users/{userID}/delete + +Löscht einen Screen-User und alle zugeordneten Screen-Permissions. + +**Verhalten:** +- User mit Rolle `screen_user` wird gelöscht +- Alle Einträge in `user_screen_permissions` für diesen User werden gelöscht + +**Status:** +- `200 OK` — Screen-User gelöscht +- `404 Not Found` — User nicht vorhanden oder falscher Typ +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite. + +--- + +### POST /admin/screens/{screenID}/users + +Fügt einen Screen-User zu einem Screen hinzu. + +**Request-Body (Form-Encoded):** +``` +user_id= +``` + +**Verhalten:** +- Eintrag in `user_screen_permissions` wird erstellt +- User muss vom Typ `screen_user` sein +- Unique-Constraint verhindert Duplikate + +**Status:** +- `200 OK` — User zu Screen hinzugefügt +- `400 Bad Request` — Fehlende Parameter, User bereits hinzugefügt +- `404 Not Found` — Screen oder User nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite oder zum Screen-Detail. + +--- + +### POST /admin/screens/{screenID}/users/{userID}/remove + +Entfernt einen Screen-User von einem Screen. + +**Verhalten:** +- Eintrag in `user_screen_permissions` wird gelöscht +- User behält seine Existenz; nur die Permission wird entfernt + +**Status:** +- `200 OK` — User von Screen entfernt +- `404 Not Found` — Screen, User oder Permission nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite oder zum Screen-Detail. + +--- + ## Playlist Management UI (Web-Formulare) ### GET /manage/{screenSlug} @@ -954,6 +1037,11 @@ Die folgenden Endpoints sind derzeit vorbereitet, aber noch nicht vollständig i ## Änderungshistorie +- **2026-03-23 (Update):** Screen-User Management Endpoints (Doris / Doku-Review) + - `POST /admin/users` — Screen-User anlegen + - `POST /admin/users/{userID}/delete` — Screen-User löschen + - `POST /admin/screens/{screenID}/users` — User zu Screen hinzufügen + - `POST /admin/screens/{screenID}/users/{userID}/remove` — User von Screen entfernen - **2026-03-23 (Update):** Security-Enhancements und Upload-Konsolidierung (Doris / Doku-Review) - CSRF-Schutz (Double-Submit-Cookie) in `internal/httpapi/csrf.go` - Rate-Limiting für `/login` in `internal/httpapi/ratelimit.go` diff --git a/docs/SCHEMA.md b/docs/SCHEMA.md index b2c1014..f646213 100644 --- a/docs/SCHEMA.md +++ b/docs/SCHEMA.md @@ -59,12 +59,34 @@ unique(tenant_id, username) Regeln: -- `role` in v1: `admin`, `tenant` +- `role` in v1: `admin`, `screen_user`, `tenant` - `username` ist nur innerhalb eines Tenants eindeutig (Unique-Constraint auf `(tenant_id, username)`) - `tenant_id` ist `NOT NULL` — jeder User gehoert genau einem Tenant - IDs sind `text`, nicht `uuid`, enthalten aber UUID-Werte (via `gen_random_uuid()::text`) - Felder wie `email`, `active`, `last_login_at` und `updated_at` existieren in v1 nicht +### `user_screen_permissions` + +Zweck: + +- Zuordnung von Screen-Usern zu Screens (rollenbasierter Zugriff) + +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 +created_at timestamptz not null default now() +unique(user_id, screen_id) +``` + +Regeln: + +- `user_id` muss ein User mit `role = 'screen_user'` sein +- `screen_id` muss existieren; Loeschen des Screens loescht auch die Permission +- Loeschen des Users loescht auch alle seine Permissions + ### `sessions` Zweck: @@ -529,6 +551,9 @@ last_error_message text null Die Auth-Tabellen werden durch `server/backend/internal/db/migrations/002_auth.sql` angelegt und sind vollstaendig unter den Abschnitten `users` und `sessions` oben beschrieben. +Die Screen-Usserverwaltung wird durch `server/backend/internal/db/migrations/003_user_screen_permissions.sql` angelegt +und ist unter dem Abschnitt `user_screen_permissions` oben beschrieben. + Der `AuthStore` (`internal/store/auth.go`) stellt folgende Methoden bereit: - `GetUserByUsername(ctx, username)` — Nutzer per Username laden (inkl. `TenantSlug` via LEFT JOIN) @@ -538,6 +563,17 @@ Der `AuthStore` (`internal/store/auth.go`) stellt folgende Methoden bereit: - `CleanExpiredSessions(ctx)` — abgelaufene Sessions bereinigen - `EnsureAdminUser(ctx, tenantSlug, password)` — Admin-User beim Start anlegen wenn nicht vorhanden - `VerifyPassword(ctx, userID, password)` — Passwort gegen bcrypt-Hash pruefen +- `CreateScreenUser(ctx, tenantID, username, password)` — neuen Screen-User anlegen +- `ListScreenUsers(ctx, tenantID)` — alle Screen-User eines Tenants auflisten +- `DeleteUser(ctx, userID)` — User und alle zugeordneten Permissions loeschen + +Der `ScreenStore` (`internal/store/screen.go`) stellt folgende Methoden bereit: + +- `GetAccessibleScreens(ctx, userID)` — alle Screens, auf die der User Zugriff hat +- `HasUserScreenAccess(ctx, userID, screenID)` — prueft ob User auf Screen zugreifen darf +- `AddUserToScreen(ctx, userID, screenID)` — User zu Screen hinzufuegen +- `RemoveUserFromScreen(ctx, userID, screenID)` — User von Screen entfernen +- `GetScreenUsers(ctx, screenID)` — alle User, die auf Screen Zugriff haben ## Wichtige Indizes diff --git a/server/backend/README.md b/server/backend/README.md index 732de14..69e5a97 100644 --- a/server/backend/README.md +++ b/server/backend/README.md @@ -29,6 +29,33 @@ Dieses Verzeichnis enthaelt das zentrale Go-Backend fuer das Info-Board-System. - `internal/mqttnotifier/` — MQTT-Notifizierungen - `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) @@ -75,12 +102,16 @@ Dieses Verzeichnis enthaelt das zentrale Go-Backend fuer das Info-Board-System. ### 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 | +| 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`) @@ -113,3 +144,26 @@ Alle Werte per Umgebungsvariable: | `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`)