auth: add login page and shared auth.js
This commit is contained in:
parent
8b842f5d74
commit
646fa747ab
22
containers/clearview/site/auth.js
Normal file
22
containers/clearview/site/auth.js
Normal file
@ -0,0 +1,22 @@
|
||||
(function (global) {
|
||||
async function postJson(url, body) {
|
||||
const r = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
let data = null;
|
||||
try { data = await r.json(); } catch (_) {}
|
||||
return { ok: r.ok, status: r.status, data };
|
||||
}
|
||||
|
||||
async function getJson(url) {
|
||||
const r = await fetch(url, { credentials: 'same-origin' });
|
||||
let data = null;
|
||||
try { data = await r.json(); } catch (_) {}
|
||||
return { ok: r.ok, status: r.status, data };
|
||||
}
|
||||
|
||||
global.ClearviewAuth = { postJson, getJson };
|
||||
})(window);
|
||||
49
containers/clearview/site/login.html
Normal file
49
containers/clearview/site/login.html
Normal file
@ -0,0 +1,49 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Clearview — Sign in</title>
|
||||
<link rel="stylesheet" href="/styles.css" />
|
||||
</head>
|
||||
<body class="auth-page">
|
||||
<main class="auth-card">
|
||||
<h1>Clearview</h1>
|
||||
<p class="auth-sub">Sign in to continue</p>
|
||||
<form id="loginForm">
|
||||
<label>Username<input name="username" autocomplete="username" required autofocus /></label>
|
||||
<label>Password<input name="password" type="password" autocomplete="current-password" required /></label>
|
||||
<label class="auth-remember"><input name="remember" type="checkbox" /> Remember me for 30 days</label>
|
||||
<button type="submit">Sign in</button>
|
||||
<p id="loginError" class="auth-error" hidden></p>
|
||||
</form>
|
||||
</main>
|
||||
<script src="/auth.js"></script>
|
||||
<script>
|
||||
(async function () {
|
||||
const setup = await ClearviewAuth.getJson('/api/auth/setup-required');
|
||||
if (setup.ok && setup.data && setup.data.setup_required) {
|
||||
window.location.replace('/setup.html');
|
||||
return;
|
||||
}
|
||||
const form = document.getElementById('loginForm');
|
||||
const err = document.getElementById('loginError');
|
||||
form.addEventListener('submit', async (ev) => {
|
||||
ev.preventDefault();
|
||||
err.hidden = true;
|
||||
const fd = new FormData(form);
|
||||
const res = await ClearviewAuth.postJson('/api/auth/login', {
|
||||
username: fd.get('username'),
|
||||
password: fd.get('password'),
|
||||
remember: fd.get('remember') === 'on',
|
||||
});
|
||||
if (res.ok) {
|
||||
window.location.replace('/');
|
||||
} else {
|
||||
err.textContent = (res.data && res.data.detail) || 'Sign-in failed';
|
||||
err.hidden = false;
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -752,3 +752,19 @@ strong {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* === Auth (login / setup) pages and header badge ============================== */
|
||||
.auth-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: #0f1115; margin: 0; }
|
||||
.auth-card { width: 360px; max-width: 92vw; padding: 28px; background: #1a1d24; border-radius: 12px; box-shadow: 0 8px 28px rgba(0,0,0,.35); color: #e6e8ee; font-family: system-ui, sans-serif; }
|
||||
.auth-card h1 { margin: 0 0 4px; font-size: 22px; }
|
||||
.auth-sub { margin: 0 0 18px; opacity: .75; }
|
||||
.auth-card form { display: flex; flex-direction: column; gap: 12px; }
|
||||
.auth-card label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
|
||||
.auth-card input[type=text], .auth-card input[type=password], .auth-card input:not([type]) { padding: 8px 10px; background: #0e1116; border: 1px solid #2a2f3a; border-radius: 6px; color: inherit; }
|
||||
.auth-card .auth-remember { flex-direction: row; align-items: center; gap: 8px; font-size: 13px; }
|
||||
.auth-card button { padding: 10px; background: #3b82f6; border: 0; border-radius: 6px; color: #fff; font-weight: 600; cursor: pointer; }
|
||||
.auth-card button:hover { background: #2563eb; }
|
||||
.auth-error { background: #3a1f25; color: #fda4af; padding: 8px 10px; border-radius: 6px; font-size: 13px; }
|
||||
.user-badge { display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px; border: 1px solid #2a2f3a; border-radius: 999px; font-size: 12px; }
|
||||
.user-badge button { background: transparent; border: 0; color: #93c5fd; cursor: pointer; padding: 0; }
|
||||
.user-badge button:hover { text-decoration: underline; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user