Add file upload portal with per-customer links and WebDAV admin access
- Customer upload via token link (no login), optional password + expiry, drag & drop for files and folders with preserved structure - Admin portal with setup wizard, role-based users (admin/staff), per-customer WebDAV access rules (read/write), session auth - WebDAV container (Debian apache2) with htpasswd + access.conf auto-generated from the SQLite DB and reloaded via inotifywait - Configurable public base URL and janitor cron interval in admin UI; janitor reconciles the uploads table with the filesystem Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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 (`read` oder `write`).
|
||||
- **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 der `docker-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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
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/`
|
||||
- Windows: Netzlaufwerk hinzufügen → `http://HOST:1900/`
|
||||
- Linux / KDE Dolphin: `webdav://<user>@HOST:1900/`
|
||||
- Write-Rechte umfassen: `PUT`, `DELETE`, `MKCOL`, `MOVE`, `COPY`, `PROPPATCH`, `LOCK`, `UNLOCK`.
|
||||
- In Dolphin löscht **Shift+Entf** direkt (umgeht den nicht existierenden WebDAV-Papierkorb).
|
||||
Reference in New Issue
Block a user