import test from "node:test"; import assert from "node:assert/strict"; import { createHttpServer } from "../src/app/http.ts"; import { createStore } from "../src/store.ts"; test("ordinary-user registration and login work with verification enhancements disabled", async () => { const server = createHttpServer(createStore(), { host: "127.0.0.1", port: 0, accessTokenSecret: "account-policy-test-secret", accessTokenTtlSeconds: 900, refreshCookieName: "refresh", adminEmail: "admin@example.com", adminPassword: "change-me-now", adminMfaRequired: false, userMfaRequired: false, userVerificationRequired: false, captchaRequired: false }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); try { const address = server.address(); assert.ok(address && typeof address !== "string"); const base = `http://127.0.0.1:${address.port}`; const policy = await fetch(`${base}/api/v1/auth/policy`); assert.deepEqual((await policy.json() as { data: unknown }).data, { captchaRequired: false, userVerificationRequired: false, userMfaRequired: false }); const register = await fetch(`${base}/api/v1/auth/register`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "policy-off@example.com", password: "password123" }) }); const registered = await register.json() as { data: { userId: string; verificationRequired: boolean } }; assert.equal(register.status, 201); assert.equal(registered.data.verificationRequired, false); const login = await fetch(`${base}/api/v1/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "policy-off@example.com", password: "password123" }) }); const session = await login.json() as { data: { accessToken?: string; mfaRequired?: boolean } }; assert.equal(login.status, 200); assert.ok(session.data.accessToken); assert.equal(session.data.mfaRequired, false); } finally { await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve())); } }); test("authenticated password change revokes other sessions and close anonymizes asynchronously", async () => { const store = createStore(); const server = createHttpServer(store, { host: "127.0.0.1", port: 0, accessTokenSecret: "account-security-test-secret", accessTokenTtlSeconds: 900, refreshCookieName: "refresh", adminEmail: "admin@example.com", adminPassword: "change-me-now", adminMfaRequired: false, userMfaRequired: false, captchaRequired: false }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); try { const address = server.address(); assert.ok(address && typeof address !== "string"); const base = `http://127.0.0.1:${address.port}`; const register = await fetch(`${base}/api/v1/auth/register`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "account-security@example.com", password: "old-password-123" }) }); const registered = await register.json() as { data: { userId: string; devVerificationCode: string } }; await fetch(`${base}/api/v1/auth/verify-email`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ userId: registered.data.userId, code: registered.data.devVerificationCode }) }); const firstLogin = await fetch(`${base}/api/v1/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "account-security@example.com", password: "old-password-123" }) }); const firstPayload = await firstLogin.json() as { data: { accessToken: string } }; assert.ok(firstPayload.data.accessToken); const secondLogin = await fetch(`${base}/api/v1/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "account-security@example.com", password: "old-password-123" }) }); const secondPayload = await secondLogin.json() as { data: { accessToken: string } }; assert.ok(secondPayload.data.accessToken); const changed = await fetch(`${base}/api/v1/auth/password/change`, { method: "POST", headers: { Authorization: `Bearer ${firstPayload.data.accessToken}`, "content-type": "application/json" }, body: JSON.stringify({ currentPassword: "old-password-123", newPassword: "new-password-456" }) }); assert.equal(changed.status, 200); const oldSession = await fetch(`${base}/api/v1/me`, { headers: { Authorization: `Bearer ${secondPayload.data.accessToken}` } }); assert.equal(oldSession.status, 401); const newLogin = await fetch(`${base}/api/v1/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email: "account-security@example.com", password: "new-password-456" }) }); const newPayload = await newLogin.json() as { data: { accessToken: string } }; assert.ok(newPayload.data.accessToken); const closed = await fetch(`${base}/api/v1/me/close`, { method: "POST", headers: { Authorization: `Bearer ${newPayload.data.accessToken}` } }); assert.equal(closed.status, 200); await new Promise((resolve) => setTimeout(resolve, 10)); assert.equal(store.users.get(registered.data.userId)?.status, "closing"); assert.equal(store.users.get(registered.data.userId)?.email, undefined); } finally { await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve())); } });