From 7bf5bcae4396d9aacfe5f565dbf4627619cfa054 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 14 May 2026 20:17:23 +0800 Subject: [PATCH] Use native form login for cloud password --- public/app.js | 45 ------------------------------------ public/mobile.js | 45 ------------------------------------ test/access-password.test.js | 30 +++++++----------------- 3 files changed, 8 insertions(+), 112 deletions(-) diff --git a/public/app.js b/public/app.js index 6a9c93a..93643cd 100644 --- a/public/app.js +++ b/public/app.js @@ -1,8 +1,6 @@ const HOTNESS_AUTH_TOKEN_KEY = "video-hotness-auth-token-v1"; const authGate = document.querySelector("#auth-gate"); -const authForm = document.querySelector("#auth-form"); const authPassword = document.querySelector("#auth-password"); -const authSubmit = document.querySelector("#auth-submit"); const authMessage = document.querySelector("#auth-message"); const form = document.querySelector("#collect-form"); const input = document.querySelector("#program-name"); @@ -111,17 +109,6 @@ let resolveTimer = 0; let resolveRequestId = 0; let temporaryQueryItems = []; let appStarted = false; -let authSubmitting = false; - -authForm?.addEventListener("submit", async (event) => { - event.preventDefault(); - await submitAccessPassword(); -}); - -authSubmit?.addEventListener("click", async (event) => { - event.preventDefault(); - await submitAccessPassword(); -}); for (const [platform, element] of Object.entries(urlInputs)) { element.addEventListener("input", () => { @@ -2144,38 +2131,6 @@ async function ensureAccessAuth() { return false; } -async function submitAccessPassword() { - if (authSubmitting) return; - const password = authPassword?.value || ""; - if (!password.trim()) { - showAuthGate("请输入访问密码"); - return; - } - authSubmitting = true; - if (authSubmit) authSubmit.disabled = true; - setAuthMessage("正在验证..."); - try { - const response = await fetch("/api/auth/login", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ password }), - }); - const payload = await response.json(); - if (!response.ok) throw new Error(payload.error || "访问密码不正确"); - if (payload.token) localStorage.setItem(HOTNESS_AUTH_TOKEN_KEY, payload.token); - window.dispatchEvent(new CustomEvent("hotness:auth-updated")); - if (authPassword) authPassword.value = ""; - setAuthMessage("登录成功,正在进入..."); - hideAuthGate(); - startApp(); - } catch (error) { - showAuthGate(error.message || "访问密码不正确"); - } finally { - authSubmitting = false; - if (authSubmit) authSubmit.disabled = false; - } -} - function authHeaders() { const token = localStorage.getItem(HOTNESS_AUTH_TOKEN_KEY) || ""; return token ? { "x-hotness-auth-token": token } : {}; diff --git a/public/mobile.js b/public/mobile.js index 4a1d1a4..fec8d81 100644 --- a/public/mobile.js +++ b/public/mobile.js @@ -1,8 +1,6 @@ const HOTNESS_AUTH_TOKEN_KEY = "video-hotness-auth-token-v1"; const authGate = document.querySelector("#auth-gate"); -const authForm = document.querySelector("#auth-form"); const authPassword = document.querySelector("#auth-password"); -const authSubmit = document.querySelector("#auth-submit"); const authMessage = document.querySelector("#auth-message"); const form = document.querySelector("#collect-form"); const input = document.querySelector("#program-name"); @@ -63,17 +61,6 @@ let activeName = ""; let dirtyUrlInputs = new Set(); let deferredInstallPrompt = null; let appStarted = false; -let authSubmitting = false; - -authForm?.addEventListener("submit", async (event) => { - event.preventDefault(); - await submitAccessPassword(); -}); - -authSubmit?.addEventListener("click", async (event) => { - event.preventDefault(); - await submitAccessPassword(); -}); for (const [platform, element] of Object.entries(urlInputs)) { element.addEventListener("input", () => { @@ -740,38 +727,6 @@ async function ensureAccessAuth() { return false; } -async function submitAccessPassword() { - if (authSubmitting) return; - const password = authPassword?.value || ""; - if (!password.trim()) { - showAuthGate("请输入访问密码"); - return; - } - authSubmitting = true; - if (authSubmit) authSubmit.disabled = true; - setAuthMessage("正在验证..."); - try { - const response = await fetch(apiUrl("/api/auth/login"), { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ password }), - }); - const payload = await response.json(); - if (!response.ok) throw new Error(payload.error || "访问密码不正确"); - if (payload.token) localStorage.setItem(HOTNESS_AUTH_TOKEN_KEY, payload.token); - window.dispatchEvent(new CustomEvent("hotness:auth-updated")); - if (authPassword) authPassword.value = ""; - setAuthMessage("登录成功,正在进入..."); - hideAuthGate(); - await startApp(); - } catch (error) { - showAuthGate(error.message || "访问密码不正确"); - } finally { - authSubmitting = false; - if (authSubmit) authSubmit.disabled = false; - } -} - function authHeaders() { const token = localStorage.getItem(HOTNESS_AUTH_TOKEN_KEY) || ""; return token ? { "x-hotness-auth-token": token } : {}; diff --git a/test/access-password.test.js b/test/access-password.test.js index 3d00a55..8d4aaeb 100644 --- a/test/access-password.test.js +++ b/test/access-password.test.js @@ -36,15 +36,10 @@ test("desktop page has a password gate and sends auth token with API calls", () assert.match(desktopCss, /\.auth-gate/); }); -test("desktop login submit is bound before the rest of the app can fail", () => { - const authBinding = desktopJs.indexOf('authForm?.addEventListener("submit"'); - const authClickBinding = desktopJs.indexOf('authSubmit?.addEventListener("click"'); - const collectBinding = desktopJs.indexOf('form.addEventListener("submit"'); - assert.ok(authBinding > -1, "auth submit binding should exist"); - assert.ok(authClickBinding > -1, "auth button click binding should exist"); - assert.ok(collectBinding > -1, "collect submit binding should exist"); - assert.ok(authBinding < collectBinding, "auth binding must run before normal app bindings"); - assert.ok(authClickBinding < collectBinding, "auth click binding must run before normal app bindings"); +test("desktop login form is not blocked by JavaScript", () => { + assert.doesNotMatch(desktopJs, /authForm\?\.addEventListener\("submit"/); + assert.doesNotMatch(desktopJs, /authSubmit\?\.addEventListener\("click"/); + assert.doesNotMatch(desktopJs, /async function submitAccessPassword/); }); test("mobile page has the same password gate for cloud use", () => { @@ -60,15 +55,10 @@ test("mobile page has the same password gate for cloud use", () => { assert.match(mobileCss, /\.auth-gate/); }); -test("mobile login submit is bound before normal capture events", () => { - const authBinding = mobileJs.indexOf('authForm?.addEventListener("submit"'); - const authClickBinding = mobileJs.indexOf('authSubmit?.addEventListener("click"'); - const collectBinding = mobileJs.indexOf('form.addEventListener("submit"'); - assert.ok(authBinding > -1, "auth submit binding should exist"); - assert.ok(authClickBinding > -1, "auth button click binding should exist"); - assert.ok(collectBinding > -1, "collect submit binding should exist"); - assert.ok(authBinding < collectBinding, "auth binding must run before normal app bindings"); - assert.ok(authClickBinding < collectBinding, "auth click binding must run before normal app bindings"); +test("mobile login form is not blocked by JavaScript", () => { + assert.doesNotMatch(mobileJs, /authForm\?\.addEventListener\("submit"/); + assert.doesNotMatch(mobileJs, /authSubmit\?\.addEventListener\("click"/); + assert.doesNotMatch(mobileJs, /async function submitAccessPassword/); }); test("ranking radar requests respect the shared cloud login token", () => { @@ -78,7 +68,3 @@ test("ranking radar requests respect the shared cloud login token", () => { assert.match(rankingsJs, /requires_auth/); assert.match(rankingsJs, /hotness:auth-updated/); }); - -test("desktop login notifies secondary modules after auth succeeds", () => { - assert.match(desktopJs, /hotness:auth-updated/); -});