test(api): cover shared resource access rules
This commit is contained in:
@@ -136,7 +136,7 @@ describe("resource router authorization", () => {
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(findUnique).toHaveBeenCalledWith({
|
||||
where: { email: "user@example.com" },
|
||||
where: { id: "user_1" },
|
||||
select: {
|
||||
resource: {
|
||||
select: {
|
||||
@@ -172,4 +172,149 @@ describe("resource router authorization", () => {
|
||||
expect(getAnonymizationDirectory).toHaveBeenCalledOnce();
|
||||
expect(anonymizeResource).toHaveBeenCalledWith(resource, null);
|
||||
});
|
||||
|
||||
it("uses the db user id for self-service resource lookups even when the session email is stale", async () => {
|
||||
const findUnique = vi.fn().mockResolvedValue({ resource: null });
|
||||
const caller = createCaller({
|
||||
session: {
|
||||
user: { email: "stale@example.com", name: "User", image: null },
|
||||
expires: "2099-01-01T00:00:00.000Z",
|
||||
},
|
||||
db: {
|
||||
user: {
|
||||
findUnique,
|
||||
},
|
||||
} as never,
|
||||
dbUser: {
|
||||
id: "user_1",
|
||||
systemRole: SystemRole.USER,
|
||||
permissionOverrides: null,
|
||||
},
|
||||
roleDefaults: null,
|
||||
});
|
||||
|
||||
await caller.getMyResource();
|
||||
|
||||
expect(findUnique).toHaveBeenCalledWith({
|
||||
where: { id: "user_1" },
|
||||
select: {
|
||||
resource: {
|
||||
select: {
|
||||
id: true,
|
||||
displayName: true,
|
||||
eid: true,
|
||||
chapter: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("requires authentication for hover-card lookups", async () => {
|
||||
const findUnique = vi.fn();
|
||||
const caller = createCaller(createContext({
|
||||
resource: {
|
||||
findUnique,
|
||||
},
|
||||
}, { session: false }));
|
||||
|
||||
await expect(caller.getHoverCard({ id: "res_1" })).rejects.toMatchObject({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
});
|
||||
|
||||
expect(findUnique).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("blocks regular users from manager-only skill imports for arbitrary resources", async () => {
|
||||
const findUnique = vi.fn();
|
||||
const update = vi.fn();
|
||||
const caller = createCaller(createContext({
|
||||
resource: {
|
||||
findUnique,
|
||||
update,
|
||||
},
|
||||
}));
|
||||
|
||||
await expect(
|
||||
caller.importSkillMatrixForResource({
|
||||
resourceId: "res_1",
|
||||
skills: [{ skill: "Houdini", proficiency: 5 }],
|
||||
}),
|
||||
).rejects.toMatchObject({
|
||||
code: "FORBIDDEN",
|
||||
});
|
||||
|
||||
expect(findUnique).not.toHaveBeenCalled();
|
||||
expect(update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("requires authentication for manager-only skill imports for arbitrary resources", async () => {
|
||||
const findUnique = vi.fn();
|
||||
const update = vi.fn();
|
||||
const caller = createCaller(createContext({
|
||||
resource: {
|
||||
findUnique,
|
||||
update,
|
||||
},
|
||||
}, { role: SystemRole.MANAGER, session: false }));
|
||||
|
||||
await expect(
|
||||
caller.importSkillMatrixForResource({
|
||||
resourceId: "res_1",
|
||||
skills: [{ skill: "Houdini", proficiency: 5 }],
|
||||
}),
|
||||
).rejects.toMatchObject({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
});
|
||||
|
||||
expect(findUnique).not.toHaveBeenCalled();
|
||||
expect(update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("blocks non-admin users from batch skill matrix imports", async () => {
|
||||
const findMany = vi.fn();
|
||||
const transaction = vi.fn();
|
||||
const caller = createCaller(createContext({
|
||||
resource: {
|
||||
findMany,
|
||||
},
|
||||
$transaction: transaction,
|
||||
}, { role: SystemRole.MANAGER }));
|
||||
|
||||
await expect(
|
||||
caller.batchImportSkillMatrices({
|
||||
entries: [{ eid: "E-001", skills: [{ skill: "Maya", proficiency: 4 }] }],
|
||||
}),
|
||||
).rejects.toMatchObject({
|
||||
code: "FORBIDDEN",
|
||||
});
|
||||
|
||||
expect(findMany).not.toHaveBeenCalled();
|
||||
expect(transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("requires authentication for admin-only batch skill matrix imports", async () => {
|
||||
const findMany = vi.fn();
|
||||
const transaction = vi.fn();
|
||||
const caller = createCaller(createContext({
|
||||
resource: {
|
||||
findMany,
|
||||
},
|
||||
$transaction: transaction,
|
||||
}, { role: SystemRole.ADMIN, session: false }));
|
||||
|
||||
await expect(
|
||||
caller.batchImportSkillMatrices({
|
||||
entries: [{ eid: "E-001", skills: [{ skill: "Maya", proficiency: 4 }] }],
|
||||
}),
|
||||
).rejects.toMatchObject({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "Authentication required",
|
||||
});
|
||||
|
||||
expect(findMany).not.toHaveBeenCalled();
|
||||
expect(transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user