|
Some checks are pending
CI / PHP Lint (push) Waiting to run
CI / PHP Lint-1 (push) Waiting to run
CI / Unit Tests & Static Analysis (push) Waiting to run
CI / PHP Lint (pull_request) Waiting to run
CI / PHP Lint-1 (pull_request) Waiting to run
CI / Unit Tests & Static Analysis (pull_request) Waiting to run
Frontend, Login/Installer/Updater und der komplette Admin-Bereich nutzen jetzt ein einziges Stylesheet (assets/global.css) statt pro Seite dupliziertem Inline-CSS. Design-System - Tokens für Flächen, Text, Linien, Marke, Status, Radien, Schatten und Layout-Maße; Dark Mode ausschließlich über Tokens (keine !important- Overrides mehr) - Komponenten: Buttons, Formularfelder, Cards, Tabellen, Badges, Alerts, Tabs, Pagination, Modals, Toasts, Statistik-Kacheln, Empty States - Schrift Inter mit System-Fallback Oberfläche - Admin-Shell neu: durchgehende Sidebar mit Marke, gruppierter Navigation und Benutzerbereich; schlanke Topbar mit Breadcrumb - Dashboard: ruhige KPI-Kacheln mit Icon-Chips, Charts an Theme-Farben gekoppelt - Öffentliche Voucher-Seite: App-Topbar, klare Formularstruktur und Ticket-Darstellung des erstellten Codes inkl. QR-Code - Login/Passwort/2FA: zweispaltiges Auth-Layout bzw. Fokus-Karten - Updater und Wartungsmodus im gleichen Look (Wartungsseite bleibt bewusst eigenständig ohne externe Abhängigkeiten) - Emoji-Icons in der UI durch Font-Awesome-Icons ersetzt Nebenbei behoben - Falscher SRI-Hash blockierte qrcode.min.js – QR-Codes wurden auf der Voucher-Seite und bei der 2FA-Einrichtung nie gerendert - assets/global.css wurde in mehreren Admin-Seiten über einen falschen Pfad eingebunden ($adminBase = '' statt '../') - TinyMCE lädt ohne API-Key jetzt die GPL-Variante von cdnjs – kein "valid API key required"-Banner mehr im Einstellungs-Editor - Tabellen in Cards scrollen horizontal statt zu überlaufen Screenshots in docs/screenshots neu erstellt, README aktualisiert (neuer Abschnitt "Design-System", Version 2.5.0). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| admin | ||
| api | ||
| assets | ||
| docker | ||
| docs/screenshots | ||
| includes | ||
| lang | ||
| tests | ||
| updater | ||
| .dockerignore | ||
| .gitignore | ||
| composer.json | ||
| config.php | ||
| cron_cleanup.php | ||
| cron_sync.php | ||
| cron_test.php | ||
| database.sql | ||
| docker-compose.yml | ||
| Dockerfile | ||
| forgot_password.php | ||
| health.php | ||
| index.php | ||
| install.php | ||
| login.php | ||
| login_simple.php | ||
| logout.php | ||
| m365_callback.php | ||
| m365_debug.php | ||
| oidc_callback.php | ||
| phpstan.neon | ||
| phpunit.xml.dist | ||
| Readme.md | ||
| reset_password.php | ||
| test.php | ||
🎫 UniFi Voucher Management System
Webbasiertes WLAN-Voucher-Management für UniFi OS – mit Multi-Site-Support, Benutzerverwaltung, Microsoft-365-Login und integriertem Auto-Updater.
✨ 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)
- 🌗 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
Administration
REST-API, 2FA & Integrationen
Updater & Wartungsmodus
📋 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
git clone https://github.com/friloo/unifi-voucher-tool.git
cd unifi-voucher-tool
- Dateien auf den Webserver hochladen
https://ihre-domain.de/install.phpöffnen- Den 5-Schritte-Assistenten durchlaufen:
- Datenbank-Verbindungsdaten
- Administrator-Account
- Allgemeine Einstellungen (Titel, Logo, öffentlicher Zugriff)
- Microsoft 365 Integration (optional)
- Installation abschließen
install.phpnach 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 voninstall.php?reinstall=1ist nur für angemeldete Administratoren möglich.
Sites konfigurieren
- Administration → Sites verwalten → Neue Site hinzufügen
- 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
- Verbindung testen klicken, dann speichern
Voucher erstellen
- Startseite öffnen (Login je nach Konfiguration optional)
- Voucher-Name, Anzahl Geräte und Standort wählen
- Voucher erstellen – Code und QR-Code werden sofort angezeigt
- 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
stableunddevelopment - 📊 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:
Der Updater ist vollständig isoliert im Ordner
updater/gekapselt. Details zur Architektur und eine Rückbau-Anleitung stehen inupdater/README.md.
⚙️ Konfiguration
config.php
Wird automatisch durch den Installer erstellt:
<?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)
- Im Azure Portal eine App-Registrierung anlegen
- Umleitungs-URI:
https://ihre-domain.de/m365_callback.php - API-Berechtigungen:
openid,profile,email,User.Read - Client ID, Client Secret und Tenant ID in Administration → Einstellungen eintragen
Cron-Job (empfohlen)
Automatische Synchronisation alle 30 Minuten:
*/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 (
:rootbzw.[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
Eigenes Branding lässt sich meist mit wenigen Zeilen umsetzen – z. B. in einer
eigenen CSS-Datei oder direkt in assets/global.css:
:root {
--accent: #0f766e; /* Primärfarbe (Buttons, aktive Navigation) */
--accent-hover: #0d5f59;
--accent-soft: #e6f4f2; /* Flächen für aktive Zustände */
--brand-gradient: linear-gradient(135deg, #0f766e 0%, #0ea5e9 100%);
--r-lg: 14px; /* Eckenradius für Cards */
}
Logo und Favicon werden nicht über CSS, sondern unter Administration → Einstellungen → Allgemein gesetzt.
🛡️ 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) |
Empfohlene zusätzliche Härtung am Server:
# .htaccess – sensible Dateien sperren (wird vom Installer erzeugt)
<FilesMatch "^(config\.php|database\.sql|install\.php|test\.php|m365_debug\.php|.*\.md)$">
Require all denied
</FilesMatch>
-- 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
Login funktioniert nicht
- Datenbankverbindung und PHP-Session-Konfiguration prüfen
- Fehler werden ins PHP-Error-Log geschrieben (nicht mehr in den Browser)
UniFi-Verbindung schlägt fehl
- 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
UniFi OS: HTTP 404 oder 401
- 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
Microsoft 365 Login funktioniert nicht
- Redirect URI in Azure AD prüfen
- Client ID, Secret und Tenant ID kontrollieren
- Diagnose unter
m365_debug.php(nur als Admin erreichbar)
📡 API-Dokumentation (UniFi OS)
# 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.
# 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:
0 3 * * * curl -s "https://ihre-domain.de/cron_cleanup.php?token=IHR_CRON_TOKEN"
🐳 Docker
# 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).
🗺️ Roadmap
- Voucher-Templates (vordefinierte Laufzeiten)
- Bulk-Voucher-Erstellung
- Mehrsprachigkeit (DE/EN)
- Dark Mode
- Passwort-Reset
- Audit-Log
- Auto-Updater mit DB-Migrationen
- REST-API mit API-Schlüsseln
- 2FA (TOTP), Webhooks, Bandbreitenlimits
- Docker-Container
- Erweiterte Reporting-Funktionen (CSV/PDF) + Health-Endpoint
- 2FA-Recovery-Codes, API-Scopes/Rate-Limit/OpenAPI, Test-Suite (PHPUnit/PHPStan)
- Gemeinsames Design-System für Frontend, Login und Backend
Version 2.5.0 · Autor: Friederich Loheide · Lizenz: MIT