No description
Find a file
friloo b7f13d8fac
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
Merge pull request 'README auf Forgejo umstellen' (#4) from docs/forgejo into main
2026-09-23 13:58:31 +00:00
.github/workflows Tests für Upload und Ui, strengere CI-Prüfungen 2026-09-23 06:52:22 +00:00
admin Sicherheits-Header, Werkzeuge und Dokumentation 2026-09-23 06:49:14 +00:00
api API-Reife: Scopes (read/write), Rate-Limit pro Key, OpenAPI-Spec 2026-06-05 20:47:26 +00:00
assets Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
docker Erweiterte Features (2/2): Cleanup/DSGVO, Webhooks, REST-API, Backup, CI, Docker 2026-06-05 19:45:28 +00:00
docs/screenshots Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
includes Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
lang Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
tests Tests für Upload und Ui, strengere CI-Prüfungen 2026-09-23 06:52:22 +00:00
tools Sicherheits-Header, Werkzeuge und Dokumentation 2026-09-23 06:49:14 +00:00
updater Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
uploads Branding: Farben systemweit einstellbar + Bild-Upload statt nur URLs 2026-09-23 06:27:30 +00:00
.dockerignore Erweiterte Features (2/2): Cleanup/DSGVO, Webhooks, REST-API, Backup, CI, Docker 2026-06-05 19:45:28 +00:00
.gitignore Konsolidierung: Security-Härtung + .gitignore 2026-06-06 05:38:40 +00:00
.htaccess Sicherheits-Header, Werkzeuge und Dokumentation 2026-09-23 06:49:14 +00:00
composer.json README: Projekt liegt auf Forgejo, nicht mehr auf GitHub 2026-09-23 13:58:16 +00:00
config.php Security: OAuth-state, Verschlüsselung, Session-Timeout & weitere Härtung 2026-06-05 18:45:47 +00:00
cron_cleanup.php Webhook-Events & Health-Endpoint 2026-06-05 20:49:06 +00:00
cron_sync.php Webhook-Events & Health-Endpoint 2026-06-05 20:49:06 +00:00
cron_test.php Initial Upload 2026-04-21 17:45:58 +02:00
database.sql DB-gestützte Sessions (opt-in) + 'überall abmelden' 2026-06-06 05:49:53 +00:00
docker-compose.yml Sicherheits-Header, Werkzeuge und Dokumentation 2026-09-23 06:49:14 +00:00
Dockerfile Sicherheits-Header, Werkzeuge und Dokumentation 2026-09-23 06:49:14 +00:00
forgot_password.php Barrierefreiheit und mobile Darstellung 2026-09-23 06:38:08 +00:00
health.php Webhook-Events & Health-Endpoint 2026-06-05 20:49:06 +00:00
index.php Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
install.php Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
login.php Entwicklerhinweis "Entwickelt von Loheide.eu" ergänzen 2026-09-23 11:21:53 +00:00
login_simple.php Barrierefreiheit und mobile Darstellung 2026-09-23 06:38:08 +00:00
logout.php Initial Upload 2026-04-21 17:45:58 +02:00
m365_callback.php Security: OAuth-state, Verschlüsselung, Session-Timeout & weitere Härtung 2026-06-05 18:45:47 +00:00
m365_debug.php Alle Frontend-Assets lokal ausliefern statt über CDNs 2026-09-23 06:23:44 +00:00
oidc_callback.php Generisches OIDC-SSO (weitere Auth-Quelle) 2026-06-06 05:47:20 +00:00
phpstan.neon Tests für Upload und Ui, strengere CI-Prüfungen 2026-09-23 06:52:22 +00:00
phpunit.xml.dist E-Mail-Retry, Voucher-Resend, Tageslimit, Docker-Politur 2026-06-05 20:56:26 +00:00
Readme.md README: Projekt liegt auf Forgejo, nicht mehr auf GitHub 2026-09-23 13:58:16 +00:00
reset_password.php Barrierefreiheit und mobile Darstellung 2026-09-23 06:38:08 +00:00
test.php Alle Frontend-Assets lokal ausliefern statt über CDNs 2026-09-23 06:23:44 +00:00

🎫 UniFi Voucher Management System

Webbasiertes WLAN-Voucher-Management für UniFi OS mit Multi-Site-Support, Benutzerverwaltung, Microsoft-365-Login und integriertem Auto-Updater.

Entwickelt von Loheide.eu

PHP MySQL UniFi OS License Version Tests Repository


Erstellter Voucher mit QR-Code Admin Dashboard

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

Anmeldung Anmeldung mit eigenem Branding
Voucher erstellen Einstellungen der Login-Seite
Voucher-Ergebnis mit QR-Code Bulk-Voucher-Erstellung

Administration

Dashboard Dashboard im Dark Mode
Live-Voucher-Verwaltung Einstellungen
Markenfarben einstellen Ansicht auf dem Smartphone

REST-API, 2FA & Integrationen

API-Schlüssel-Verwaltung Integration & Wartung
Zwei-Faktor-Authentifizierung

Updater & Wartungsmodus

Updater – Ausgangszustand Auto-Updater mit verfügbarem Update
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://git.loheide.cloud/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:

Wartungsmodus

Der Updater ist vollständig isoliert im Ordner updater/ gekapselt. Details zur Architektur und eine Rückbau-Anleitung stehen in updater/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)

  1. Im Azure Portal 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:

*/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:

: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.

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:

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; } }
-- 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).

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:

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:

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.

Tests und statische Analyse:

composer install
vendor/bin/phpunit          # 29 Tests (Crypto, TOTP, API-Keys, Upload, Ui)
vendor/bin/phpstan analyse  # Level 5

Die Pipeline (.github/workflows/ci.yml) führt zusätzlich einen Syntax-Check über alle PHP-Dateien aus und prüft, ob lang/de.php und lang/en.php dieselben Schlüssel enthalten und jeder im Code verwendete Schlüssel existiert. Dieselben Schritte lassen sich lokal ausführen.


📦 Repository & Mitwirken

Der Quellcode liegt auf der eigenen Forgejo-Instanz nicht auf GitHub:

https://git.loheide.cloud/friloo/Unifi-Voucher-Tool

# HTTPS
git clone https://git.loheide.cloud/friloo/Unifi-Voucher-Tool.git

# SSH (Port 2222)
git clone ssh://git@git.loheide.cloud:2222/friloo/Unifi-Voucher-Tool.git

Fehlerberichte und Änderungsvorschläge laufen über die Issues und Pull Requests dort. Für die Kommandozeile eignet sich tea, die Gitea-/Forgejo-CLI:

tea pr create      # Pull Request öffnen
tea issues ls      # offene Tickets ansehen

Die Workflows unter .github/workflows/ werden von Forgejo Actions mitgelesen; das Badge oben ist bewusst statisch, solange kein Runner registriert ist. docker-publish.yml veröffentlicht nach ghcr.io und stammt noch aus der GitHub-Zeit für den Forgejo-Betrieb entweder auf die eigene Registry umstellen oder entfernen.

Der Auto-Updater ist davon unabhängig: er zieht seine Pakete über update.loheide.eu (Channels stable und development) und nicht direkt aus dem Git-Hoster.


🗺️ 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
  • Branding über die Oberfläche (Farben, Logo, Login-Seite)
  • Assets lokal ausliefern (keine Drittanbieter-CDNs)
  • Vollständige englische Übersetzung des Admin-Bereichs

Version 2.6.0 · Autor: Friederich Loheide · Lizenz: MIT

Entwickelt von Loheide.eu