Visitor sign in kiosk: multi-site, badge printing, WWCC expiry warnings, admin accounts with 2FA

This commit is contained in:
2026-09-04 14:55:59 +10:00
commit 3278890491
41 changed files with 8920 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
<!doctype html>
<html lang="en-AU">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<title>Sign in — visitor admin</title>
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="/css/login.css">
</head>
<body class="auth">
<div class="auth-card">
<header class="auth-head">
<button type="button" class="auth-back" id="auth-back" hidden aria-label="Go back">&#8592;</button>
<p class="auth-site" id="auth-site">Visitor admin</p>
<div class="auth-rail" id="auth-rail" hidden></div>
<h1 id="auth-title">Sign in</h1>
<p class="auth-sub" id="auth-subtitle"></p>
</header>
<div class="auth-body" id="auth-body">
<form class="auth-screen" id="step-password">
<label>
<span>Email address</span>
<input type="email" id="login-email" name="email" autocomplete="username" autocapitalize="none" required>
</label>
<label>
<span>Password</span>
<input type="password" id="login-password" name="password" autocomplete="current-password" required>
</label>
<p class="hint" id="domain-rule" hidden></p>
<button type="submit">Continue</button>
</form>
<form class="auth-screen" id="step-2fa" hidden>
<div id="twofa-setup" hidden>
<img id="twofa-qr" alt="Two factor setup QR code" width="180" height="180">
<details class="auth-details">
<summary>Can't scan it?</summary>
<p class="hint">Type this key into your authenticator app instead:</p>
<p><code id="twofa-secret"></code></p>
</details>
</div>
<label>
<span id="twofa-label">6 digit code</span>
<input id="twofa-code" name="code" inputmode="numeric" autocomplete="one-time-code" maxlength="12" required>
</label>
<button type="submit">Verify</button>
</form>
<div class="auth-screen" id="step-recovery" hidden>
<ul class="recovery" id="recovery-list"></ul>
<div class="auth-row">
<button type="button" class="secondary" id="recovery-copy">Copy codes</button>
<button type="button" id="recovery-done">I've saved them</button>
</div>
</div>
<form class="auth-screen" id="step-newpassword" hidden>
<!-- Hidden but present: password managers and screen readers need to know
which account the new password belongs to. -->
<input type="text" id="pw-username" name="username" autocomplete="username"
tabindex="-1" aria-hidden="true" class="visually-hidden" readonly>
<label>
<span>Current password</span>
<input type="password" id="pw-current" name="current-password" autocomplete="current-password" required>
</label>
<label>
<span>New password</span>
<input type="password" id="pw-new" name="new-password" autocomplete="new-password" required>
</label>
<label>
<span>New password again</span>
<input type="password" id="pw-again" name="confirm-password" autocomplete="new-password" required>
</label>
<p class="hint">At least 12 characters, with upper and lower case and a number.</p>
<button type="submit">Save and continue</button>
</form>
<div class="auth-screen" id="step-setup" hidden>
<p class="hint" id="setup-message"></p>
</div>
</div>
<p class="err" id="login-error" role="alert" hidden></p>
</div>
<p class="auth-foot">
<a href="/">Back to the kiosk</a>
<span>Created by: Jess Rogerson (yelling commands at Claude.AI)</span>
</p>
<script src="/js/login.js"></script>
</body>
</html>