permissions.test.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* @vitest-environment node */
  2. import { describe, it, expect } from "vitest";
  3. import {
  4. canAccessBranch,
  5. filterBranchesForSession,
  6. canManageUsers,
  7. requireUserManagement,
  8. } from "./permissions.js";
  9. describe("lib/auth/permissions", () => {
  10. describe("canAccessBranch", () => {
  11. it("returns false when session is missing", () => {
  12. expect(canAccessBranch(null, "NL01")).toBe(false);
  13. });
  14. it("returns false when branchId is missing", () => {
  15. expect(canAccessBranch({ role: "admin" }, "")).toBe(false);
  16. expect(canAccessBranch({ role: "admin" }, null)).toBe(false);
  17. expect(canAccessBranch({ role: "admin" }, undefined)).toBe(false);
  18. });
  19. it("allows branch role only for its own branch", () => {
  20. const session = { role: "branch", branchId: "NL01" };
  21. expect(canAccessBranch(session, "NL01")).toBe(true);
  22. expect(canAccessBranch(session, "NL02")).toBe(false);
  23. });
  24. it("allows admin role for any branch", () => {
  25. const session = { role: "admin" };
  26. expect(canAccessBranch(session, "NL01")).toBe(true);
  27. expect(canAccessBranch(session, "NL99")).toBe(true);
  28. });
  29. it("allows superadmin role for any branch", () => {
  30. const session = { role: "superadmin" };
  31. expect(canAccessBranch(session, "NL01")).toBe(true);
  32. expect(canAccessBranch(session, "NL99")).toBe(true);
  33. });
  34. it("allows dev role for any branch", () => {
  35. const session = { role: "dev" };
  36. expect(canAccessBranch(session, "NL01")).toBe(true);
  37. expect(canAccessBranch(session, "NL99")).toBe(true);
  38. });
  39. it("denies unknown roles", () => {
  40. const session = { role: "user", branchId: "NL01" };
  41. expect(canAccessBranch(session, "NL01")).toBe(false);
  42. });
  43. });
  44. describe("filterBranchesForSession", () => {
  45. it("returns [] when session is missing", () => {
  46. expect(filterBranchesForSession(null, ["NL01", "NL02"])).toEqual([]);
  47. });
  48. it("returns [] when branchIds is not an array", () => {
  49. expect(filterBranchesForSession({ role: "admin" }, null)).toEqual([]);
  50. expect(filterBranchesForSession({ role: "admin" }, "NL01")).toEqual([]);
  51. });
  52. it("for branch role: returns only own branch (if present)", () => {
  53. const session = { role: "branch", branchId: "NL01" };
  54. expect(filterBranchesForSession(session, ["NL01", "NL02"])).toEqual([
  55. "NL01",
  56. ]);
  57. expect(filterBranchesForSession(session, ["NL02", "NL03"])).toEqual([]);
  58. });
  59. it("for admin/superadmin/dev: returns the full list", () => {
  60. const branches = ["NL01", "NL02", "NL03"];
  61. expect(filterBranchesForSession({ role: "admin" }, branches)).toEqual(
  62. branches,
  63. );
  64. expect(
  65. filterBranchesForSession({ role: "superadmin" }, branches),
  66. ).toEqual(branches);
  67. expect(filterBranchesForSession({ role: "dev" }, branches)).toEqual(
  68. branches,
  69. );
  70. });
  71. it("does not mutate the input array", () => {
  72. const branches = ["NL01", "NL02"];
  73. const copy = [...branches];
  74. filterBranchesForSession({ role: "admin" }, branches);
  75. expect(branches).toEqual(copy);
  76. });
  77. });
  78. describe("canManageUsers", () => {
  79. it("returns true for dev and superadmin", () => {
  80. expect(canManageUsers({ role: "dev" })).toBe(true);
  81. expect(canManageUsers({ role: "superadmin" })).toBe(true);
  82. });
  83. it("returns false for admin and branch", () => {
  84. expect(canManageUsers({ role: "admin" })).toBe(false);
  85. expect(canManageUsers({ role: "branch", branchId: "NL01" })).toBe(false);
  86. });
  87. it("returns false for unknown roles or missing session", () => {
  88. expect(canManageUsers({ role: "user" })).toBe(false);
  89. expect(canManageUsers(null)).toBe(false);
  90. });
  91. });
  92. describe("requireUserManagement", () => {
  93. it("does not throw for dev and superadmin", () => {
  94. expect(() => requireUserManagement({ role: "dev" })).not.toThrow();
  95. expect(() => requireUserManagement({ role: "superadmin" })).not.toThrow();
  96. });
  97. it("throws 403 AUTH_FORBIDDEN_USER_MANAGEMENT for admin", () => {
  98. try {
  99. requireUserManagement({ role: "admin" });
  100. throw new Error("Expected requireUserManagement to throw");
  101. } catch (err) {
  102. expect(err).toMatchObject({
  103. status: 403,
  104. code: "AUTH_FORBIDDEN_USER_MANAGEMENT",
  105. message: "Forbidden",
  106. });
  107. }
  108. });
  109. it("throws 403 AUTH_FORBIDDEN_USER_MANAGEMENT for branch", () => {
  110. try {
  111. requireUserManagement({ role: "branch", branchId: "NL01" });
  112. throw new Error("Expected requireUserManagement to throw");
  113. } catch (err) {
  114. expect(err).toMatchObject({
  115. status: 403,
  116. code: "AUTH_FORBIDDEN_USER_MANAGEMENT",
  117. message: "Forbidden",
  118. });
  119. }
  120. });
  121. });
  122. });