103 lines
2.7 KiB
JavaScript
103 lines
2.7 KiB
JavaScript
async function readJsonResponse(response) {
|
|
const text = await response.text();
|
|
if (!text) {
|
|
return {};
|
|
}
|
|
try {
|
|
return JSON.parse(text);
|
|
} catch (error) {
|
|
throw new Error(text);
|
|
}
|
|
}
|
|
|
|
function nextLocation() {
|
|
const params = new URLSearchParams(window.location.search);
|
|
const candidate = (params.get("next") || "").trim();
|
|
if (candidate.startsWith("/") && !candidate.startsWith("//")) {
|
|
return candidate;
|
|
}
|
|
return "/select";
|
|
}
|
|
|
|
window.addEventListener("DOMContentLoaded", async () => {
|
|
const bootIndicator = document.getElementById("boot-indicator");
|
|
const root = document.getElementById("login-root");
|
|
const form = document.getElementById("login-form");
|
|
const usernameInput = document.getElementById("username");
|
|
const passwordInput = document.getElementById("password");
|
|
const submitButton = document.getElementById("login-submit");
|
|
const errorNode = document.getElementById("login-error");
|
|
|
|
const showForm = () => {
|
|
if (bootIndicator) {
|
|
bootIndicator.hidden = true;
|
|
}
|
|
if (root) {
|
|
root.hidden = false;
|
|
}
|
|
};
|
|
|
|
const setError = (message) => {
|
|
if (!errorNode) {
|
|
return;
|
|
}
|
|
errorNode.textContent = message || "";
|
|
errorNode.hidden = !message;
|
|
};
|
|
|
|
try {
|
|
const response = await fetch("/api/auth/session", {
|
|
cache: "no-store",
|
|
credentials: "same-origin",
|
|
});
|
|
if (response.ok) {
|
|
window.location.replace(nextLocation());
|
|
return;
|
|
}
|
|
|
|
if (response.status !== 401) {
|
|
const payload = await readJsonResponse(response);
|
|
setError(payload.error || `HTTP ${response.status}`);
|
|
}
|
|
} catch (error) {
|
|
setError(error instanceof Error ? error.message : String(error));
|
|
} finally {
|
|
showForm();
|
|
}
|
|
|
|
if (!form || !(usernameInput instanceof HTMLInputElement) || !(passwordInput instanceof HTMLInputElement)) {
|
|
return;
|
|
}
|
|
|
|
usernameInput.focus();
|
|
|
|
form.addEventListener("submit", async (event) => {
|
|
event.preventDefault();
|
|
setError("");
|
|
submitButton.disabled = true;
|
|
|
|
try {
|
|
const response = await fetch("/api/auth/login", {
|
|
method: "POST",
|
|
credentials: "same-origin",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
username: usernameInput.value.trim(),
|
|
password: passwordInput.value,
|
|
}),
|
|
});
|
|
const payload = await readJsonResponse(response);
|
|
if (!response.ok) {
|
|
throw new Error(payload.error || `HTTP ${response.status}`);
|
|
}
|
|
window.location.replace(nextLocation());
|
|
} catch (error) {
|
|
setError(error instanceof Error ? error.message : String(error));
|
|
} finally {
|
|
submitButton.disabled = false;
|
|
}
|
|
});
|
|
});
|