server_photo_s85js/public/js/auth.js
2026-08-11 08:45:04 +02:00

433 lines
5.6 KiB
JavaScript

// ===============================
// AUTH.JS — Login + Token + Redirect + Sessione browser
// ===============================
// parseJwt DEVE essere globale
function parseJwt(token) {
try {
const base64Url = token.split(".")[1];
const base64 = base64Url
.replace(/-/g, "+")
.replace(/_/g, "/");
const jsonPayload = decodeURIComponent(
atob(base64)
.split("")
.map(
(c) =>
"%" +
("00" + c.charCodeAt(0).toString(16)).slice(-2),
)
.join(""),
);
return JSON.parse(jsonPayload);
} catch (e) {
console.error("Errore parseJwt:", e);
return null;
}
}
(() => {
const LOGIN_ENDPOINT = "/auth/login";
const TOKEN_KEY = "token";
// -------------------------------
// TOKEN STORAGE
// -------------------------------
function saveToken(token) {
try {
localStorage.setItem(TOKEN_KEY, token);
} catch (err) {
console.error("Errore salvataggio token:", err);
}
}
function getToken() {
try {
return localStorage.getItem(TOKEN_KEY) || "";
} catch {
return "";
}
}
function clearToken() {
try {
localStorage.removeItem(TOKEN_KEY);
sessionStorage.removeItem("app_open");
} catch {}
}
// -------------------------------
// LOGIN
// -------------------------------
async function login(email, password) {
try {
const res = await fetch(LOGIN_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
});
if (!res.ok) {
const msg = await res.text();
throw new Error(
msg || "Credenziali non valide"
);
}
const data = await res.json();
if (!data?.token) {
throw new Error(
"Token mancante nella risposta"
);
}
saveToken(data.token);
// segna apertura applicazione
sessionStorage.setItem(
"app_open",
"1"
);
window.dispatchEvent(
new CustomEvent(
"login:success",
{
detail: data,
}
)
);
scheduleAutoLogout();
return data;
} catch(err) {
console.error(
"Errore login:",
err
);
throw err;
}
}
// -------------------------------
// CHECK LOGIN
// -------------------------------
function isLoggedIn() {
// nuova apertura browser/tab
if (
!sessionStorage.getItem("app_open")
) {
console.log(
"[AUTH] nuova apertura browser"
);
return false;
}
const token = getToken();
if (!token) {
console.log(
"[AUTH] token assente"
);
return false;
}
const payload = parseJwt(token);
if (!payload?.exp) {
console.log(
"[AUTH] token senza exp"
);
return false;
}
const valid =
payload.exp * 1000 > Date.now();
console.log(
"[AUTH CHECK]",
{
valid,
user: payload.name,
exp: new Date(
payload.exp * 1000
).toISOString()
}
);
return valid;
}
// -------------------------------
// USER INFO
// -------------------------------
function getUser() {
const token = getToken();
if (!token) {
return null;
}
return parseJwt(token);
}
// -------------------------------
// REQUIRE AUTH
// -------------------------------
function requireAuth(
redirectUrl = "/login"
) {
if (isLoggedIn()) {
return true;
}
clearToken();
const currentPath =
window.location.pathname +
window.location.search +
window.location.hash;
const separator =
redirectUrl.includes("?")
? "&"
: "?";
window.location.replace(
`${redirectUrl}${separator}redirect=${encodeURIComponent(currentPath)}`
);
return false;
}
// -------------------------------
// AUTO LOGOUT JWT
// -------------------------------
let autoLogoutTimer = null;
function scheduleAutoLogout() {
clearTimeout(
autoLogoutTimer
);
const token = getToken();
if (!token) {
return;
}
const payload =
parseJwt(token);
const expSec =
payload?.exp;
if (!expSec) {
return;
}
const timeout =
expSec * 1000 -
Date.now();
if (timeout <= 0) {
window.AppAuth.logout?.({
redirect:true
});
return;
}
autoLogoutTimer =
setTimeout(() => {
window.AppAuth.logout?.({
redirect:true
});
}, timeout);
}
// -------------------------------
// EXPORT
// -------------------------------
window.AppAuth =
Object.freeze({
login,
logout:(opts)=>
window.AppAuthLogout?.logout(opts),
isLoggedIn,
getUser,
requireAuth,
scheduleAutoLogout,
});
// -------------------------------
// INIT
// -------------------------------
function init() {
// marca questa apertura browser
sessionStorage.setItem(
"app_open",
"1"
);
if (isLoggedIn()) {
scheduleAutoLogout();
}
}
if (
document.readyState === "loading"
) {
document.addEventListener(
"DOMContentLoaded",
init
);
} else {
init();
}
// chiusura pagina/tab
window.addEventListener(
"pagehide",
() => {
sessionStorage.removeItem(
"app_open"
);
}
);
})();