feat(aether): initial commit – self-hosted Cloud, Phasen 1–7
Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA. Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb, Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming, Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office (Collabora/OnlyOffice). Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort) sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
31a027c93a
225 files changed
+38042
No files matched your search
@@ -0,0 +1,59 @@
|
||||
package webdav
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"aether/internal/files"
|
||||
)
|
||||
|
||||
// Ein abgebrochener Upload darf nichts hinterlassen. x/net/webdav ruft Close
|
||||
// per defer auf – auch nach einem Fehler in io.Copy. Ohne die Sperre in Close
|
||||
// landete der halb gefüllte Puffer als vollständige Datei in Cloud und
|
||||
// Datenbank: der Client meldet einen Fehler, die Datei ist trotzdem da, nur
|
||||
// abgeschnitten – und die Prüfsumme passt zum Torso, fällt also nie auf.
|
||||
//
|
||||
// fileStore und storage sind hier absichtlich nil: greift Close doch darauf
|
||||
// zu, paniert der Test statt still durchzulaufen.
|
||||
func TestWriteFileCloseDiscardsAbortedUpload(t *testing.T) {
|
||||
t.Run("quota exceeded during write", func(t *testing.T) {
|
||||
f := &davWriteFile{
|
||||
ctx: context.Background(), name: "big.bin", expected: -1,
|
||||
written: 31, writeErr: files.ErrQuotaExceeded,
|
||||
}
|
||||
|
||||
if err := f.Close(); !errors.Is(err, files.ErrQuotaExceeded) {
|
||||
t.Fatalf("Close() = %v, want ErrQuotaExceeded", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("connection dropped mid-upload", func(t *testing.T) {
|
||||
f := &davWriteFile{
|
||||
ctx: context.Background(), name: "abort.bin",
|
||||
expected: 4096, written: 14,
|
||||
}
|
||||
|
||||
if err := f.Close(); err == nil {
|
||||
t.Fatal("Close() = nil, want error for incomplete upload")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Chunked Uploads kündigen keine Größe an (Content-Length -1). Dann kann Close
|
||||
// die Vollständigkeit nicht prüfen und darf deshalb nicht blockieren – sonst
|
||||
// wäre jeder chunked Upload kaputt.
|
||||
func TestWriteFileCloseAcceptsUnknownLength(t *testing.T) {
|
||||
f := &davWriteFile{
|
||||
ctx: context.Background(), name: "chunked.bin",
|
||||
expected: -1, written: 12,
|
||||
}
|
||||
|
||||
// Kommt bis zum Store durch – der ist nil, also panic statt Fehler.
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
t.Fatal("Close() should have proceeded to the store, but returned early")
|
||||
}
|
||||
}()
|
||||
_ = f.Close()
|
||||
}
|
||||
Reference in new issue
Block a user