- helmet, express-rate-limit (login/setup/customer-auth/me-password) - Constant-time login (bcrypt always runs against a dummy hash on miss) - Cookie secure flag follows req.protocol; trust proxy is env-gated to prevent X-Forwarded-For spoofing on direct exposure - Drop SVG from accepted logo types (same-origin XSS) and resolve the served logo path against LOGO_DIR as defense in depth - Self-service /me/password endpoint plus header button; bumps minimum password length to 8 across backend, prompts and edit modal - Multer 1.x → 2.x for current security backports - Customer edit modal replaces stacked prompts; user role is now an inline dropdown with a confirm-and-revert flow - Windows .reg helper plus README section for Basic-Auth-over-HTTP and the http:// vs \\HOST@PORT\DavWWWRoot\ mapping syntax Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| public | ||
| src | ||
| webdav | ||
| windows | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| Dockerfile | ||
| README.md | ||
| docker-compose.yml | ||
| package.json | ||
README.md
Simple File Upload
Kunden laden Dateien/Ordner über einen individuellen Link hoch (ohne Login). Admin + Sachbearbeiter verwalten Kunden im Adminportal und greifen per WebDAV zu.
Start
cp .env.example .env # optional: Ports anpassen
docker compose up -d --build
- Adminportal: http://localhost:3500/
- WebDAV:
webdav://HOST:1900/(Basic Auth, dieselben Benutzer wie im Adminportal)
Beim ersten Start öffnet sich ein Setup-Wizard — dort legst du den ersten Admin an.
Rollen
- Admin: legt Kunden + weitere Benutzer (Admins / Sachbearbeiter) an, verwaltet Upload-Links und pro-Kunde-Zugriffe. Hat WebDAV-Vollzugriff auf alles.
- Sachbearbeiter (Staff): sieht im Adminportal nur die Kunden, auf die ihm der Admin Zugriff erteilt hat. Per WebDAV greift er auf die zugeteilten Kundenordner zu (
readoderwrite). - Kunde: kein Login; Upload via individuellem Token-Link (optional mit Passwort + Ablaufdatum). Sieht keine Dateiliste.
Konfiguration
.env (Ports)
| Variable | Default | Zweck |
|---|---|---|
APP_PORT |
3500 |
Host-Port für Adminportal + Upload |
WEBDAV_PORT |
1900 |
Host-Port für WebDAV |
Admin-GUI → Einstellungen
- Öffentliche Basis-URL: wird in generierten Upload-Links verwendet. Leer = aus Request ableiten.
- Cron-Intervall (Minuten): periodischer DB/FS-Abgleich (entfernt verwaiste DB-Einträge von via WebDAV gelöschten Dateien und erfasst direkt per WebDAV hochgeladene Dateien).
Volumes
./data/db/→ SQLite-Datei neben derdocker-compose.yml./data/uploads/→ ein Unterordner pro Kunde (Slug)- Named Volume
webdav-config→ dynamisch generierte Apache-Config
Beide Container laufen als UID 1000:1000. Falls vorhandene Daten root gehören:
sudo chown -R 1000:1000 data/
Wie die WebDAV-ACLs funktionieren
Der App-Container erzeugt bei jeder Benutzer-/Kundenänderung:
/webdav-config/htpasswd— alle Benutzer (bcrypt-Hashes direkt aus DB)/webdav-config/access.conf— pro Kundenordner ein<Location>-Block:- gleiche Read- und Write-User → ein
Require user … - unterschiedliche →
<Limit GET PROPFIND OPTIONS HEAD>+<LimitExcept …>für saubere Trennung
- gleiche Read- und Write-User → ein
Der WebDAV-Container (Debian Apache) beobachtet das Verzeichnis via inotifywait und ruft apachectl graceful auf → Änderungen sind in ~2 Sek. wirksam.
Kunden-Upload
- Datei-Button, Ordner-Button oder Drag & Drop (Dateien und Ordner — Struktur bleibt erhalten).
- Optional Passwortabfrage, optional Ablaufdatum.
- Kunde sieht keine Dateiliste, nur eigenes Upload-Feedback.
WebDAV-Zugriff
- macOS Finder:
Gehe zu → Mit Server verbinden → http://HOST:1900/ - Linux / KDE Dolphin:
webdav://<user>@HOST:1900/ - Windows: siehe Abschnitt unten (einmalige Einrichtung nötig)
Write-Rechte umfassen: PUT, DELETE, MKCOL, MOVE, COPY, PROPPATCH, LOCK, UNLOCK.
In Dolphin löscht Shift+Entf direkt (umgeht den nicht existierenden WebDAV-Papierkorb).
Windows als Netzlaufwerk verbinden
Windows verweigert standardmäßig WebDAV via Basic Auth über HTTP und limitiert Dateien auf 50 MB. Beides per Registry erlauben:
-
windows/enable-webdav-basicauth.reg per Rechtsklick → Zusammenführen (als Administrator) ausführen.
-
WebClient-Dienst (neu) starten:
sc config WebClient start=auto net stop WebClient net start WebClient -
Verbinden — HTTP-URL ist die saubere Variante (eindeutig WebDAV, keine SMB-Verwechslung). Beispiel mit
karlheinz-Credentials, gemountet alsZ::net use Z: http://HOST:1900/frank-meier /user:karlheinz DEINPW /persistent:yesIm Explorer „Netzlaufwerk verbinden" → Adresse:
http://HOST:1900/bzw.http://HOST:1900/frank-meier/.Alternativ mit UNC-Syntax (intern dasselbe, etwas hakeliger):
\\HOST@1900\DavWWWRoot\frank-meier\—@1900und\DavWWWRoot\sind dabei Pflicht, sonst landest du bei SMB Port 445.
Wenn weiterhin „Ordner nicht gefunden" → meist ist der WebClient-Dienst nicht gestartet oder das Registry-Merge wurde nicht als Administrator ausgeführt.