42 lines
5.3 KiB
TypeScript
42 lines
5.3 KiB
TypeScript
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<void>((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<void>((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<void>((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<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve())); }
|
|
});
|