feat(dokument): Dokumente-Modul (Roadmap Phase 5)
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
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
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
|
||||
Reference in New Issue
Block a user