67 lines
2.0 KiB
TypeScript
67 lines
2.0 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
import { authorizeAdminAccess } from "../src/lib/admin/auth-policy.ts";
|
|
import type { IdentityUser } from "../src/modules/identity/contracts.ts";
|
|
|
|
const adminAuthSource = readFileSync(
|
|
new URL("../src/lib/admin/auth.ts", import.meta.url),
|
|
"utf8",
|
|
);
|
|
|
|
function user(): IdentityUser {
|
|
return {
|
|
id: "11111111-1111-4111-8111-111111111111",
|
|
email: "admin@example.com",
|
|
emailVerified: true,
|
|
twoFactorEnabled: false,
|
|
name: "Admin",
|
|
image: null,
|
|
role: ["user"],
|
|
};
|
|
}
|
|
|
|
test("anonymous admin access is 401", () => {
|
|
assert.deepEqual(authorizeAdminAccess(null, [], "admin.access"), {
|
|
allowed: false,
|
|
status: 401,
|
|
});
|
|
});
|
|
|
|
test("missing permission is 403", () => {
|
|
assert.deepEqual(authorizeAdminAccess(user(), [], "admin.access"), {
|
|
allowed: false,
|
|
status: 403,
|
|
});
|
|
assert.deepEqual(authorizeAdminAccess(user(), ["admin.access"], "models.publish"), {
|
|
allowed: false,
|
|
status: 403,
|
|
});
|
|
});
|
|
|
|
test("database permission keys authorize only the requested operation", () => {
|
|
assert.deepEqual(authorizeAdminAccess(user(), ["admin.access"], "admin.access"), {
|
|
allowed: true,
|
|
});
|
|
assert.deepEqual(authorizeAdminAccess(user(), ["models.read", "models.publish"], "models.publish"), {
|
|
allowed: true,
|
|
});
|
|
});
|
|
|
|
|
|
test("admin session guard requires the configured admin Host before session lookup", () => {
|
|
const guard = adminAuthSource.slice(
|
|
adminAuthSource.indexOf("export async function requirePermission"),
|
|
adminAuthSource.indexOf("export function requireAdminSession"),
|
|
);
|
|
|
|
assert.match(guard, /readSelfHostedIdentityConfig\(process\.env\)/);
|
|
assert.match(guard, /resolveIdentitySurface\(adminHeaders\.get\("host"\), identityConfig\) !== "admin"/);
|
|
assert.ok(
|
|
guard.indexOf("resolveIdentitySurface") < guard.indexOf("requireIdentityServerSession"),
|
|
"Host must be rejected before Better Auth session lookup",
|
|
);
|
|
assert.doesNotMatch(guard, /x-forwarded-host|forwarded/i);
|
|
});
|