Polymorphe Datei-Anhänge (PDF/JPEG/PNG/WebP, Whitelist statt Blacklist -
owasp-Grundsatz) an beliebige Ressource, gleiches entitaet_typ/entitaet_id-
Muster wie Mangel/Historie. Lokale Ablage (settings.upload_dir, kein Cloud-
Zwang, Self-Hosting-Anforderung), server-generierter Dateiname verhindert
Path-Traversal/Namenskollisionen.
POST /dokumente (multipart), GET /dokumente (Filter Pflicht: entitaet_typ +
entitaet_id), GET /dokumente/{id}/download, DELETE /dokumente/{id}. Hochladen:
alle Mitarbeiter+, Löschen: Materialverantwortliche+Leitung+Admin.
Frontend: wiederverwendbares DokumentePanel (Upload/Liste/Download/Löschen),
eingebunden in ObjektSection (je Objekt) und MangelListePage (Fotos zu
Mängeln) - weitere Ressourcen (Geräteinstanz, Fahrzeugdetails, Benutzer)
können denselben Baustein später einfach wiederverwenden.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
26 lines
726 B
Python
26 lines
726 B
Python
import uuid
|
|
from datetime import datetime
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
# Bewusst geschlossene Liste statt Freitext (Konsistenz mit Mangel.entitaet_typ-
|
|
# Validierung) - jeder Ressourcentyp, an den Dokumente angehängt werden dürfen,
|
|
# muss hier explizit freigeschaltet werden.
|
|
EntitaetTyp = Literal[
|
|
"objekt", "objektposition", "geraet_instanz", "mangel", "fahrzeugdetails", "benutzer"
|
|
]
|
|
|
|
|
|
class DokumentRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
id: uuid.UUID
|
|
entitaet_typ: str
|
|
entitaet_id: str
|
|
dateiname: str
|
|
mime_type: str
|
|
groesse_bytes: int
|
|
beschreibung: str | None
|
|
hochgeladen_von: int
|
|
hochgeladen_am: datetime
|