import { afterEach, describe, expect, it } from "vitest"; import { adminClient, createBareAuthUser, createHrUser, deleteTestUser, signInAs, type TestUser, } from "./helpers"; // HR-only access model (supabase/migrations/20260714120000_hr_only_access.sql): // nobody except an active, explicitly-provisioned HR user may read or write // anything beyond their own profile row. describe("HR-only access (is_hr_user gate)", () => { const createdUsers: TestUser[] = []; afterEach(async () => { while (createdUsers.length) { const user = createdUsers.pop()!; await deleteTestUser(user); } }); it("a bare authenticated user (no profile row) reads zero employees, not an error", async () => { const user = await createBareAuthUser(); createdUsers.push(user); const client = await signInAs(user); const { data, error } = await client.from("employees").select("id"); expect(error).toBeNull(); expect(data).toEqual([]); }); it("a bare authenticated user cannot insert into org reference tables", async () => { const user = await createBareAuthUser(); createdUsers.push(user); const client = await signInAs(user); const { error } = await client .from("org_units") .insert({ org_number: "20999999", name: `Test-${user.id}`, unit_type: "Bereich" }); expect(error).not.toBeNull(); }); it("an inactive HR profile can read its own profile row", async () => { const user = await createHrUser({ active: false }); createdUsers.push(user); const client = await signInAs(user); const { data, error } = await client.from("profiles").select("id, is_active").eq("id", user.id); expect(error).toBeNull(); expect(data).toHaveLength(1); expect(data?.[0].is_active).toBe(false); }); it("an inactive HR profile reads zero employees and cannot call mutation RPCs", async () => { const user = await createHrUser({ active: false }); createdUsers.push(user); const client = await signInAs(user); const { data: employees, error: readError } = await client.from("employees").select("id"); expect(readError).toBeNull(); expect(employees).toEqual([]); const { error: rpcError } = await client.rpc("hire_employee", { payload: { first_name: "X", last_name: "Y", gender: "m", birth_date: "1990-01-01", entry_date: "2020-01-01" }, }); expect(rpcError?.message).toMatch(/Nicht berechtigt/); }); it("an active HR user reads the seeded employee roster", async () => { const user = await createHrUser({ active: true }); createdUsers.push(user); const client = await signInAs(user); const { data, error } = await client.from("employees").select("id").limit(1); expect(error).toBeNull(); expect((data ?? []).length).toBeGreaterThan(0); }); it("apply_due_pending_changes is revoked from authenticated users, even active HR", async () => { const user = await createHrUser({ active: true }); createdUsers.push(user); const client = await signInAs(user); const { error } = await client.rpc("apply_due_pending_changes"); expect(error).not.toBeNull(); }); it("apply_due_pending_changes is callable by the service-role client", async () => { const { data, error } = await adminClient.rpc("apply_due_pending_changes"); expect(error).toBeNull(); expect(typeof data).toBe("number"); }); });