From b0d6c15e633ee6fc5f05b2ff55af066721a0a10c Mon Sep 17 00:00:00 2001 From: Kfir Amar Date: Sun, 15 Mar 2026 02:06:49 +0200 Subject: [PATCH] fix(auth): harden login bootstrap checks Stabilize the bootstrap metadata test by clearing INITIAL_PASSWORD before each run and add focused coverage for env-backed and stored-password states. Log settings lookup failures before returning the bootstrap-safe fallback payload so operational errors are still visible on the server side. --- src/app/api/settings/require-login/route.ts | 1 + tests/unit/login-bootstrap-route.test.mjs | 45 ++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/app/api/settings/require-login/route.ts b/src/app/api/settings/require-login/route.ts index 93415c72d2..547ac96859 100644 --- a/src/app/api/settings/require-login/route.ts +++ b/src/app/api/settings/require-login/route.ts @@ -12,6 +12,7 @@ export async function GET() { const setupComplete = !!settings.setupComplete; return NextResponse.json({ requireLogin, hasPassword, setupComplete }); } catch (error) { + console.error("[API] Error fetching require-login settings:", error); return NextResponse.json( { requireLogin: true, hasPassword: true, setupComplete: true }, { status: 200 } diff --git a/tests/unit/login-bootstrap-route.test.mjs b/tests/unit/login-bootstrap-route.test.mjs index f4fbdd55f5..fc56cbd2ab 100644 --- a/tests/unit/login-bootstrap-route.test.mjs +++ b/tests/unit/login-bootstrap-route.test.mjs @@ -17,14 +17,18 @@ async function resetStorage() { fs.mkdirSync(TEST_DATA_DIR, { recursive: true }); } +test.beforeEach(async () => { + delete process.env.INITIAL_PASSWORD; + await resetStorage(); +}); + test.after(() => { + delete process.env.INITIAL_PASSWORD; core.resetDbInstance(); fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true }); }); test("public login bootstrap route exposes the metadata the login page consumes", async () => { - await resetStorage(); - await settingsDb.updateSettings({ requireLogin: true, setupComplete: true, @@ -40,3 +44,40 @@ test("public login bootstrap route exposes the metadata the login page consumes" setupComplete: true, }); }); + +test("public login bootstrap route reports env-provided bootstrap password metadata", async () => { + process.env.INITIAL_PASSWORD = "bootstrap-secret"; + + await settingsDb.updateSettings({ + requireLogin: true, + setupComplete: true, + }); + + const response = await route.GET(); + const body = await response.json(); + + assert.equal(response.status, 200); + assert.deepEqual(body, { + requireLogin: true, + hasPassword: true, + setupComplete: true, + }); +}); + +test("public login bootstrap route reports stored password metadata and disabled auth state", async () => { + await settingsDb.updateSettings({ + requireLogin: false, + password: "hashed-password", + setupComplete: true, + }); + + const response = await route.GET(); + const body = await response.json(); + + assert.equal(response.status, 200); + assert.deepEqual(body, { + requireLogin: false, + hasPassword: true, + setupComplete: true, + }); +});