server/account-signin.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, expect, it } from "vitest";
import { allowedScopes, createEmailSignIn, parseAllowList, signInEnabled } from "./account-signin.ts";
import { startControlPlaneStub } from "./testing/control-plane-stub.ts";
describe("the sign-in allow-list", () => {
it("splits on commas, spaces and newlines and ignores case", () => {
expect(parseAllowList(" Her@Example.test, @Agentada.test\nstaff@example.test ")).toEqual(["her@example.test", "@agentada.test", "staff@example.test"]);
expect(parseAllowList(undefined)).toEqual([]);
});
it("maps addresses and @domains to scopes, and never matches a look-alike domain", () => {
const list = { admins: ["her@example.test", "@agentada.test"], members: ["staff@example.test", "@partner.test"] };
expect(allowedScopes("HER@example.test", list)).toEqual(["admin", "client"]);
expect(allowedScopes("anyone@agentada.test", list)).toEqual(["admin", "client"]);
expect(allowedScopes("staff@example.test", list)).toEqual(["client"]);
expect(allowedScopes("x@partner.test", list)).toEqual(["client"]);
expect(allowedScopes("x@evilagentada.test", list)).toBeNull();
expect(allowedScopes("x@agentada.test.evil", list)).toBeNull();
expect(allowedScopes("@agentada.test", list)).toBeNull();
expect(allowedScopes("stranger@example.test", list)).toBeNull();
expect(signInEnabled(list)).toBe(true);
expect(signInEnabled({ admins: [], members: [] })).toBe(false);
});
});
describe("the exchange with the control plane", () => {
it("sends a code only to welcome addresses, turns the right code into scopes, and explains the wrong one", async () => {
const stub = await startControlPlaneStub();
try {
const signIn = createEmailSignIn({
allow: { admins: ["her@example.test"], members: ["@team.test"] },
env: { ...process.env, OMB_CONTROL_PLANE_URL: stub.url },
});
expect(signIn.enabled()).toBe(true);
expect(await signIn.start("nobody@example.test")).toMatchObject({ ok: false, status: 403 });
expect(await signIn.start("not an email")).toMatchObject({ ok: false, status: 400 });
expect(stub.calls).not.toContain("POST /api/auth/email-otp/send-verification-otp");
expect(await signIn.start("Her@Example.test")).toEqual({ ok: true });
expect(stub.calls).toContain("POST /api/auth/email-otp/send-verification-otp");
const wrong = await signIn.verify("her@example.test", "00000000");
expect(wrong).toMatchObject({ ok: false, status: 401 });
expect(wrong.ok ? "" : wrong.error).toMatch(/wrong or has expired/);
expect(await signIn.verify("her@example.test", "12")).toMatchObject({ ok: false, status: 400 });
expect(await signIn.verify("nobody@example.test", stub.otp)).toMatchObject({ ok: false, status: 403 });
const admin = await signIn.verify("her@example.test", stub.otp);
expect(admin).toEqual({ ok: true, email: "her@example.test", userId: "user_stub", scopes: ["admin", "client"] });
const member = await signIn.verify("someone@team.test", stub.otp);
expect(member).toMatchObject({ ok: true, scopes: ["client"] });
await new Promise((r) => setTimeout(r, 50));
expect(stub.calls.filter((call) => call === "POST /api/auth/sign-out").length).toBe(2);
} finally {
await stub.close();
}
});
it("is off with an empty allow-list and says so when the sign-in service is down", async () => {
const off = createEmailSignIn({ allow: () => ({ admins: [], members: [] }) });
expect(off.enabled()).toBe(false);
const down = createEmailSignIn({ allow: { admins: ["a@b.test"], members: [] }, env: { ...process.env, OMB_CONTROL_PLANE_URL: "http://127.0.0.1:9" } });
expect(await down.start("a@b.test")).toMatchObject({ ok: false, status: 502 });
});
});