Project-Image-Uploader/scripts/README.md
matthias.lotz 6332b82c6a Feature Request: admin session security
- 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
2025-11-23 21:18:42 +01:00

330 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scripts Overview
## Admin-Benutzer anlegen (Shell)
```bash
./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
```bash
# Python Dependencies installieren
pip install -r requirements.txt
# Oder einzeln:
pip install requests pillow
```
## Usage
### Einfacher Upload
```bash
# 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
```bash
# 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:
```bat
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:
```bash
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:
```bash
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
1. **Verzeichnis-Struktur**: Aus dem Jahr-Verzeichnis (z.B. `2024/`)
2. **EXIF-Daten**: `DateTime`, `DateTimeOriginal`, `DateTimeDigitized`
3. **Pfad-Pattern**: `2024`, `2023`, etc. in anderen Verzeichnis/Dateinamen
4. **Fallback**: Aktuelles Jahr
### Titel
1. **Parameter**: `--titel` (überschreibt alles)
2. **Projekt-Verzeichnis**: `Urlaub_Mallorca``Urlaub Mallorca`
3. **Cleaning**: Unterstriche/Bindestriche → Leerzeichen
### Beschreibung
1. **README.md im Projekt-Verzeichnis**: Erste Zeile der README.md
2. **README.md im Name-Verzeichnis**: Als Fallback
3. **Pfad-Info**: `Jahr: 2024 | Name: Max Mustermann | Projekt: Urlaub Mallorca`
4. **Final-Fallback**: Verzeichnis-Pfad
### Name
1. **Parameter**: `--name` (überschreibt alles)
2. **Name-Verzeichnis**: Aus dem Namen-Verzeichnis (z.B. `Max_Mustermann`)
3. **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
```markdown
# 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
```json
{
"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
```bash
# 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
```bash
# Prüfe Backend-Status
curl http://localhost:5000/api/groups
# Backend starten
cd ../
./prod.sh
```
### EXIF-Fehler
```bash
# Pillow neu installieren
pip install --upgrade Pillow
```
### Performance bei großen Batches
```bash
# 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
```