docs: media_assets.created_by_user_id + Berechtigungslogik dokumentiert

- SCHEMA.md: Index idx_media_assets_created_by_user_id hinzugefügt
- API-ENDPOINTS.md: GET/POST Media-Endpoints erweitert um owner_is_restricted und owner_username
- API-ENDPOINTS.md: DELETE Media-Endpoint mit Berechtigungslogik dokumentiert
  * admin_user: immer erlaubt
  * screen_user: erlaubt wenn asset.tenant_id == user.tenant_id
  * restricted: erlaubt nur wenn asset.created_by_user_id == user.id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jesko Anschütz 2026-03-28 09:14:35 +01:00
parent 8bcb59468a
commit e884acf41d
2 changed files with 21 additions and 4 deletions

View file

@ -428,6 +428,10 @@ default_duration_seconds=25
Listet alle Medien-Assets eines Tenants auf. Listet alle Medien-Assets eines Tenants auf.
**Rolle `restricted`:** Gibt nur Medien zurück, die der eingeloggte User selbst hochgeladen hat (`created_by_user_id = user.id`).
**Alle anderen Rollen (`admin_user`, `screen_user`):** Alle Medien des Tenants. Response-Felder `owner_is_restricted` und `owner_username` sind befüllt, wenn das Medium von einem Restricted-User hochgeladen wurde.
**Response:** **Response:**
```json ```json
[ [
@ -444,7 +448,9 @@ Listet alle Medien-Assets eines Tenants auf.
"size_bytes": 102400, "size_bytes": 102400,
"enabled": true, "enabled": true,
"created_at": "2026-03-22T16:00:00Z", "created_at": "2026-03-22T16:00:00Z",
"updated_at": "2026-03-22T16:00:00Z" "updated_at": "2026-03-22T16:00:00Z",
"owner_is_restricted": false,
"owner_username": "admin"
}, },
{ {
"id": "uuid...", "id": "uuid...",
@ -455,7 +461,9 @@ Listet alle Medien-Assets eines Tenants auf.
"original_url": "http://example.com", "original_url": "http://example.com",
"storage_path": null, "storage_path": null,
"enabled": true, "enabled": true,
"created_at": "2026-03-22T16:00:00Z" "created_at": "2026-03-22T16:00:00Z",
"owner_is_restricted": true,
"owner_username": "teacher01"
} }
] ]
``` ```
@ -471,7 +479,7 @@ Wenn keine Assets vorhanden sind, wird eine leere Liste zurückgegeben.
### POST /api/v1/tenants/{tenantSlug}/media ### POST /api/v1/tenants/{tenantSlug}/media
Registriert ein neues Medien-Asset (Datei-Upload oder externe URL). Registriert ein neues Medien-Asset (Datei-Upload oder externe URL). Setzt `created_by_user_id` auf die ID des eingeloggten Users.
**Request-Typ A: Datei-Upload (Multipart)** **Request-Typ A: Datei-Upload (Multipart)**
``` ```
@ -503,7 +511,9 @@ url: http://example.com
"mime_type": "image/jpeg", "mime_type": "image/jpeg",
"size_bytes": 102400, "size_bytes": 102400,
"enabled": true, "enabled": true,
"created_at": "2026-03-22T16:00:00Z" "created_at": "2026-03-22T16:00:00Z",
"owner_is_restricted": false,
"owner_username": "teacher01"
} }
``` ```
@ -519,8 +529,14 @@ url: http://example.com
Löscht ein Medien-Asset (und physische Datei falls lokal gespeichert). Löscht ein Medien-Asset (und physische Datei falls lokal gespeichert).
**Berechtigungen:**
- **admin_user:** Immer erlaubt
- **screen_user:** Erlaubt, wenn `asset.tenant_id == user.tenant_id`
- **restricted:** Erlaubt nur wenn `asset.created_by_user_id == user.id` (eigenes Medium)
**Status:** **Status:**
- `204 No Content` — Erfolgreich gelöscht - `204 No Content` — Erfolgreich gelöscht
- `403 Forbidden` — User hat nicht die erforderliche Berechtigung
- `404 Not Found` — Asset nicht vorhanden - `404 Not Found` — Asset nicht vorhanden
- `500 Internal Server Error` — DB-Fehler - `500 Internal Server Error` — DB-Fehler

View file

@ -653,6 +653,7 @@ Empfohlen mindestens:
```sql ```sql
create index idx_screens_tenant_id on screens(tenant_id); create index idx_screens_tenant_id on screens(tenant_id);
create index idx_media_assets_tenant_id on media_assets(tenant_id); create index idx_media_assets_tenant_id on media_assets(tenant_id);
create index idx_media_assets_created_by_user_id on media_assets(created_by_user_id);
create index idx_playlists_screen_id on playlists(screen_id); create index idx_playlists_screen_id on playlists(screen_id);
create index idx_playlist_items_playlist_id_order on playlist_items(playlist_id, order_index); create index idx_playlist_items_playlist_id_order on playlist_items(playlist_id, order_index);
create index idx_campaigns_active_validity on campaigns(active, valid_from, valid_until); create index idx_campaigns_active_validity on campaigns(active, valid_from, valid_until);