Sicherheit: - .htaccess im Projektstamm mit X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy und einer Content-Security-Policy; da alle Assets lokal liegen, erlaubt sie nur noch die eigene Herkunft (Ausnahme: hCaptcha, falls aktiviert) - includes/, tools/, tests/, updater/storage und uploads/ schützen sich über eigene .htaccess-Dateien – auch bei Installation im Unterordner - Docker: AllowOverride All, damit diese Regeln überhaupt greifen, und ein Volume für uploads/, damit Logos ein Image-Update überstehen Werkzeuge: - tools/screenshots.py erzeugt alle Bilder in docs/screenshots aus der Demo-Instanz; tools/README.md beschreibt beides - Einstellungs-Tabs sind per ?tab=… direkt verlinkbar (serverseitig, also auch ohne JavaScript) Dokumentation: Readme um Markenfarben, Bild-Upload, lokale Assets, Sicherheits-Header (inkl. Nginx-Entsprechung) und einen Abschnitt "Entwicklung" ergänzt; Screenshots neu erzeugt, Version 2.6.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
544 lines
21 KiB
Markdown
544 lines
21 KiB
Markdown
<div align="center">
|
||
|
||
# 🎫 UniFi Voucher Management System
|
||
|
||
**Webbasiertes WLAN-Voucher-Management für UniFi OS** – mit Multi-Site-Support, Benutzerverwaltung, Microsoft-365-Login und integriertem Auto-Updater.
|
||
|
||

|
||

|
||

|
||

|
||

|
||

|
||
|
||
</div>
|
||
|
||
---
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/voucher-result.png" alt="Erstellter Voucher mit QR-Code" width="48%">
|
||
<img src="docs/screenshots/admin-dashboard.png" alt="Admin Dashboard" width="48%">
|
||
</div>
|
||
|
||
---
|
||
|
||
## ✨ Features
|
||
|
||
- 🎟️ **Voucher-Erstellung** mit sofortiger QR-Code-Anzeige, Druckvorlage und E-Mail-Versand
|
||
- 📦 **Bulk-Erstellung** – bis zu 20 Vouchers auf einmal, inkl. Sammeldruck-Layout
|
||
- 🧩 **Voucher-Profile/Templates** – vordefinierte Laufzeiten & Gerätelimits per Schnellauswahl
|
||
- 🏢 **Multi-Site-Support** – beliebig viele UniFi-Standorte zentral verwalten
|
||
- 👥 **Benutzerverwaltung** mit granularer Site-Zugriffskontrolle
|
||
- 🔐 **Authentifizierung** via lokale Accounts **oder** Microsoft 365 OAuth
|
||
- 🔒 **2FA (TOTP)** – optional, mit Recovery-Codes & erzwingbarer Admin-Pflicht
|
||
- 📈 **Reporting** – Auswertungen mit Charts und CSV-/PDF-Export
|
||
- 🩺 **Health-Endpoint** (`/health.php`) für Monitoring/Uptime
|
||
- 🔑 **Passwort-Reset** per E-Mail (token-basiert, zeitlich begrenzt)
|
||
- 🚦 **Bandbreiten- & Datenlimits** pro Voucher/Profil (UniFi QoS)
|
||
- 🧰 **REST-API mit API-Schlüsseln** – Scopes (read/write), Rate-Limit, OpenAPI-Spec
|
||
- 🪪 **Single Sign-On** via generisches OpenID Connect (zusätzlich zu M365)
|
||
- 📲 **SMS-Versand** der Codes (Twilio) · **CSV-Batch-Import** von Vouchern
|
||
- 🤖 **CAPTCHA** (Rechenaufgabe oder hCaptcha) im öffentlichen Modus
|
||
- 🗄️ **DB-gestützte Sessions** (opt-in) mit „überall abmelden"
|
||
- 🔔 **Webhooks** (Slack / Teams / generisch) für Erstellung, Ausfälle, neue Login-IP
|
||
- 🧹 **Auto-Cleanup & DSGVO** – Aufbewahrungsfristen per Cron
|
||
- 💾 **Config-Backup & -Restore** (JSON Export/Import)
|
||
- 🐳 **Docker** – Dockerfile + docker-compose (MariaDB)
|
||
- 🌍 **Öffentlicher Modus** – optional ohne Login nutzbar (mit CSRF-Schutz & Throttle)
|
||
- 🎨 **Einheitliches Design-System** – ein Stylesheet für Frontend, Login und Backend (Tokens, Komponenten, Light/Dark)
|
||
- 🏷️ **Login-Seite individualisierbar** – Firmenname, Logo, Texte, Hintergrundbild bzw. Farbverlauf
|
||
- 🖌️ **Eigene Markenfarben** – Akzentfarbe, Verlauf und Eckenradius wirken auf die gesamte Oberfläche
|
||
- ⬆️ **Bild-Upload** für Logo, Favicon und Login-Hintergrund (kein externes Hosting nötig)
|
||
- 🔒 **Keine externen CDNs** – Schrift, Icons, Diagramme und Editor werden lokal ausgeliefert (DSGVO, Offline-Netze)
|
||
- ♿ **Barrierearm** – Kontraste nach WCAG AA, Sprungmarke, aria-Beschriftungen, `prefers-reduced-motion`
|
||
- 📱 **Mobil nutzbar** – Tabellen werden auf schmalen Geräten zu Karten
|
||
- 🌗 **Dark Mode** – umschaltbar, Einstellung wird im Browser gespeichert
|
||
- 🌐 **Mehrsprachig** – Deutsch / Englisch per Umschalter (`lang/`)
|
||
- 📱 **Responsive Admin-Layout** mit Hamburger-Menü & Sidebar-Overlay
|
||
- 📊 **Admin-Dashboard** mit Live-Statistiken und Sync-Funktion
|
||
- 📝 **Audit-Log** – nachvollziehbare Protokollierung von Login & Änderungen (mit Filter)
|
||
- 📥 **CSV-Export** aller Vouchers pro Site
|
||
- 🔄 **Integrierter Auto-Updater** – Updates & DB-Migrationen per Klick aus dem Admin-Bereich
|
||
- 🛡️ **Security-by-default**: CSRF-Schutz, bcrypt-Passwörter, Prepared Statements,
|
||
Login-Rate-Limiting, OAuth-State-Validierung, Verschlüsselung sensibler Daten
|
||
|
||
---
|
||
|
||
## 📸 Screenshots
|
||
|
||
> Alle Screenshots stammen aus der Oberfläche in Version 2.5.0 (neues Design-System).
|
||
|
||
### Anmeldung & Voucher-Erstellung
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/login.png" alt="Anmeldung" width="48%">
|
||
<img src="docs/screenshots/login-branding.png" alt="Anmeldung mit eigenem Branding" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/voucher-form.png" alt="Voucher erstellen" width="48%">
|
||
<img src="docs/screenshots/settings-login.png" alt="Einstellungen der Login-Seite" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/voucher-result.png" alt="Voucher-Ergebnis mit QR-Code" width="48%">
|
||
<img src="docs/screenshots/bulk-vouchers.png" alt="Bulk-Voucher-Erstellung" width="48%">
|
||
</div>
|
||
|
||
### Administration
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/admin-dashboard.png" alt="Dashboard" width="48%">
|
||
<img src="docs/screenshots/admin-dashboard-dark.png" alt="Dashboard im Dark Mode" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/vouchers.png" alt="Live-Voucher-Verwaltung" width="48%">
|
||
<img src="docs/screenshots/settings.png" alt="Einstellungen" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/settings-branding.png" alt="Markenfarben einstellen" width="48%">
|
||
<img src="docs/screenshots/mobile-vouchers.png" alt="Ansicht auf dem Smartphone" width="22%">
|
||
</div>
|
||
|
||
### REST-API, 2FA & Integrationen
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/api-keys.png" alt="API-Schlüssel-Verwaltung" width="48%">
|
||
<img src="docs/screenshots/integrations.png" alt="Integration & Wartung" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/two-factor.png" alt="Zwei-Faktor-Authentifizierung" width="60%">
|
||
</div>
|
||
|
||
### Updater & Wartungsmodus
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/updater.png" alt="Updater – Ausgangszustand" width="48%">
|
||
<img src="docs/screenshots/updater-available.png" alt="Auto-Updater mit verfügbarem Update" width="48%">
|
||
</div>
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/maintenance.png" alt="Wartungsmodus" width="60%">
|
||
</div>
|
||
|
||
---
|
||
|
||
## 📋 Anforderungen
|
||
|
||
| Komponente | Version |
|
||
|---|---|
|
||
| PHP | 7.4+ (mit PDO, PDO_MySQL, cURL, mbstring, JSON; empfohlen: OpenSSL/libsodium, Zip) |
|
||
| Datenbank | MySQL 5.7+ / MariaDB 10.2+ |
|
||
| Webserver | Apache / Nginx |
|
||
| UniFi | **Network Application 7.0+ mit UniFi OS** (z. B. UDM, UDR, UniFi OS Server) |
|
||
|
||
---
|
||
|
||
## 🚀 Installation
|
||
|
||
```bash
|
||
git clone https://github.com/friloo/unifi-voucher-tool.git
|
||
cd unifi-voucher-tool
|
||
```
|
||
|
||
1. Dateien auf den Webserver hochladen
|
||
2. `https://ihre-domain.de/install.php` öffnen
|
||
3. Den **5-Schritte-Assistenten** durchlaufen:
|
||
1. Datenbank-Verbindungsdaten
|
||
2. Administrator-Account
|
||
3. Allgemeine Einstellungen (Titel, Logo, öffentlicher Zugriff)
|
||
4. Microsoft 365 Integration (optional)
|
||
5. Installation abschließen
|
||
4. `install.php` nach erfolgreicher Installation **löschen**
|
||
|
||
> 🔒 Der Installer erzeugt automatisch einen zufälligen `APP_KEY` (für die
|
||
> Verschlüsselung der UniFi-Passwörter) und eine `.htaccess`, die sensible
|
||
> Dateien sperrt. Ein erneuter Aufruf von `install.php?reinstall=1` ist nur
|
||
> für **angemeldete Administratoren** möglich.
|
||
|
||
### Sites konfigurieren
|
||
|
||
1. **Administration → Sites verwalten → Neue Site hinzufügen**
|
||
2. Felder ausfüllen:
|
||
- **Name:** Anzeigename (z. B. „Hauptgebäude")
|
||
- **Site ID:** UniFi Site ID (meist `default`)
|
||
- **Controller URL:** `https://unifi.example.com:11443`
|
||
- **Benutzername / Passwort:** UniFi Admin-Zugangsdaten
|
||
3. **Verbindung testen** klicken, dann speichern
|
||
|
||
### Voucher erstellen
|
||
|
||
1. Startseite öffnen (Login je nach Konfiguration optional)
|
||
2. Voucher-Name, Anzahl Geräte und Standort wählen
|
||
3. **Voucher erstellen** – Code und QR-Code werden sofort angezeigt
|
||
4. Code per E-Mail senden oder ausdrucken
|
||
|
||
---
|
||
|
||
## 🔄 Auto-Updater
|
||
|
||
Das System bringt einen vollständig integrierten Updater mit, der Quellcode und
|
||
Datenbank-Migrationen über einen zentralen Update-Proxy nachzieht – ganz ohne
|
||
SSH oder manuelles `git pull`.
|
||
|
||
```
|
||
[diese Instanz] ←HTTPS→ [Update-Proxy] ←pull→ [Git-Repo]
|
||
```
|
||
|
||
**Aufruf:** Administration → **System-Update** (`/admin/update.php`)
|
||
|
||
- 🔍 **„Auf Updates prüfen"** zeigt verfügbare Versionen inkl. Changelog
|
||
- ⬇️ **„Update installieren"** spielt das Update ein – mit Wartungsseite,
|
||
geschützten Pfaden (`config.php`, Uploads, …), automatischen DB-Migrationen
|
||
und OPcache-Reset
|
||
- 🔀 **Channel-Auswahl** zwischen `stable` und `development`
|
||
- 📊 **Migrations-Status** in einem eigenen Tab – inkl. Button **„Ausstehende
|
||
Migrationen ausführen"** (legt z. B. neue Tabellen für bestehende
|
||
Installationen an, ohne dass ein Code-Update nötig ist)
|
||
|
||
Während eines Updates wird die Anwendung kurz in den **Wartungsmodus** versetzt:
|
||
|
||
<div align="center">
|
||
<img src="docs/screenshots/maintenance.png" alt="Wartungsmodus" width="60%">
|
||
</div>
|
||
|
||
> Der Updater ist vollständig isoliert im Ordner [`updater/`](updater/) gekapselt.
|
||
> Details zur Architektur und eine Rückbau-Anleitung stehen in
|
||
> [`updater/README.md`](updater/README.md).
|
||
|
||
---
|
||
|
||
## ⚙️ Konfiguration
|
||
|
||
### `config.php`
|
||
|
||
Wird automatisch durch den Installer erstellt:
|
||
|
||
```php
|
||
<?php
|
||
define('DB_HOST', 'localhost');
|
||
define('DB_NAME', 'unifi_voucher');
|
||
define('DB_USER', 'username');
|
||
define('DB_PASS', 'password');
|
||
define('APP_KEY', '...'); // Schlüssel für Verschlüsselung-at-rest
|
||
define('SESSION_LIFETIME', 3600); // Session-Timeout in Sekunden
|
||
date_default_timezone_set('Europe/Berlin');
|
||
```
|
||
|
||
### Microsoft 365 OAuth (optional)
|
||
|
||
1. Im [Azure Portal](https://portal.azure.com) eine App-Registrierung anlegen
|
||
2. Umleitungs-URI: `https://ihre-domain.de/m365_callback.php`
|
||
3. API-Berechtigungen: `openid`, `profile`, `email`, `User.Read`
|
||
4. Client ID, Client Secret und Tenant ID in **Administration → Einstellungen** eintragen
|
||
|
||
### Cron-Job (empfohlen)
|
||
|
||
Automatische Synchronisation alle 30 Minuten:
|
||
|
||
```bash
|
||
*/30 * * * * curl -s "https://ihre-domain.de/cron_sync.php?token=IHR_CRON_TOKEN"
|
||
```
|
||
|
||
Den Token finden Sie unter **Administration → Einstellungen → Cron**.
|
||
|
||
---
|
||
|
||
## 🎨 Design-System
|
||
|
||
Frontend, Login-Seiten, Installer, Updater und der gesamte Admin-Bereich nutzen ein
|
||
gemeinsames Stylesheet: **`assets/global.css`**.
|
||
|
||
- **Design-Tokens** (`:root` bzw. `[data-theme="dark"]`) für Flächen, Text, Linien,
|
||
Markenfarbe, Statusfarben, Radien, Schatten und Layout-Maße
|
||
- **Komponenten** darauf aufgebaut: Buttons, Formularfelder, Cards, Tabellen, Badges,
|
||
Alerts, Tabs, Pagination, Modals, Toasts, Statistik-Kacheln, Sidebar/Topbar
|
||
- **Dark Mode** ausschließlich über Tokens – keine `!important`-Overrides mehr
|
||
- **Schriftart** Inter (via Google Fonts) mit System-Font-Fallback
|
||
|
||
### Markenfarben ohne Code
|
||
|
||
Unter **Administration → Einstellungen → Design** lassen sich Akzentfarbe
|
||
(hell und dunkel), Markenverlauf und Eckenradius setzen. Abgeleitete Töne –
|
||
Hover, weiche Flächen, Rahmen, Fokusring – berechnet das System per `color-mix`
|
||
aus der Grundfarbe; eine Farbe genügt also. Eine Live-Vorschau zeigt Button,
|
||
Badge, Chip und Logo-Kachel sofort im neuen Ton.
|
||
|
||
Die Werte landen als schlanker `:root`-Override im Seitenkopf und gelten überall,
|
||
auch auf Login-Seite, Installer und Updater. Wer lieber in CSS arbeitet, kann
|
||
dieselben Variablen weiterhin in `assets/global.css` überschreiben:
|
||
|
||
```css
|
||
:root {
|
||
--accent: #0f766e; /* Primärfarbe (Buttons, aktive Navigation) */
|
||
--brand-gradient: linear-gradient(135deg, #0f766e 0%, #0ea5e9 100%);
|
||
--r-lg: 14px; /* Eckenradius für Cards */
|
||
}
|
||
```
|
||
|
||
### Bilder hochladen
|
||
|
||
Logo, Favicon, Login-Logo und Login-Hintergrund lassen sich direkt hochladen –
|
||
alternativ bleibt das URL-Feld bestehen. Die Dateien landen unter `uploads/`
|
||
(Docker: eigenes Volume, siehe unten). Erlaubt sind PNG, JPG, WEBP, GIF und SVG
|
||
bis 3 MB; SVGs werden vor dem Speichern von Skripten und externen Verweisen
|
||
befreit, und im Upload-Ordner sperrt eine `.htaccess` die PHP-Ausführung.
|
||
|
||
### Assets ohne Drittanbieter
|
||
|
||
Schrift (Inter), Icons (Font Awesome), Diagramme (Chart.js), QR-Codes und der
|
||
WYSIWYG-Editor (TinyMCE) liegen unter `assets/vendor/` und kommen vom eigenen
|
||
Server. Das hält Besucher-IPs bei Ihnen – und die Oberfläche funktioniert auch
|
||
dort, wo das Netz keinen Weg nach außen hat. Details und Aktualisierungs-Hinweise:
|
||
[`assets/vendor/README.md`](assets/vendor/README.md).
|
||
|
||
Alle Asset-URLs tragen einen Versionsstempel (`?v=…`), damit Browser nach einem
|
||
Update nicht die alten Dateien aus dem Cache verwenden.
|
||
|
||
### Login-Seite individualisieren
|
||
|
||
Unter **Administration → Einstellungen → Login-Seite** lässt sich die Anmeldeseite
|
||
ohne Code-Änderung an das eigene Haus anpassen. Leere Felder verwenden jeweils den
|
||
Standardwert – eine frische Installation sieht also unverändert aus.
|
||
|
||
| Einstellung | Wirkung |
|
||
|---|---|
|
||
| Linke Bildspalte anzeigen | Split-Screen an/aus. Aus = zentrierte Anmeldekarte |
|
||
| Firmenname | Name neben dem Logo bzw. in der Fußzeile (leer = Anwendungstitel) |
|
||
| Logo (URL) | Eigenes Logo in der Bildspalte (leer = allgemeines Logo) |
|
||
| Überschrift / Beschreibungstext | Claim in der Bildspalte |
|
||
| Stichpunkte | Liste mit Haken – ein Stichpunkt pro Zeile, leer = keine Liste |
|
||
| Fußzeile | z. B. `© 2026 Muster GmbH · Datenschutz · Impressum` |
|
||
| Hintergrundbild (URL) | Formatfüllendes Bild der Bildspalte |
|
||
| Verlauf Start-/Endfarbe | Farbverlauf, wenn kein Bild gesetzt ist |
|
||
| Abdunklung (%) | Dunkle Ebene über dem Bild, damit der Text lesbar bleibt |
|
||
|
||
Über **„Vorschau öffnen"** lässt sich die Login-Seite als angemeldeter Administrator
|
||
ansehen (`login.php?preview=1`), ohne sich abzumelden.
|
||
|
||
---
|
||
|
||
## 🛡️ Sicherheit
|
||
|
||
Das Tool ist auf einen sicheren Standardbetrieb ausgelegt:
|
||
|
||
| Schutz | Umsetzung |
|
||
|---|---|
|
||
| **Passwörter** | bcrypt (`password_hash`) für Accounts |
|
||
| **UniFi-Passwörter** | Verschlüsselt-at-rest (AES-256-GCM / libsodium) über `APP_KEY` |
|
||
| **SQL-Injection** | Durchgängig Prepared Statements (PDO) |
|
||
| **CSRF** | Token für alle schreibenden Aktionen – auch im öffentlichen Modus |
|
||
| **OAuth** | `state`-Validierung gegen Login-CSRF |
|
||
| **Brute-Force** | Login-Rate-Limiting + Throttle der öffentlichen Voucher-Erstellung |
|
||
| **Sessions** | HttpOnly, SameSite, strict mode + absolutes Timeout |
|
||
| **Fehler** | `display_errors` aus, `log_errors` an (kein Info-Leak) |
|
||
|
||
Mitgeliefert wird eine `.htaccess` im Projektstamm mit Sicherheits-Headern
|
||
(`X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`,
|
||
`Permissions-Policy` und einer Content-Security-Policy). Da alle Assets lokal
|
||
liegen, erlaubt die CSP nur noch die eigene Herkunft – externe Verbindungen
|
||
bleiben lediglich für hCaptcha offen, falls es aktiviert wird. Ordner wie
|
||
`includes/`, `tools/`, `tests/` und `uploads/` schützen sich über eigene
|
||
`.htaccess`-Dateien.
|
||
|
||
> **Apache:** `AllowOverride All` muss für das Verzeichnis gesetzt sein, sonst
|
||
> werden die `.htaccess`-Dateien ignoriert. Das mitgelieferte Docker-Image
|
||
> erledigt das bereits.
|
||
|
||
Für **Nginx** entspricht das:
|
||
|
||
```nginx
|
||
add_header X-Content-Type-Options "nosniff" always;
|
||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; frame-ancestors 'self'" always;
|
||
|
||
location ~ ^/(includes|tools|tests)/ { deny all; }
|
||
location ~ ^/updater/(storage|migrations)/ { deny all; }
|
||
location ~ ^/(config\.php|database\.sql)$ { deny all; }
|
||
location ^~ /uploads/ { location ~ \.php$ { deny all; } }
|
||
```
|
||
|
||
```sql
|
||
-- Dedizierter Datenbank-Benutzer mit minimalen Rechten
|
||
CREATE USER 'unifi_voucher'@'localhost' IDENTIFIED BY 'sicheres_passwort';
|
||
GRANT SELECT, INSERT, UPDATE, DELETE ON unifi_voucher.* TO 'unifi_voucher'@'localhost';
|
||
```
|
||
|
||
---
|
||
|
||
## 🩺 Problembehandlung
|
||
|
||
<details>
|
||
<summary><b>Login funktioniert nicht</b></summary>
|
||
|
||
- Datenbankverbindung und PHP-Session-Konfiguration prüfen
|
||
- Fehler werden ins PHP-Error-Log geschrieben (nicht mehr in den Browser)
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>UniFi-Verbindung schlägt fehl</b></summary>
|
||
|
||
- Controller-URL im Browser testen
|
||
- Port **11443** für UniFi OS verwenden (nicht 8443)
|
||
- Benutzername, Passwort und Site ID prüfen
|
||
- cURL-Extension muss aktiviert sein
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>UniFi OS: HTTP 404 oder 401</b></summary>
|
||
|
||
- Login-Endpunkt ist `/api/auth/login` (nicht `/api/login`)
|
||
- API-Pfade benötigen Präfix `/proxy/network/api/s/{site}/...`
|
||
- Älterer UniFi Network Controller (ohne UniFi OS) wird ab Version 2.1.0 nicht mehr unterstützt
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>Microsoft 365 Login funktioniert nicht</b></summary>
|
||
|
||
- Redirect URI in Azure AD prüfen
|
||
- Client ID, Secret und Tenant ID kontrollieren
|
||
- Diagnose unter `m365_debug.php` (nur als Admin erreichbar)
|
||
</details>
|
||
|
||
---
|
||
|
||
## 📡 API-Dokumentation (UniFi OS)
|
||
|
||
```http
|
||
# Login
|
||
POST /api/auth/login
|
||
Body: {"username": "admin", "password": "password"}
|
||
Response-Header: X-CSRF-Token: <token>
|
||
|
||
# Voucher erstellen
|
||
POST /proxy/network/api/s/{site_id}/cmd/hotspot
|
||
X-CSRF-Token: <token>
|
||
Body: {"cmd": "create-voucher", "expire": 480, "n": 1, "note": "Name", "quota": 1}
|
||
|
||
# Vouchers abrufen
|
||
GET /proxy/network/api/s/{site_id}/stat/voucher
|
||
|
||
# Voucher löschen
|
||
POST /proxy/network/api/s/{site_id}/cmd/hotspot
|
||
Body: {"cmd": "delete-voucher", "_id": "<voucher_id>"}
|
||
```
|
||
|
||
---
|
||
|
||
## 🧰 REST-API
|
||
|
||
Voucher lassen sich programmatisch erstellen (z. B. aus Buchungssystemen oder
|
||
Self-Service-Terminals). Schlüssel werden unter **Administration → API-Schlüssel**
|
||
verwaltet. Authentifizierung per `Authorization: Bearer <key>` oder `X-API-Key`.
|
||
|
||
```bash
|
||
# Voucher erstellen
|
||
curl -X POST https://ihre-domain.de/api/vouchers.php \
|
||
-H "Authorization: Bearer uvt_…" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"site_id":1,"name":"API Gast","max_uses":1,"expire_minutes":480,
|
||
"qos":{"down":10000,"up":2000,"quota_mb":500}}'
|
||
|
||
# Sites auflisten
|
||
curl https://ihre-domain.de/api/sites.php -H "X-API-Key: uvt_…"
|
||
|
||
# Voucher einer Site abrufen
|
||
curl "https://ihre-domain.de/api/vouchers.php?site_id=1" -H "X-API-Key: uvt_…"
|
||
```
|
||
|
||
| Methode | Endpunkt | Zweck |
|
||
|---|---|---|
|
||
| `POST` | `/api/vouchers.php` | Voucher erstellen (optional mit QoS-Limits) |
|
||
| `GET` | `/api/vouchers.php?site_id=<id>` | Voucher einer Site auflisten |
|
||
| `GET` | `/api/sites.php` | Aktive Sites auflisten |
|
||
|
||
## 🔒 2FA, Webhooks & Wartung
|
||
|
||
- **2FA:** Unter **Administration → Sicherheit (2FA)** aktivierbar – QR-Code
|
||
scannen, Code bestätigen. Danach wird bei jeder Anmeldung ein Authenticator-
|
||
Code abgefragt.
|
||
- **Webhooks & Trusted-Proxy & Datenhaltung:** unter **Administration →
|
||
Integration & Wartung** konfigurierbar.
|
||
- **Auto-Cleanup (DSGVO):** täglicher Cron, löscht abgelaufene Voucher,
|
||
Audit-Log, Login-Versuche nach einstellbaren Fristen:
|
||
```bash
|
||
0 3 * * * curl -s "https://ihre-domain.de/cron_cleanup.php?token=IHR_CRON_TOKEN"
|
||
```
|
||
|
||
## 🐳 Docker
|
||
|
||
```bash
|
||
# APP_KEY erzeugen und in docker-compose.yml eintragen:
|
||
php -r 'echo base64_encode(random_bytes(32))."\n";'
|
||
|
||
docker compose up -d # App auf http://localhost:8080
|
||
```
|
||
|
||
Das Schema wird beim ersten Start automatisch in MariaDB geladen; danach den
|
||
Installer (`/install.php`) für den Admin-Account aufrufen oder Config per ENV
|
||
setzen (`DB_*`, `APP_KEY`).
|
||
|
||
Hochgeladene Logos und Hintergründe liegen im Volume `uploads` und überstehen
|
||
damit ein Image-Update. Bei eigener Apache-/Nginx-Installation muss `uploads/`
|
||
für den Webserver beschreibbar sein:
|
||
|
||
```bash
|
||
chown -R www-data:www-data uploads updater/storage
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Entwicklung
|
||
|
||
Für Screenshots und einen schnellen Durchlauf aller Seiten gibt es eine
|
||
Demo-Instanz **ohne Datenbank** – `Database` und `Auth` werden durch Stubs mit
|
||
festen Beispieldaten ersetzt:
|
||
|
||
```bash
|
||
python3 tools/demo/build.py /tmp/uvt-demo
|
||
php -S 127.0.0.1:8123 -t /tmp/uvt-demo &
|
||
|
||
# Bilder in docs/screenshots neu erzeugen (benötigt headless Chromium)
|
||
CHROME_BIN=/usr/bin/chromium python3 tools/screenshots.py
|
||
```
|
||
|
||
Details und die verfügbaren Demo-Zustände: [`tools/README.md`](tools/README.md).
|
||
|
||
Tests und statische Analyse:
|
||
|
||
```bash
|
||
composer install
|
||
vendor/bin/phpunit
|
||
vendor/bin/phpstan analyse
|
||
```
|
||
|
||
## 🗺️ Roadmap
|
||
|
||
- [x] Voucher-Templates (vordefinierte Laufzeiten)
|
||
- [x] Bulk-Voucher-Erstellung
|
||
- [x] Mehrsprachigkeit (DE/EN)
|
||
- [x] Dark Mode
|
||
- [x] Passwort-Reset
|
||
- [x] Audit-Log
|
||
- [x] Auto-Updater mit DB-Migrationen
|
||
- [x] REST-API mit API-Schlüsseln
|
||
- [x] 2FA (TOTP), Webhooks, Bandbreitenlimits
|
||
- [x] Docker-Container
|
||
- [x] Erweiterte Reporting-Funktionen (CSV/PDF) + Health-Endpoint
|
||
- [x] 2FA-Recovery-Codes, API-Scopes/Rate-Limit/OpenAPI, Test-Suite (PHPUnit/PHPStan)
|
||
- [x] Gemeinsames Design-System für Frontend, Login und Backend
|
||
- [x] Branding über die Oberfläche (Farben, Logo, Login-Seite)
|
||
- [x] Assets lokal ausliefern (keine Drittanbieter-CDNs)
|
||
- [x] Vollständige englische Übersetzung des Admin-Bereichs
|
||
|
||
---
|
||
|
||
<div align="center">
|
||
|
||
**Version 2.6.0** · Autor: **Friederich Loheide** · Lizenz: **MIT**
|
||
|
||
</div>
|