Display-Seiten: Gäste holen sich den Zugang selbst
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>
This commit is contained in:
parent
5d72febadc
commit
61810eb050
30 changed files with 1360 additions and 29 deletions
|
|
@ -89,6 +89,16 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
patch(os.path.join(target, 'admin', 'api_keys.php'), '$keys = $db->fetchAll(',
|
||||
"if (($_GET['demo'] ?? '') === 'new') { $newKey = 'uvt_3f9a2c7d41e8b60592af18cc4d7e0b3a95f2617c'; }\n$keys = $db->fetchAll(")
|
||||
|
||||
# Kiosk: ausgegebenen Code zeigen, ohne echten Controller (?demo=code)
|
||||
patch(os.path.join(target, 'kiosk.php'),
|
||||
"$headline = trim((string)($kiosk['headline'] ?? ''))",
|
||||
'''if (($_GET['demo'] ?? '') === 'code' && $kiosk) {
|
||||
$voucher = ['code' => '4829-17364', 'site_name' => $kiosk['site_name'], 'max_uses' => 2,
|
||||
'expire_min' => 480, 'expiry_date' => '24.09.2026', 'expiry_time' => '08:00'];
|
||||
}
|
||||
|
||||
$headline = trim((string)($kiosk['headline'] ?? ''))''')
|
||||
|
||||
# Theme per Query-Parameter erzwingen (fuer Dark-Mode-Screenshots)
|
||||
ui = os.path.join(target, 'includes', 'Ui.php')
|
||||
patch(ui, 'var s=localStorage.getItem("theme");',
|
||||
|
|
|
|||
|
|
@ -58,6 +58,22 @@ class Database {
|
|||
public function fetchAll($sql, $params = []) {
|
||||
$s = preg_replace('/\s+/', ' ', strtolower($sql));
|
||||
|
||||
if (str_contains($s, 'from kiosks')) {
|
||||
return [
|
||||
['id'=>1,'site_id'=>1,'template_id'=>1,'name'=>'Empfang Erdgeschoss','token'=>'a1b2c3d4e5f60718293a4b5c6d7e8f90',
|
||||
'headline'=>'Willkommen im Hotel Seeblick','subline'=>'Tippen Sie auf den Knopf – Ihr WLAN-Code erscheint sofort.',
|
||||
'is_active'=>1,'daily_limit'=>150,'cooldown_seconds'=>15,'display_seconds'=>90,'last_used_at'=>null,
|
||||
'site_name'=>'Hauptstandort Nord','site_active'=>1,'template_name'=>'Tagesgast',
|
||||
'tpl_max_uses'=>2,'tpl_expire_minutes'=>480,'qos_rate_max_down'=>20000,'qos_rate_max_up'=>5000,'qos_usage_quota'=>0,
|
||||
'total_vouchers'=>412,'today_vouchers'=>23,'created_at'=>'2026-06-01 10:00:00'],
|
||||
['id'=>2,'site_id'=>2,'template_id'=>null,'name'=>'Tagungsraum West','token'=>'0f1e2d3c4b5a69788796a5b4c3d2e1f0',
|
||||
'headline'=>'','subline'=>'','is_active'=>1,'daily_limit'=>0,'cooldown_seconds'=>30,'display_seconds'=>60,
|
||||
'last_used_at'=>null,'site_name'=>'Campus West','site_active'=>1,'template_name'=>null,
|
||||
'tpl_max_uses'=>0,'tpl_expire_minutes'=>0,'qos_rate_max_down'=>0,'qos_rate_max_up'=>0,'qos_usage_quota'=>0,
|
||||
'total_vouchers'=>87,'today_vouchers'=>4,'created_at'=>'2026-07-12 09:30:00'],
|
||||
];
|
||||
}
|
||||
|
||||
if (str_contains($s, 'count(*) as count from sites')) return [['count'=>4]];
|
||||
if (str_contains($s, 'count(*) as count from users')) return [['count'=>12]];
|
||||
if (str_contains($s, 'count(*) as count from vouchers where date(created_at)=curdate()')) return [['count'=>18]];
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ SHOTS = [
|
|||
('two-factor.png', 'admin/security.php', 1200, 900),
|
||||
('updater.png', 'admin/update.php', 1200, 780),
|
||||
('updater-available.png', 'admin/update.php?demo=available', 1200, 780),
|
||||
('kiosk-display.png', 'kiosk.php?k=a1b2c3d4e5f60718293a4b5c6d7e8f90', 1200, 900),
|
||||
('kiosk-code.png', 'kiosk.php?k=a1b2c3d4e5f60718293a4b5c6d7e8f90&demo=code', 1200, 900),
|
||||
('kiosks-admin.png', 'admin/kiosks.php', 1200, 780),
|
||||
('mobile-vouchers.png', 'admin/users.php', 430, 860),
|
||||
('maintenance.png', 'updater/templates/maintenance.html', 1200, 700),
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue