// Package upload implementiert DOC-01: fortsetzbare Server-seitige // Dateiaufnahme mit Größen-/MIME-Validierung und transaktionaler // Dokument+Revision-Anlage. Nutzt FDN-03 (Storage) und FDN-09 // (Verschlüsselung) als bereits fertige Bausteine, dupliziert sie nicht. package upload import ( "errors" "fmt" ) // ErrFileTooLarge wird geliefert, wenn die angekündigte oder tatsächliche // Größe das konfigurierte Limit überschreitet (Schutz vor // Speicherbomben — siehe "Bekannte Fehler vermeiden" im Ticket). var ErrFileTooLarge = errors.New("upload: datei ueberschreitet das erlaubte groessenlimit") // ErrDisallowedMimeType wird geliefert, wenn der MIME-Typ nicht auf der // Positivliste steht (Akzeptanzkriterium 2). var ErrDisallowedMimeType = errors.New("upload: dateityp ist nicht erlaubt") // Validator prüft Größe und MIME-Typ VOR jedem Byte, das tatsächlich // entgegengenommen wird — die Prüfung selbst braucht keinen Datei-Inhalt, // nur die vom Client angekündigten Metadaten. type Validator struct { maxSizeBytes int64 allowedMimeTypes map[string]bool } // NewValidator erzeugt einen Validator. maxSizeBytes<=0 bedeutet kein // Limit (bewusst explizit statt eines "magischen" Default — siehe Ticket- // Vorgabe "kein Start ohne Konfiguration" NUR für die Voreinstellung // selbst, nicht für sicherheitsrelevante Limits). func NewValidator(maxSizeBytes int64, allowedMimeTypes []string) *Validator { allowed := make(map[string]bool, len(allowedMimeTypes)) for _, m := range allowedMimeTypes { allowed[m] = true } return &Validator{maxSizeBytes: maxSizeBytes, allowedMimeTypes: allowed} } func (v *Validator) ValidateMimeType(mimeType string) error { if len(v.allowedMimeTypes) == 0 { return nil } if !v.allowedMimeTypes[mimeType] { return fmt.Errorf("%w: %q", ErrDisallowedMimeType, mimeType) } return nil } func (v *Validator) ValidateSize(sizeBytes int64) error { if v.maxSizeBytes <= 0 { return nil } if sizeBytes > v.maxSizeBytes { return fmt.Errorf("%w: %d bytes > limit %d bytes", ErrFileTooLarge, sizeBytes, v.maxSizeBytes) } return nil }