Doku: Screen-Usserverwaltung (Phase 8)

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) <noreply@anthropic.com>
This commit is contained in:
Jesko Anschütz 2026-03-23 22:07:32 +01:00
parent d1d86126c8
commit 8e0501a012
4 changed files with 190 additions and 7 deletions

View file

@ -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

View file

@ -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=<userID>
```
**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`

View file

@ -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

View file

@ -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)
@ -76,11 +103,15 @@ 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 |
| 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`)