175 lines
5.8 KiB
TypeScript
175 lines
5.8 KiB
TypeScript
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();
|
|
});
|
|
});
|