120 lines
4.0 KiB
JavaScript
120 lines
4.0 KiB
JavaScript
const form = document.querySelector("#login-form");
|
|
const nextInput = document.querySelector("#next-url");
|
|
const statusEl = document.querySelector("#login-status");
|
|
const brand = document.querySelector("#login-brand");
|
|
const brandIcon = document.querySelector("#login-brand-icon");
|
|
const brandText = document.querySelector("#login-brand-text");
|
|
const sectionLink = document.querySelector("#login-section-link");
|
|
const currentNav = document.querySelector("#login-nav-current");
|
|
const kickerEl = document.querySelector("#login-kicker");
|
|
const titleEl = document.querySelector("#login-title");
|
|
const copyEl = document.querySelector("#login-copy");
|
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
const requestedNext = params.get("next") || "/software.html";
|
|
|
|
function safeNext(value) {
|
|
if (!value) return "/software.html";
|
|
if (value.startsWith("/") && !value.startsWith("//")) return value;
|
|
if (/^[a-z0-9._/-]+$/i.test(value)) return value;
|
|
return "/software.html";
|
|
}
|
|
|
|
function loginContext(nextUrl) {
|
|
const cleanNext = safeNext(nextUrl);
|
|
if (/^\/?admin\/svn(?:\.html)?(?:$|[/?#])/.test(cleanNext)) {
|
|
return {
|
|
bodyClass: "login-context-svn",
|
|
title: "SVN 管理登录",
|
|
pageTitle: "sumi.work - SVN 管理登录",
|
|
kicker: "SVN Admin Access",
|
|
copy: "登录后即可进入 SVN 控制台,管理仓库、工作副本和版本操作。",
|
|
brandText: "sumi.work SVN 管理",
|
|
brandHref: "/admin/svn.html",
|
|
brandLabel: "返回 SVN 管理",
|
|
brandIcon: "assets/icons/svn.svg",
|
|
sectionText: "SVN 管理",
|
|
sectionHref: "/admin/svn.html",
|
|
};
|
|
}
|
|
return {
|
|
bodyClass: "login-context-player",
|
|
title: "玩家登录",
|
|
pageTitle: "sumi.work - 玩家登录",
|
|
kicker: "Player Access",
|
|
copy: "登录后即可下载软件中心里的安装包。",
|
|
brandText: "sumi.work 软件中心",
|
|
brandHref: "software.html",
|
|
brandLabel: "返回软件下载",
|
|
brandIcon: "assets/icons/software.svg",
|
|
sectionText: "软件下载",
|
|
sectionHref: "software.html",
|
|
};
|
|
}
|
|
|
|
function applyLoginContext() {
|
|
const context = loginContext(requestedNext);
|
|
document.body.classList.add(context.bodyClass);
|
|
document.title = context.pageTitle;
|
|
brand.href = context.brandHref;
|
|
brand.setAttribute("aria-label", context.brandLabel);
|
|
brandIcon.src = context.brandIcon;
|
|
brandText.textContent = context.brandText;
|
|
sectionLink.href = context.sectionHref;
|
|
sectionLink.textContent = context.sectionText;
|
|
currentNav.href = `login.html?next=${encodeURIComponent(safeNext(requestedNext))}`;
|
|
currentNav.textContent = context.title;
|
|
kickerEl.textContent = context.kicker;
|
|
titleEl.textContent = context.title;
|
|
copyEl.textContent = context.copy;
|
|
}
|
|
|
|
function setStatus(message, type = "") {
|
|
statusEl.textContent = message;
|
|
statusEl.classList.toggle("is-error", type === "error");
|
|
statusEl.classList.toggle("is-ok", type === "ok");
|
|
}
|
|
|
|
async function checkExistingLogin() {
|
|
try {
|
|
const response = await fetch("/api/auth/me", { headers: { Accept: "application/json" } });
|
|
const payload = await response.json();
|
|
if (payload.authenticated) {
|
|
window.location.href = safeNext(requestedNext);
|
|
}
|
|
} catch {
|
|
setStatus("");
|
|
}
|
|
}
|
|
|
|
nextInput.value = safeNext(requestedNext);
|
|
applyLoginContext();
|
|
|
|
form.addEventListener("submit", async (event) => {
|
|
event.preventDefault();
|
|
const formData = new FormData(form);
|
|
const payload = Object.fromEntries(formData.entries());
|
|
|
|
try {
|
|
setStatus("正在登录...");
|
|
const response = await fetch("/api/auth/login", {
|
|
method: "POST",
|
|
headers: {
|
|
Accept: "application/json",
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
const data = await response.json();
|
|
if (!response.ok) {
|
|
throw new Error(data.error || "登录失败");
|
|
}
|
|
setStatus("登录成功,正在跳转。", "ok");
|
|
window.location.href = safeNext(data.next || payload.next);
|
|
} catch (error) {
|
|
setStatus(error.message, "error");
|
|
}
|
|
});
|
|
|
|
checkExistingLogin();
|