branchUiDecision.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import {
  2. getBranchAccess,
  3. BRANCH_ACCESS,
  4. } from "@/lib/frontend/rbac/branchAccess";
  5. import { isAdminLike as isAdminLikeRole } from "@/lib/frontend/auth/roles";
  6. export const BRANCH_UI_DECISION = Object.freeze({
  7. ALLOWED: "allowed",
  8. FORBIDDEN: "forbidden",
  9. NOT_FOUND: "not-found",
  10. });
  11. /**
  12. * Decide which UI outcome should be shown for a branch route.
  13. *
  14. * Notes:
  15. * - This function assumes the user is authenticated (handled by AuthProvider).
  16. * - For admin-like roles we can optionally validate branch existence using `allowedBranches`
  17. * from GET /api/branches. If the list is not available, we fail open.
  18. *
  19. * @param {{
  20. * user: { userId: string, role: string, branchId: string|null },
  21. * branch: string,
  22. * allowedBranches?: string[]|null
  23. * }} input
  24. * @returns {"allowed"|"forbidden"|"not-found"}
  25. */
  26. export function decideBranchUi({ user, branch, allowedBranches = null }) {
  27. const access = getBranchAccess(user, branch);
  28. if (access === BRANCH_ACCESS.FORBIDDEN) {
  29. return BRANCH_UI_DECISION.FORBIDDEN;
  30. }
  31. // Only admin-like roles may validate existence across branches.
  32. if (isAdminLikeRole(user.role)) {
  33. if (Array.isArray(allowedBranches) && !allowedBranches.includes(branch)) {
  34. return BRANCH_UI_DECISION.NOT_FOUND;
  35. }
  36. }
  37. return BRANCH_UI_DECISION.ALLOWED;
  38. }