2697d16ef1
- IDENTITY_TEST_OTP env: when set to a 6-digit code, no real email is delivered; login page surfaces the fixed code so testers can register and sign in without a mailbox. Opt-in, never set in production. - email-otp-login: test-channel notice with the pinned code. - Rectification candidate list restyled with the project design system (warm canvas, action color, display serif, soft shadow, hover lift). - Regression tests for config parsing, pinned OTP generation, login UI notice, and candidate card styles.
76 lines
3.4 KiB
TypeScript
76 lines
3.4 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import type { SelfHostedIdentityConfig } from "../src/modules/identity/config.ts";
|
|
import { createHostIsolatedAuthHandlers, resolveIdentitySurface } from "../src/modules/identity/host.ts";
|
|
|
|
const config: SelfHostedIdentityConfig = {
|
|
provider: "self-hosted",
|
|
databaseUrl: "postgresql://identity_runtime:test@postgres:5432/jyotisha",
|
|
userOrigin: "https://staging.jyotisha.chat",
|
|
adminOrigin: "https://admin.staging.jyotisha.chat",
|
|
userSecret: "user-secret-that-is-at-least-32-bytes-long",
|
|
resendApiKey: "re_test",
|
|
resendFrom: "Jyotisha <login@staging.jyotisha.chat>",
|
|
testOtp: null,
|
|
};
|
|
|
|
test("identity host accepts only the two configured origins", () => {
|
|
assert.equal(resolveIdentitySurface("staging.jyotisha.chat", config), "user");
|
|
assert.equal(resolveIdentitySurface("STAGING.JYOTISHA.CHAT:443", config), "user");
|
|
assert.equal(resolveIdentitySurface("admin.staging.jyotisha.chat", config), "admin");
|
|
assert.equal(resolveIdentitySurface("ADMIN.STAGING.JYOTISHA.CHAT:443", config), "admin");
|
|
for (const host of [
|
|
null,
|
|
"",
|
|
"evil.staging.jyotisha.chat",
|
|
"staging.jyotisha.chat.evil.example",
|
|
"staging.jyotisha.chat,evil.example",
|
|
"admin.staging.jyotisha.chat:444",
|
|
"admin.staging.jyotisha.chat.",
|
|
]) {
|
|
assert.equal(resolveIdentitySurface(host, config), null);
|
|
}
|
|
});
|
|
|
|
test("auth route dispatches only to the user service", async () => {
|
|
let calls = 0;
|
|
const handlers = createHostIsolatedAuthHandlers(config, { user: { GET: async () => { calls += 1; return new Response("user"); }, POST: async () => { calls += 1; return new Response("user"); } } });
|
|
const response = await handlers.GET(new Request("https://internal/api/auth/get-session", { headers: { host: "staging.jyotisha.chat" } }));
|
|
assert.equal(await response.text(), "user");
|
|
assert.equal(calls, 1);
|
|
});
|
|
|
|
test("unknown hosts remain fail-closed with 421", async () => {
|
|
let calls = 0;
|
|
const handler = async () => { calls += 1; return new Response("unexpected"); };
|
|
const handlers = createHostIsolatedAuthHandlers(config, { user: { GET: handler, POST: handler } });
|
|
const response = await handlers.GET(new Request("https://internal/api/auth/get-session", { headers: { host: "unknown.example" } }));
|
|
assert.equal(response.status, 421);
|
|
assert.equal(calls, 0);
|
|
});
|
|
|
|
test("main auth surface keeps Better Auth admin endpoints closed", async () => {
|
|
let calls = 0;
|
|
const handler = async () => { calls += 1; return new Response("unexpected"); };
|
|
const handlers = createHostIsolatedAuthHandlers(config, { user: { GET: handler, POST: handler } });
|
|
const response = await handlers.POST(new Request("https://internal/api/auth/admin/set-role", {
|
|
method: "POST",
|
|
headers: {
|
|
host: "staging.jyotisha.chat",
|
|
"x-forwarded-host": "admin.staging.jyotisha.chat",
|
|
},
|
|
}));
|
|
assert.equal(response.status, 404);
|
|
assert.equal(calls, 0);
|
|
});
|
|
|
|
test("admin auth surface reaches the same Better Auth service", async () => {
|
|
let calls = 0;
|
|
const handler = async () => { calls += 1; return new Response("admin-host"); };
|
|
const handlers = createHostIsolatedAuthHandlers(config, { user: { GET: handler, POST: handler } });
|
|
const response = await handlers.POST(new Request("https://internal/api/auth/admin/set-role", { method: "POST", headers: { host: "admin.staging.jyotisha.chat" } }));
|
|
assert.equal(response.status, 200);
|
|
assert.equal(await response.text(), "admin-host");
|
|
assert.equal(calls, 1);
|
|
});
|