107 lines
2.8 KiB
JavaScript
107 lines
2.8 KiB
JavaScript
(function () {
|
|
"use strict";
|
|
|
|
const TOKEN_KEY = "orgWebJwt";
|
|
const LOGIN_PATH = "/home/login.html";
|
|
|
|
function token() {
|
|
return window.localStorage.getItem(TOKEN_KEY) || "";
|
|
}
|
|
|
|
function isLoginPage() {
|
|
return window.location.pathname === LOGIN_PATH;
|
|
}
|
|
|
|
function loginUrl() {
|
|
const next = window.location.pathname + window.location.search + window.location.hash;
|
|
return `${LOGIN_PATH}?next=${encodeURIComponent(next)}`;
|
|
}
|
|
|
|
function redirectToLogin() {
|
|
if (!isLoginPage()) {
|
|
window.location.assign(loginUrl());
|
|
}
|
|
}
|
|
|
|
function authHeaders(existingHeaders = {}) {
|
|
const headers = new Headers(existingHeaders);
|
|
const jwt = token();
|
|
if (jwt) headers.set("Authorization", `Bearer ${jwt}`);
|
|
return headers;
|
|
}
|
|
|
|
async function authFetch(input, options = {}) {
|
|
const response = await fetch(input, {
|
|
...options,
|
|
headers: authHeaders(options.headers),
|
|
});
|
|
|
|
if (response.status === 401) {
|
|
window.localStorage.removeItem(TOKEN_KEY);
|
|
redirectToLogin();
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
async function login(username, password) {
|
|
const response = await fetch("/api/auth/login", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username, password }),
|
|
});
|
|
|
|
const data = await response.json().catch(() => ({}));
|
|
if (!response.ok) {
|
|
throw new Error(data.error || "Login failed");
|
|
}
|
|
|
|
window.localStorage.setItem(TOKEN_KEY, data.token);
|
|
return data.token;
|
|
}
|
|
|
|
function initLoginForm() {
|
|
const form = document.getElementById("login-form");
|
|
if (!form) return;
|
|
|
|
const message = document.getElementById("login-message");
|
|
form.addEventListener("submit", async (event) => {
|
|
event.preventDefault();
|
|
const submit = form.querySelector("button[type='submit']");
|
|
form.classList.add("is-loading");
|
|
form.setAttribute("aria-busy", "true");
|
|
if (submit) submit.disabled = true;
|
|
if (message) message.textContent = "";
|
|
|
|
try {
|
|
await login(form.username.value.trim(), form.password.value);
|
|
const params = new URLSearchParams(window.location.search);
|
|
window.location.assign(params.get("next") || "/");
|
|
} catch (error) {
|
|
if (message) message.textContent = error.message;
|
|
} finally {
|
|
if (submit) submit.disabled = false;
|
|
form.classList.remove("is-loading");
|
|
form.removeAttribute("aria-busy");
|
|
}
|
|
});
|
|
}
|
|
|
|
window.orgAuth = {
|
|
fetch: authFetch,
|
|
headers: authHeaders,
|
|
token,
|
|
logout: () => {
|
|
window.localStorage.removeItem(TOKEN_KEY);
|
|
redirectToLogin();
|
|
},
|
|
};
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
initLoginForm();
|
|
if (!isLoginPage() && !token()) {
|
|
redirectToLogin();
|
|
}
|
|
});
|
|
})();
|