83 lines
3.3 KiB
TypeScript
83 lines
3.3 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { hasAdminSessionAccess, hasSuperAdminAccess } from "@/lib/auth/permissions";
|
|
import type { AuthSession } from "@/lib/auth/session";
|
|
|
|
type FixtureCase = {
|
|
name: string;
|
|
state: { required: boolean; configured: boolean };
|
|
requirement: "app" | "admin" | "super_admin";
|
|
resolverOutcome: "not_called" | "unauthenticated" | "authenticated" | "infrastructure_error";
|
|
session?: { authMode: "user" | "admin"; role: "user" | "organization_admin" | "super_admin" };
|
|
expected: { outcome: string; status: number; role?: string; authMode?: string };
|
|
};
|
|
|
|
type Fixture = { version: 1; cookieName: string; cases: FixtureCase[] };
|
|
|
|
const fixtureUrl = new URL("../contracts/auth/platform-http-auth-v1.json", import.meta.url);
|
|
|
|
describe("platform HTTP authorization v1 contract", () => {
|
|
it("freezes the current configuration fallback and error categories", async () => {
|
|
const fixture = JSON.parse(await readFile(fixtureUrl, "utf8")) as Fixture;
|
|
expect(fixture.version).toBe(1);
|
|
expect(fixture.cookieName).toBe("zhinian_session");
|
|
|
|
for (const contractCase of fixture.cases) {
|
|
expect(evaluateConfiguration(contractCase), contractCase.name).toEqual(contractCase.expected);
|
|
}
|
|
});
|
|
|
|
it("uses the current role and auth-mode permission helpers", async () => {
|
|
const fixture = JSON.parse(await readFile(fixtureUrl, "utf8")) as Fixture;
|
|
for (const contractCase of fixture.cases.filter((item) => item.session)) {
|
|
const session = fixtureSession(contractCase.session!);
|
|
const allowed = contractCase.requirement === "app"
|
|
? true
|
|
: contractCase.requirement === "admin"
|
|
? hasAdminSessionAccess(session)
|
|
: hasSuperAdminAccess(session.user);
|
|
expect(allowed, contractCase.name).toBe(contractCase.expected.outcome === "authenticated");
|
|
}
|
|
});
|
|
});
|
|
|
|
function evaluateConfiguration(contractCase: FixtureCase): FixtureCase["expected"] {
|
|
if (contractCase.resolverOutcome === "infrastructure_error") {
|
|
return { outcome: "infrastructure_error", status: 500 };
|
|
}
|
|
if (contractCase.resolverOutcome === "authenticated") {
|
|
const session = fixtureSession(contractCase.session!);
|
|
const allowed = contractCase.requirement === "app"
|
|
|| (contractCase.requirement === "admin" && hasAdminSessionAccess(session))
|
|
|| (contractCase.requirement === "super_admin" && hasSuperAdminAccess(session.user));
|
|
return allowed
|
|
? { outcome: "authenticated", status: 200, role: session.user.role, authMode: session.authMode }
|
|
: { outcome: "forbidden", status: 403 };
|
|
}
|
|
if (!contractCase.state.required) {
|
|
return { outcome: "authenticated", status: 200, role: "super_admin", authMode: "admin" };
|
|
}
|
|
if (!contractCase.state.configured) return { outcome: "configuration_error", status: 503 };
|
|
return { outcome: "unauthenticated", status: 401 };
|
|
}
|
|
|
|
function fixtureSession(input: NonNullable<FixtureCase["session"]>): AuthSession {
|
|
return {
|
|
version: 1,
|
|
authMode: input.authMode,
|
|
issuedAt: 100,
|
|
expiresAt: 200,
|
|
user: {
|
|
id: "fixture-user",
|
|
subject: "fixture-user",
|
|
displayName: "Fixture User",
|
|
clientId: "platform",
|
|
role: input.role,
|
|
authorities: [],
|
|
scope: [],
|
|
},
|
|
};
|
|
}
|