refactor(api): share owned resource read access

This commit is contained in:
2026-04-01 07:35:34 +02:00
parent a0c98cf24d
commit 41916a4e46
7 changed files with 336 additions and 118 deletions
@@ -0,0 +1,80 @@
import { describe, expect, it, vi } from "vitest";
import {
assertCanReadOwnedResource,
canManageOwnedResourceReads,
findOwnedReadResourceId,
resolveOwnedResourceReadFilter,
} from "../router/resource-owned-read-access.js";
function createContext(options: {
role?: string | null;
userId?: string | null;
resourceFindFirst?: ReturnType<typeof vi.fn>;
} = {}) {
return {
dbUser: options.userId === null
? null
: {
id: options.userId ?? "user_1",
systemRole: options.role ?? "USER",
},
db: {
resource: options.resourceFindFirst
? { findFirst: options.resourceFindFirst }
: {
findFirst: vi.fn().mockResolvedValue({ id: "res_own" }),
},
},
};
}
describe("resource-owned-read-access", () => {
it("treats admins and managers as broad readers", () => {
expect(canManageOwnedResourceReads(createContext({ role: "ADMIN" }))).toBe(true);
expect(canManageOwnedResourceReads(createContext({ role: "MANAGER" }))).toBe(true);
expect(canManageOwnedResourceReads(createContext({ role: "USER" }))).toBe(false);
});
it("finds the signed-in user's owned resource id", async () => {
const resourceFindFirst = vi.fn().mockResolvedValue({ id: "res_123" });
await expect(findOwnedReadResourceId(createContext({ resourceFindFirst }))).resolves.toBe("res_123");
expect(resourceFindFirst).toHaveBeenCalledWith({
where: { userId: "user_1" },
select: { id: true },
});
});
it("scopes regular readers to their own resource filter", async () => {
await expect(
resolveOwnedResourceReadFilter(
createContext({ role: "USER" }),
undefined,
"forbidden",
),
).resolves.toBe("res_own");
});
it("preserves the requested filter for managers", async () => {
await expect(
resolveOwnedResourceReadFilter(
createContext({ role: "MANAGER" }),
"res_other",
"forbidden",
),
).resolves.toBe("res_other");
});
it("rejects access to another resource for regular readers", async () => {
await expect(
assertCanReadOwnedResource(
createContext({ role: "USER" }),
"res_other",
"forbidden",
),
).rejects.toMatchObject({
code: "FORBIDDEN",
message: "forbidden",
});
});
});