docs: Dokumentation validiert und korrigiert
- 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 <noreply@example.com>
This commit is contained in:
parent
bb35594211
commit
097cd58c0c
5 changed files with 66 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue