Jede Display-Seite bringt jetzt ihr eigenes Erscheinungsbild mit – der
Empfang sieht anders aus als der Tagungsraum nebenan:
- eigenes Logo (leer = Logo aus den Einstellungen)
- formatfüllendes Hintergrundbild mit einstellbarer Abdunklung (0–90 %),
damit die Karte auf hellen Fotos lesbar bleibt
- eigene Akzentfarbe für den Knopf (leer = Farbe aus dem Design-Tab)
- Karte wahlweise hell oder dunkel; auf Fotos wirkt dunkel meist ruhiger
Logo und Hintergrund lassen sich hochladen oder als URL hinterlegen; beim
Löschen einer Display-Seite verschwinden die hochgeladenen Dateien mit.
Nebenbei aufgeräumt: das Bildfeld (Vorschau + Upload + URL + Entfernen)
lag als Funktion in admin/settings.php und wird jetzt von beiden Seiten
genutzt – Ui::imageField() für die Darstellung, Upload::resolveField()
für die Auswertung.
Sicherheit: die Akzentfarbe landet in einem style-Attribut, deshalb wird
sie sowohl beim Speichern als auch beim Ausgeben auf eine echte Hex-Farbe
geprüft; ein Test hält das fest.
Migration 0006, database.sql nachgezogen, 4 neue Tests (42 gesamt),
Screenshots ergänzt, Version 2.8.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Für Empfang, Lobby oder Tagungsraum lässt sich je Site eine öffentliche
Seite anlegen (kiosk.php), die auf einem Bildschirm oder Tablet läuft:
ein großer Knopf, ein Klick, ein Zugangscode mit QR-Code. Nach einer
einstellbaren Anzeigedauer springt der Bildschirm zurück, damit der
nächste Gast nicht den Code seines Vorgängers sieht.
Verwaltung unter Administration → Display-Seiten:
- Site und optionales Voucher-Profil (bestimmt Laufzeit, Geräte, QoS)
- eigene Überschrift und Text für den Bildschirm
- Codes pro Tag, Wartezeit zwischen zwei Codes, Anzeigedauer
- geheimer Link zum Kopieren, als QR-Code anzeigbar und jederzeit
erneuerbar (der alte Link gilt dann sofort nicht mehr)
Absicherung: der Link ist der Zugang, deshalb Tageslimit und Wartezeit
je Display, CSRF-Token am Formular, `noindex` im Kopf und ein Eintrag im
Audit-Log für jeden ausgegebenen Code. Webhooks werden für Kiosk-Codes
bewusst nicht ausgelöst – ein Empfangsdisplay würde den Kanal fluten.
Technik:
- neue Tabelle `kiosks`, `vouchers.kiosk_id` hält die Herkunft fest
(Migration 0005, database.sql nachgezogen)
- includes/Kiosk.php kapselt Token, Limits und Profil-Auflösung
- includes/VoucherService.php bündelt die Voucher-Erstellung, die vorher
in index.php lag und für den Kiosk ein zweites Mal nötig gewesen wäre
- Startbildschirm zeigt zusätzlich einen QR auf sich selbst, damit Gäste
die Seite am eigenen Handy öffnen können
Tests: 9 neue Fälle für Token-Prüfung, Wartezeit, Tageslimit und
Profil-Auflösung (38 Tests gesamt), PHPStan deckt Kiosk.php mit ab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
tools/runner/ enthält eine Compose-Datei, eine Beispiel-Konfiguration und
eine Schritt-für-Schritt-Anleitung, um den Runner auf dem Server zu
registrieren. Der Runner läuft in einem eigenen Verzeichnis und fasst
/opt/forgejo nicht an.
Abgestimmt auf die vorhandenen Workflows und den Server:
- Label-Zuordnung ubuntu-latest -> node:20-bookworm, damit runs-on in
ci.yml und release.yml greift
- capacity 1 und Speicherlimit, weil der Server nur 4 GB hat
- Hinweis darauf, was das Reichen des Docker-Sockets bedeutet, und die
Host-Modus-Alternative samt ihrer Grenzen (setup-php braucht Container)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.github/workflows/release.yml baut bei jedem Push auf main (also auch
nach jedem gemergten Pull Request) ein installierbares Paket und hängt es
an das rollende Vorab-Release "latest-main". Der Download-Link bleibt
damit stabil und zeigt immer auf den aktuellen Stand. Ein Tag v* erzeugt
mit derselben Mechanik ein reguläres Release.
Details:
- das ZIP entsteht per `git archive`, die Auswahl steuert .gitattributes
(export-ignore) – docs/, tests/, tools/ und CI bleiben draußen, das
Paket ist rund 1,4 MB groß
- eine Prüfschritt kontrolliert, dass Kerndateien wirklich enthalten sind,
dazu gibt es eine .sha256-Datei
- zusätzlich als Build-Artefakt abgelegt (optional, bricht nicht ab, wenn
der Artefakt-Speicher fehlt)
- Release-API wird über den automatisch bereitgestellten Token
angesprochen, FORGEJO_TOKEN dient als Ausweichweg; ohne Token wird der
Schritt übersprungen statt fehlzuschlagen
Neu ist die Datei VERSION als einzige Quelle der Versionsnummer: sie
benennt das Paket und erscheint über Ui::version() unten in der
Admin-Seitenleiste ("v2.6.0 · Entwickelt von Loheide.eu").
Geprüft: Paket lokal gebaut, entpackt und die Anwendung daraus gestartet –
alle Seiten antworten mit 200, keine fehlenden Dateien.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- CI-Badge von github.com entfernt (zeigte ins Leere); stattdessen ein
statisches Test-Badge und ein Link zum Repository
- Clone-Befehl in der Installation auf git.loheide.cloud umgestellt
- neuer Abschnitt "Repository & Mitwirken" mit HTTPS-/SSH-Adressen,
Hinweis auf Issues und Pull Requests sowie der tea-CLI
- vermerkt, dass .github/workflows von Forgejo Actions mitgelesen wird und
docker-publish.yml (ghcr.io) noch aus der GitHub-Zeit stammt
- klargestellt, dass der Auto-Updater unabhängig davon über
update.loheide.eu läuft
- Entwicklungs-Abschnitt nennt jetzt auch die CI-Prüfungen der Sprachdateien
- composer.json: homepage, authors und support-Links ergänzt
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zentral in Ui::credit() gepflegt und dezent im Seitenfuß eingebunden:
- Admin-Bereich: unter dem Benutzerbereich in der Sidebar
- öffentliche Voucher-Seite: unter der Karte
- Anmeldung, Installer und Updater: am Ende der jeweiligen Karte
- Wartungsseite: direkt im Markup, da sie bewusst eigenständig bleibt
- README: im Kopf und in der Fußzeile
Der Hinweis ist übersetzt ("Entwickelt von" / "Developed by") und stört
das Branding der Betreiber nicht – die konfigurierbare Fußzeile der
Login-Seite bleibt unverändert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Neuer Einstellungs-Tab "Login-Seite" (Administration → Einstellungen):
- Firmenname und eigenes Logo für die Anmeldeseite
- Überschrift, Beschreibungstext, Stichpunkte (eine Zeile je Punkt) und
Fußzeile frei setzbar
- Hintergrundbild für die linke Bildspalte, alternativ Farbverlauf mit
Farbwähler (Start-/Endfarbe) sowie einstellbarer Abdunklung für die
Lesbarkeit auf hellen Bildern
- Bildspalte abschaltbar: dann zentrierte Anmeldekarte auf dem
App-Hintergrund
- "Vorschau öffnen" zeigt die Login-Seite als angemeldeter Admin
(login.php?preview=1), ohne die Sitzung zu beenden
Alle Felder sind optional; leere Werte fallen auf die bisherigen
Standardtexte und -farben zurück. Bestehende Installationen sehen
unverändert aus, es ist keine Migration nötig.
README um den Abschnitt "Login-Seite individualisieren" mit Beispiel-
Screenshots ergänzt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>
Alle Screenshots im einheitlichen Format neu gerendert; Admin-Mockups mit
vollständiger, konsistenter Sidebar. Neue README-Sektion mit API-Keys-,
Integration-&-Wartung- und 2FA-Screenshot.
- updater/migrations/0001_feature_ui_tables.sql: legt voucher_templates und
password_reset_tokens idempotent an (CREATE TABLE IF NOT EXISTS), damit
bestehende Installationen die neuen Tabellen per System-Update erhalten
- Updater-UI: Button "Ausstehende Migrationen ausführen" + run_migrations-Action
(CSRF-geschützt) im Migrations-Tab
- README: Features (Bulk, Templates, Dark Mode, i18n, Audit-Log, Passwort-Reset),
zwei neue Screenshots (Bulk-Erstellung, Dashboard Dark Mode), Roadmap & Updater-
Abschnitt aktualisiert
Bug fixes:
- UniFiController: add CURLOPT_TIMEOUT (10s) and CURLOPT_CONNECTTIMEOUT (5s)
to login() and apiRequest() — prevents page freeze when controller unreachable
- UniFiController: fix login response validation for UniFi OS API which returns
a user object instead of meta.rc=ok
- admin/sites.php: add JS loading state on form submit to give visual feedback
- login.php: handle new 'rate_limited' return value from Auth::login()
New features:
- Database: in-memory settings cache eliminates redundant DB queries per request
- Auth: login rate limiting (10 attempts per 10 min per IP/email) via login_attempts table
- admin/vouchers.php: CSV export with UTF-8 BOM for Excel compatibility
- admin/vouchers.php: client-side pagination (50 per page)
- index.php: QR code display after voucher creation (qrcodejs CDN)
- Mailer: sendTestEmail() method
- admin/settings.php: SMTP test button with AJAX handler
- database.sql: add login_attempts and audit_log tables
Readme: condensed from ~420 to ~220 lines, removed duplicated sections,
M365 Azure Portal walkthrough, contribution guidelines, update/migration section
https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
- Update login endpoint: /api/login → /api/auth/login
- Add X-CSRF-Token extraction via CURLOPT_HEADERFUNCTION in login()
- Inject X-CSRF-Token header into all POST requests in apiRequest()
- Prefix all API paths with /proxy/network (createVoucher, getVouchers, deleteVoucher)
- Update admin/sites.php placeholder and help text to reflect port 11443
- Update Readme.md: fix GitHub clone URL, update port references, rewrite
API documentation section for UniFi OS, add UniFi OS troubleshooting entry,
bump version to 2.1.0
https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq