fabro/apps/arc-web/app/lib/session.server.test.ts
Bryan Helmkamp fb47745cc2 Add Tailscale authentication provider
Read Tailscale-User-Login/Name/Profile-Pic headers when web.auth.provider
is "tailscale", checking login against required allowed_usernames list.
Rename githubLogin → login across session/callback/shell for provider
neutrality. Update app-shell loader and auth-login page to handle the
new provider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:46:55 -05:00

119 lines
3.3 KiB
TypeScript

import { describe, test, expect, beforeEach, mock } from "bun:test";
// --- Mocks (must be set up before importing module under test) ---
let testAuthConfig = { provider: "github" as string, allowed_usernames: [] as string[] };
mock.module("./config.server", () => ({
getAppConfig: () => ({ web: { auth: testAuthConfig } }),
reloadAppConfig: () => {},
ARC_CONFIG_PATH: "/tmp/test.toml",
}));
let sessionData: Record<string, unknown> = {};
mock.module("./session-storage.server", () => ({
createSqliteSessionStorage: () => ({
getSession: async () => ({
get: (key: string) => sessionData[key],
}),
commitSession: async () => "",
destroySession: async () => "",
}),
}));
process.env.SESSION_SECRET = "test-secret";
const { getUser } = await import("./session.server");
// --- Tests ---
describe("getUser", () => {
beforeEach(() => {
sessionData = {};
testAuthConfig = { provider: "github", allowed_usernames: [] };
});
describe("tailscale provider", () => {
beforeEach(() => {
testAuthConfig = { provider: "tailscale", allowed_usernames: ["user@example.com"] };
});
test("returns user from headers when login is in allowed_usernames", async () => {
const request = new Request("http://localhost", {
headers: {
"Tailscale-User-Login": "user@example.com",
"Tailscale-User-Name": "Test User",
"Tailscale-User-Profile-Pic": "https://example.com/pic.jpg",
},
});
const user = await getUser(request);
expect(user).toEqual({
userUrl: "tailscale:user@example.com",
login: "user@example.com",
name: "Test User",
email: "user@example.com",
avatarUrl: "https://example.com/pic.jpg",
});
});
test("returns null when Tailscale-User-Login header is missing", async () => {
const request = new Request("http://localhost");
const user = await getUser(request);
expect(user).toBeNull();
});
test("returns null when login is not in allowed_usernames", async () => {
const request = new Request("http://localhost", {
headers: {
"Tailscale-User-Login": "stranger@example.com",
"Tailscale-User-Name": "Stranger",
},
});
const user = await getUser(request);
expect(user).toBeNull();
});
});
describe("github provider", () => {
beforeEach(() => {
testAuthConfig = { provider: "github", allowed_usernames: [] };
});
test("returns user from session", async () => {
sessionData = {
userUrl: "https://github.com/octocat",
login: "octocat",
name: "Octocat",
email: "octocat@github.com",
avatarUrl: "https://github.com/octocat.png",
};
const request = new Request("http://localhost");
const user = await getUser(request);
expect(user).toEqual({
userUrl: "https://github.com/octocat",
login: "octocat",
name: "Octocat",
email: "octocat@github.com",
avatarUrl: "https://github.com/octocat.png",
});
});
test("returns null when session is empty", async () => {
sessionData = {};
const request = new Request("http://localhost");
const user = await getUser(request);
expect(user).toBeNull();
});
});
});