- replace bearer auth with session+CSRF flow and add admin user directory - update frontend moderation flow, force password change gate, and new CLI - refresh changelog/docs/feature plan + ensure swagger dev experience |
||
|---|---|---|
| .. | ||
| test_images | ||
| batch_uploader.py | ||
| create_admin_user.sh | ||
| examples.sh | ||
| README.md | ||
| requirements.txt | ||
| test_path_compatibility.py | ||
| test_setup.py | ||
Scripts Overview
Admin-Benutzer anlegen (Shell)
./create_admin_user.sh --username admin2 --password 'SehrSicher123!'
Optionen entsprechen dem Node-Skript (backend/src/scripts/createAdminUser.js): --role <rolle> und --require-password-change sind verfügbar. Das Skript setzt automatisch SKIP_PREVIEW_GENERATION=1, prüft ob Node installiert ist und leitet alle Argumente an das bestehende CLI weiter. Alternativ kann weiterhin npm run create-admin -- --username ... im Backend-Ordner benutzt werden.
Batch Image Uploader
Ein Python-Skript für automatischen Batch-Upload von Bildern mit Metadaten-Extraktion.
Features
- 🔍 Rekursives Verzeichnis-Scanning nach unterstützten Bildformaten
- 📊 Automatische Metadaten-Extraktion aus EXIF-Daten und Pfad-Struktur
- 🚀 Batch-Upload mit automatischer Projekt-Gruppierung
- 📈 Progress-Tracking und Error-Handling
- 🏗️ Strukturierte Metadaten (Jahr, Titel, Beschreibung, Name)
- 🔐 Admin-Session Login mit CSRF-Schutz (entsprechend
AUTHENTICATION.md)
Installation
# Python Dependencies installieren
pip install -r requirements.txt
# Oder einzeln:
pip install requests pillow
Usage
Einfacher Upload
# Linux/macOS
python batch_uploader.py /path/to/images --titel "Meine Foto-Sammlung" \
--user admin --password 'SehrSicher123!'
# Windows
python batch_uploader.py "C:\Users\username\Photos" --titel "Meine Foto-Sammlung" ^
--user admin --password "SehrSicher123!"
Erweiterte Optionen
# Linux/macOS - Mit Standard-Name und Backend-URL
python batch_uploader.py ./photos \
--titel "Urlaubsbilder 2024" \
--name "Max Mustermann" \
--backend http://localhost:5000 \
--user admin --password 'SehrSicher123!' \
--social-media-consents consents.json
## Windows / WSL: Pfade mit Leerzeichen und Sonderzeichen
Windows-PowerShell (empfohlen):
```powershell
# Doppelte Anführungszeichen um den kompletten Pfad, Backslashes bleiben unverändert
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=" \
--titel "Nextcloud Archive" --name "Lotz M." --verbose \
--user admin --password "SehrSicher123!"
Windows (CMD) – ohne Anführungszeichen mit Escapes oder mit Anführungszeichen:
REM Mit Backslashes escapen (CMD):
python batch_uploader.py C:\Users\lotzm\Nextcloud2\HH\ DropFolder\ with\ quota\=NutzerBildUploads= \
--titel "Nextcloud Archive" --user admin --password SehrSicher123!
REM Oder einfacher mit Anführungszeichen:
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=" \
--titel "Nextcloud Archive" --user admin --password "SehrSicher123!"
WSL / Linux (bash) – Pfad in /mnt/c/... verwenden, ohne zusätzliche Backslashes in Quotes:
python3 batch_uploader.py "/mnt/c/Users/lotzm/Nextcloud2/HH DropFolder with quota/=NutzerBildUploads=" \
--titel "Nextcloud Archive" --name "Lotz M." --verbose \
--user admin --password 'SehrSicher123!'
# oder ohne Quotes, mit Backslash-Escapes:
python3 batch_uploader.py /mnt/c/Users/lotzm/Nextcloud2/HH\ DropFolder\ with\ quota/=NutzerBildUploads= \
--titel "Nextcloud Archive" --user admin --password 'SehrSicher123!'
Hinweis:
- Verwende nicht gleichzeitig single-quotes und Backslash-Escapes: in single-quotes werden Backslashes nicht als Escape interpretiert.
- Prüfe mit
ls(oder Tab-Completion), ob der Pfad exakt existiert, bevor du das Skript startest.
Dry-Run (nur Analyse) - Cross-Platform
python batch_uploader.py /photos --dry-run --verbose python batch_uploader.py "D:\Photos" --dry-run --verbose
Nicht-rekursiv (nur Top-Level)
python batch_uploader.py ./images --no-recursive
### Parameter
| Parameter | Beschreibung | Standard |
|-----------|--------------|----------|
| `directory` | Verzeichnis mit Bildern (Required) | - |
| `--titel` | Standard-Titel für alle Bilder | Aus Pfad extrahiert |
| `--name` | Standard-Name für alle Bilder | Leer |
| `--backend` | Backend-URL | `http://localhost:5000` |
| `--user / --password` | Admin-Credentials für Session-Login | - |
| `--workshop-consent` / `--no-workshop-consent` | Zustimmung zur Anzeige in der Werkstatt | `True` |
| `--social-media-consents` | JSON-String oder Datei mit Social-Media-Consents | `[]` |
| `--no-recursive` | Nicht in Unterverzeichnisse | `False` |
| `--dry-run` | Nur Analyse, kein Upload | `False` |
| `--verbose` | Detailliertes Logging | `False` |
## Admin-Login & Consents
Der Batch-Uploader verwendet denselben Session-/CSRF-Flow wie die Admin-UI (siehe `AUTHENTICATION.md`).
1. **Admin-Benutzer vorbereiten** – entweder über die UI oder per `./create_admin_user.sh`.
2. **Login-Daten übergeben** – `--user admin --password '•••'`.
3. **Skript führt automatisch aus**:
- `POST /auth/login`
- `GET /auth/csrf-token` (falls nötig)
- `POST /api/upload/batch` mit `X-CSRF-Token`
### Consents setzen
- `workshopConsent` ist Pflicht. Standard ist `True`, kann via `--no-workshop-consent` deaktiviert werden.
- Social-Media-Consents können aus einer Datei oder einem JSON-String geladen werden:
```json
[
{ "platformId": 1, "consented": true },
{ "platformId": 2, "consented": false }
]
Aufruf-Beispiel:
python batch_uploader.py ./photos \
--user admin --password 'SehrSicher123!' \
--social-media-consents consents.json
Metadaten-Extraktion
Erwartete Struktur: Photos/Jahr/Name/Projekt/dateiname.endung
Jahr
- Verzeichnis-Struktur: Aus dem Jahr-Verzeichnis (z.B.
2024/) - EXIF-Daten:
DateTime,DateTimeOriginal,DateTimeDigitized - Pfad-Pattern:
2024,2023, etc. in anderen Verzeichnis/Dateinamen - Fallback: Aktuelles Jahr
Titel
- Parameter:
--titel(überschreibt alles) - Projekt-Verzeichnis:
Urlaub_Mallorca→Urlaub Mallorca - Cleaning: Unterstriche/Bindestriche → Leerzeichen
Beschreibung
- README.md im Projekt-Verzeichnis: Erste Zeile der README.md
- README.md im Name-Verzeichnis: Als Fallback
- Pfad-Info:
Jahr: 2024 | Name: Max Mustermann | Projekt: Urlaub Mallorca - Final-Fallback: Verzeichnis-Pfad
Name
- Parameter:
--name(überschreibt alles) - Name-Verzeichnis: Aus dem Namen-Verzeichnis (z.B.
Max_Mustermann) - Fallback: Leer
Unterstützte Formate
- Bilder:
.jpg,.jpeg,.png,.gif,.bmp,.webp,.tiff,.tif - Max. Größe: 10MB pro Datei
Beispiel-Output
12:34:56 - __main__ - INFO - Teste Verbindung zu http://localhost:5000...
12:34:56 - __main__ - INFO - ✅ Backend erreichbar
12:34:56 - __main__ - INFO - Scanne Verzeichnis: /home/user/photos
12:34:56 - __main__ - INFO - 📁 25 Bilder gefunden
12:34:56 - __main__ - INFO - 🚀 Starte Upload...
12:34:56 - __main__ - INFO - Starte Upload von 25 Bildern in 5er Batches
12:34:57 - __main__ - INFO - Chunk erfolgreich: 5 Bilder
12:34:57 - __main__ - INFO - Progress: 20.0% (5/25)
12:34:58 - __main__ - INFO - Chunk erfolgreich: 5 Bilder
12:34:58 - __main__ - INFO - Progress: 40.0% (10/25)
...
12:35:01 - __main__ - INFO - 📊 Upload abgeschlossen:
12:35:01 - __main__ - INFO - ✅ Erfolgreich: 25
12:35:01 - __main__ - INFO - ❌ Fehlgeschlagen: 0
Verzeichnis-Struktur Beispiele
Input-Struktur: Photos/Jahr/Name/Projekt/dateiname.endung
Linux/macOS:
photos/
├── 2024/
│ ├── Max_Mustermann/
│ │ ├── Urlaub_Mallorca/
│ │ │ ├── README.md
│ │ │ ├── sonnenuntergang.jpg
│ │ │ └── strand_spaziergang.jpg
│ │ └── Hochzeit_Anna/
│ │ ├── README.md
│ │ ├── zeremonie.jpg
│ │ └── party.jpg
│ └── Anna_Schmidt/
│ └── Architektur_Berlin/
│ ├── README.md
│ └── brandenburger_tor.jpg
└── 2023/
└── Familie_Mueller/
└── Weihnachten/
├── README.md
└── weihnachtsbaum.jpg
Windows:
C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=\
├── 2024\
│ ├── Familie_Schmidt\
│ │ ├── Urlaub_Toskana\
│ │ │ ├── README.md
│ │ │ ├── florenz_dom.jpg
│ │ │ └── vineyard_sunset.jpg
│ │ └── Geburtstag_Opa\
│ │ ├── README.md
│ │ ├── torte.jpg
│ │ └── familie_komplett.jpg
│ └── Max_Mueller\
│ └── Business_Frankfurt\
│ ├── README.md
│ └── skyline_evening.jpg
└── 2023\
└── Events\
└── Hochzeit_Sarah\
├── README.md
└── kirche_aussen.jpg
README.md Beispiel
# Urlaub Mallorca
Traumhafter Urlaub auf Mallorca mit Sonne, Strand und entspannten Momenten am Pool.
## Details
- Jahr: 2024
- Fotograf: Max Mustermann
- Projekt: Urlaub Mallorca
Extrahierte Metadaten
{
"jahr": "2024",
"titel": "Urlaub Mallorca",
"beschreibung": "Traumhafter Urlaub auf Mallorca mit Sonne, Strand und entspannten Momenten am Pool.",
"name": "Max Mustermann"
}
Error-Handling
- Connection-Timeout: 10s für Backend-Test, 60s für Upload
- File-Errors: Automatisches Skip von beschädigten Bildern
- Projekt-Fehler: Fehler in einem Projekt stoppen den Gesamtprozess nicht
- Retry-Logic: Verwendet Session für Connection-Reuse
Cross-Platform Support
- ✅ Windows: Vollständige Unterstützung für Windows-Pfade und Leerzeichen
- ✅ Linux/macOS: Native Unix-Pfad Unterstützung
- ✅ Nextcloud/Dropbox: Funktioniert mit Sync-Ordnern
- ✅ Netzwerk-Pfade: UNC-Pfade (
\\server\share) unterstützt
Windows-spezifische Hinweise
# Absolute Pfade mit Leerzeichen in Anführungszeichen
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads="
# Escape-Zeichen für Sonderzeichen im Pfad
python batch_uploader.py "D:\Photos\Familie Schmidt\2024 Events"
# UNC-Netzwerk-Pfade
python batch_uploader.py "\\\\nas-server\\photos\\2024" --verbose
Performance
- Single-Group Upload: Alle Bilder einer Session gehören zu EINER Gruppe (Fixed!)
- Session-Reuse: HTTP-Connections werden wiederverwendet
- Memory-Effizient: Bilder werden einzeln gelesen und direkt uploaded
- Path-Performance:
pathlib.Path.resolve()für optimale Pfad-Verarbeitung - Robuste Uploads: Längere Timeouts für große Batches (120s)
Troubleshooting
Backend nicht erreichbar
# Prüfe Backend-Status
curl http://localhost:5000/api/groups
# Backend starten
cd ../
./prod.sh
EXIF-Fehler
# Pillow neu installieren
pip install --upgrade Pillow
Performance bei großen Batches
# Nach Jahr oder Name aufteilen
python batch_uploader.py /photos/2024/Familie_Schmidt \
--user admin --password 'SehrSicher123!'
# Vorab prüfen
python batch_uploader.py /photos --dry-run --verbose