feat: add database-refreshed identity authorization

This commit is contained in:
zn-admin committed 2026-08-13 11:56:36 +08:00
1 parent 716a8031b1
commit c849077591
12 files changed
+1809 -15

No files matched your search

@@ -0,0 +1,174 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const { backend, getPlatformOrganization, getPlatformUserById, queryDatabase } = vi.hoisted(() => ({
backend: { postgres: true },
getPlatformOrganization: vi.fn(),
getPlatformUserById: vi.fn(),
queryDatabase: vi.fn()
}));
vi.mock("@/lib/server/database", () => ({
isPostgresBackend: () => backend.postgres,
queryDatabase
}));
vi.mock("@/lib/server/account-store", () => ({
getPlatformOrganization,
getPlatformUserById
}));
import { loadPlatformAuthorizationSnapshot } from "@/lib/server/auth/platform-authorization-store";
const AUTHORIZATION_SQL = `SELECT
users.id AS account_id,
users.phone AS account_phone,
users.display_name AS account_display_name,
users.role AS account_role,
users.organization_id AS account_organization_id,
users.status AS account_status,
users.session_version AS account_session_version,
organizations.id AS organization_id,
organizations.name AS organization_name,
organizations.status AS organization_status
FROM public.platform_users AS users
LEFT JOIN public.platform_organizations AS organizations
ON organizations.id = users.organization_id
WHERE users.id = $1`;
describe("platform authorization snapshot store", () => {
beforeEach(() => {
backend.postgres = true;
queryDatabase.mockReset();
getPlatformUserById.mockReset();
getPlatformOrganization.mockReset();
});
it("loads a complete PostgreSQL authorization snapshot with one explicit parameterized join", async () => {
queryDatabase.mockResolvedValueOnce({
rows: [{
account_id: "account-1",
account_phone: "13800138000",
account_display_name: "Ada",
account_role: "organization_admin",
account_organization_id: "org-1",
account_status: "disabled",
account_session_version: 7,
organization_id: "org-1",
organization_name: "Research",
organization_status: "disabled"
}]
});
await expect(loadPlatformAuthorizationSnapshot("account-1")).resolves.toEqual({
account: {
id: "account-1",
phone: "13800138000",
displayName: "Ada",
role: "organization_admin",
organizationId: "org-1",
status: "disabled",
sessionVersion: 7
},
organization: { id: "org-1", name: "Research", status: "disabled" }
});
expect(queryDatabase).toHaveBeenCalledTimes(1);
expect(queryDatabase).toHaveBeenCalledWith(AUTHORIZATION_SQL, ["account-1"]);
expect(AUTHORIZATION_SQL).not.toMatch(/password|SELECT\s+\*/i);
expect(getPlatformUserById).not.toHaveBeenCalled();
});
it("projects disabled local accounts without exposing password storage fields", async () => {
backend.postgres = false;
getPlatformUserById.mockResolvedValueOnce({
id: "account-disabled",
phone: "13900139000",
displayName: "Grace",
role: "user",
organizationId: "org-disabled",
status: "disabled",
sessionVersion: 3,
passwordHash: "secret-hash",
passwordSalt: "secret-salt",
failedLoginCount: 4,
createdAt: "2026-08-13T00:00:00.000Z",
updatedAt: "2026-08-13T00:00:00.000Z"
});
getPlatformOrganization.mockResolvedValueOnce({
id: "org-disabled",
name: "Archived",
status: "disabled",
archiveOwnerId: "archive:org-disabled",
createdAt: "2026-08-13T00:00:00.000Z",
updatedAt: "2026-08-13T00:00:00.000Z"
});
await expect(loadPlatformAuthorizationSnapshot("account-disabled")).resolves.toEqual({
account: {
id: "account-disabled",
phone: "13900139000",
displayName: "Grace",
role: "user",
organizationId: "org-disabled",
status: "disabled",
sessionVersion: 3
},
organization: { id: "org-disabled", name: "Archived", status: "disabled" }
});
expect(getPlatformUserById).toHaveBeenCalledWith("account-disabled", { includeDisabled: true });
expect(getPlatformOrganization).toHaveBeenCalledWith("org-disabled");
expect(queryDatabase).not.toHaveBeenCalled();
});
it("maps a PostgreSQL account with no joined organization", async () => {
queryDatabase.mockResolvedValueOnce({
rows: [{
account_id: "super-1",
account_phone: "13700137000",
account_display_name: "Lin",
account_role: "super_admin",
account_organization_id: null,
account_status: "active",
account_session_version: 11,
organization_id: null,
organization_name: null,
organization_status: null
}]
});
await expect(loadPlatformAuthorizationSnapshot("super-1")).resolves.toEqual({
account: {
id: "super-1",
phone: "13700137000",
displayName: "Lin",
role: "super_admin",
organizationId: undefined,
status: "active",
sessionVersion: 11
},
organization: null
});
});
it("returns null when PostgreSQL has no matching account", async () => {
queryDatabase.mockResolvedValueOnce({ rows: [] });
await expect(loadPlatformAuthorizationSnapshot("missing")).resolves.toBeNull();
expect(queryDatabase).toHaveBeenCalledWith(AUTHORIZATION_SQL, ["missing"]);
});
it("propagates PostgreSQL query errors", async () => {
const failure = new Error("database unavailable");
queryDatabase.mockRejectedValueOnce(failure);
await expect(loadPlatformAuthorizationSnapshot("account-1")).rejects.toBe(failure);
});
it("returns null for a missing local account without loading an organization", async () => {
backend.postgres = false;
getPlatformUserById.mockResolvedValueOnce(null);
await expect(loadPlatformAuthorizationSnapshot("missing")).resolves.toBeNull();
expect(getPlatformUserById).toHaveBeenCalledWith("missing", { includeDisabled: true });
expect(getPlatformOrganization).not.toHaveBeenCalled();
});
});
@@ -0,0 +1,84 @@
import { readFile } from "node:fs/promises";
import { describe, expect, it, vi } from "vitest";
import type { AuthSession } from "@/lib/auth/session";
import {
authorizePlatformSession,
type PlatformAuthorizationSnapshot,
} from "@/lib/server/auth/platform-session";
type ContractCase = {
name: string;
session: AuthSession;
snapshot: PlatformAuthorizationSnapshot | null;
expected:
| { outcome: "authenticated"; loaderCalls: number; session: AuthSession }
| { outcome: "unauthenticated"; loaderCalls: number; reason: string };
};
type ContractFixture = {
version: 1;
requiredClientId: string;
cases: ContractCase[];
};
const fixtureUrl = new URL("../contracts/auth/platform-session-authorization-v1.json", import.meta.url);
async function loadFixture(): Promise<ContractFixture> {
return JSON.parse(await readFile(fixtureUrl, "utf8")) as ContractFixture;
}
describe("platform session authorization v1 cross-language contract", () => {
it("refreshes an active user's forged Cookie claims from the database", async () => {
const fixture = await loadFixture();
const contractCase = fixture.cases[0];
const loader = vi.fn(async () => contractCase.snapshot);
const result = await authorizePlatformSession(
contractCase.session,
loader,
fixture.requiredClientId,
);
expect(result).toEqual(contractCase.expected.outcome === "authenticated"
? { outcome: "authenticated", session: contractCase.expected.session }
: { outcome: "unauthenticated", reason: contractCase.expected.reason });
expect(loader).toHaveBeenCalledTimes(contractCase.expected.loaderCalls);
});
it("matches every remaining authorization and rejection case", async () => {
const fixture = await loadFixture();
for (const contractCase of fixture.cases.slice(1)) {
const loader = vi.fn(async () => contractCase.snapshot);
const result = await authorizePlatformSession(
contractCase.session,
loader,
fixture.requiredClientId,
);
expect(result, contractCase.name).toEqual(contractCase.expected.outcome === "authenticated"
? { outcome: "authenticated", session: contractCase.expected.session }
: { outcome: "unauthenticated", reason: contractCase.expected.reason });
expect(loader, contractCase.name).toHaveBeenCalledTimes(contractCase.expected.loaderCalls);
if (contractCase.expected.loaderCalls > 0) {
expect(loader, contractCase.name).toHaveBeenCalledWith(contractCase.session.user.id);
}
}
});
it("rejects a mismatched joined organization instead of trusting its display claims", async () => {
const fixture = await loadFixture();
const contractCase = fixture.cases[0];
const snapshot = structuredClone(contractCase.snapshot);
if (!snapshot?.organization) throw new Error("fixture requires organization");
snapshot.organization.id = "org-other";
await expect(authorizePlatformSession(
contractCase.session,
async () => snapshot,
fixture.requiredClientId,
)).resolves.toEqual({ outcome: "unauthenticated", reason: "organization_not_active" });
});
});