first commit
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Sign in — Basis</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body class="login-body">
|
||||
<main class="login-main">
|
||||
<section class="panel login-panel">
|
||||
<h1 class="login-title">Basis</h1>
|
||||
<p class="notice error" id="login-error" hidden></p>
|
||||
<form id="login-form" class="form">
|
||||
<label>Username <input type="text" name="username" autocomplete="username" required autofocus></label>
|
||||
<label>Password <input type="password" name="password" autocomplete="current-password" required></label>
|
||||
<button type="submit">Sign in</button>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div class="modal-overlay" id="mfa-overlay" hidden>
|
||||
<div class="modal">
|
||||
<h2>Enter authenticator code</h2>
|
||||
<p class="hint">Your account has MFA enabled — enter the 6-digit code from your authenticator app.</p>
|
||||
<p class="notice error" id="mfa-error" hidden></p>
|
||||
<form id="mfa-form" class="form">
|
||||
<label>Code <input type="text" name="code" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" autocomplete="one-time-code" required></label>
|
||||
<button type="submit">Verify</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var loginForm = document.getElementById("login-form");
|
||||
var loginError = document.getElementById("login-error");
|
||||
var overlay = document.getElementById("mfa-overlay");
|
||||
var mfaForm = document.getElementById("mfa-form");
|
||||
var mfaError = document.getElementById("mfa-error");
|
||||
var pendingToken = "";
|
||||
|
||||
function postForm(url, fields) {
|
||||
var body = Object.keys(fields).map(function (k) {
|
||||
return encodeURIComponent(k) + "=" + encodeURIComponent(fields[k]);
|
||||
}).join("&");
|
||||
return fetch(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: body,
|
||||
}).then(function (r) { return r.json(); });
|
||||
}
|
||||
|
||||
function showError(el, msg) {
|
||||
el.textContent = msg;
|
||||
el.hidden = false;
|
||||
}
|
||||
|
||||
loginForm.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
loginError.hidden = true;
|
||||
var fd = new FormData(loginForm);
|
||||
postForm("/login", { username: fd.get("username"), password: fd.get("password") }).then(function (res) {
|
||||
if (res.error) {
|
||||
showError(loginError, res.error);
|
||||
return;
|
||||
}
|
||||
if (res.mfa_required) {
|
||||
pendingToken = res.pending_token;
|
||||
overlay.hidden = false;
|
||||
mfaForm.querySelector('input[name="code"]').focus();
|
||||
return;
|
||||
}
|
||||
window.location.href = res.redirect || "/";
|
||||
}).catch(function () {
|
||||
showError(loginError, "Something went wrong — try again.");
|
||||
});
|
||||
});
|
||||
|
||||
mfaForm.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
mfaError.hidden = true;
|
||||
var fd = new FormData(mfaForm);
|
||||
postForm("/login/mfa", { pending_token: pendingToken, code: fd.get("code") }).then(function (res) {
|
||||
if (res.error) {
|
||||
showError(mfaError, res.error);
|
||||
return;
|
||||
}
|
||||
window.location.href = res.redirect || "/";
|
||||
}).catch(function () {
|
||||
showError(mfaError, "Something went wrong — try again.");
|
||||
});
|
||||
});
|
||||
|
||||
overlay.addEventListener("click", function (e) {
|
||||
if (e.target === overlay) {
|
||||
overlay.hidden = true;
|
||||
pendingToken = "";
|
||||
mfaForm.reset();
|
||||
mfaError.hidden = true;
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user