From a0fcc0afbbc2ab3d34ab12c9c8695a410187d1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Mon, 30 Mar 2026 12:33:10 +0200 Subject: [PATCH] test(notification): expand audience auth coverage --- .../notification-router-auth.test.ts | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/packages/api/src/__tests__/notification-router-auth.test.ts b/packages/api/src/__tests__/notification-router-auth.test.ts index e72c3b2..b5bdc44 100644 --- a/packages/api/src/__tests__/notification-router-auth.test.ts +++ b/packages/api/src/__tests__/notification-router-auth.test.ts @@ -52,6 +52,40 @@ describe("notification router authorization", () => { expect(findMany).not.toHaveBeenCalled(); }); + it("requires authentication for unread counts, reminders, and self-service deletes", async () => { + const count = vi.fn(); + const findFirst = vi.fn(); + const deleteFn = vi.fn(); + const caller = createCaller(createContext({ + notification: { + count, + findMany: vi.fn(), + findFirst, + delete: deleteFn, + }, + user: { + findUnique: vi.fn(), + }, + }, { session: false })); + + await expect(caller.unreadCount()).rejects.toMatchObject({ + code: "UNAUTHORIZED", + message: "Authentication required", + }); + await expect(caller.listReminders({ limit: 10 })).rejects.toMatchObject({ + code: "UNAUTHORIZED", + message: "Authentication required", + }); + await expect(caller.delete({ id: "notif_1" })).rejects.toMatchObject({ + code: "UNAUTHORIZED", + message: "Authentication required", + }); + + expect(count).not.toHaveBeenCalled(); + expect(findFirst).not.toHaveBeenCalled(); + expect(deleteFn).not.toHaveBeenCalled(); + }); + it("forbids regular users from creating broadcasts", async () => { const create = vi.fn(); const caller = createCaller(createContext({ @@ -71,6 +105,34 @@ describe("notification router authorization", () => { expect(create).not.toHaveBeenCalled(); }); + it("forbids regular users from reading broadcasts or creating tasks", async () => { + const findUnique = vi.fn(); + const create = vi.fn(); + const caller = createCaller(createContext({ + notificationBroadcast: { + findUnique, + }, + notification: { + create, + }, + })); + + await expect(caller.getBroadcastById({ id: "broadcast_1" })).rejects.toMatchObject({ + code: "FORBIDDEN", + message: "Manager or Admin role required", + }); + await expect(caller.createTask({ + userId: "user_2", + title: "Review proposal", + })).rejects.toMatchObject({ + code: "FORBIDDEN", + message: "Manager or Admin role required", + }); + + expect(findUnique).not.toHaveBeenCalled(); + expect(create).not.toHaveBeenCalled(); + }); + it("forbids regular users from reassigning tasks", async () => { const findUnique = vi.fn(); const caller = createCaller(createContext({ @@ -113,4 +175,31 @@ describe("notification router authorization", () => { }, }); }); + + it("allows managers to read individual broadcasts", async () => { + const findUnique = vi.fn().mockResolvedValue({ + id: "broadcast_1", + title: "Ops update", + sender: { id: "user_mgr", name: "Manager", email: "mgr@example.com" }, + }); + const caller = createCaller(createContext({ + notificationBroadcast: { + findUnique, + }, + }, { role: SystemRole.MANAGER })); + + const result = await caller.getBroadcastById({ id: "broadcast_1" }); + + expect(result).toEqual({ + id: "broadcast_1", + title: "Ops update", + sender: { id: "user_mgr", name: "Manager", email: "mgr@example.com" }, + }); + expect(findUnique).toHaveBeenCalledWith({ + where: { id: "broadcast_1" }, + include: { + sender: { select: { id: true, name: true, email: true } }, + }, + }); + }); });