route.js 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import { listBranches } from "@/lib/storage";
  2. import { getSession } from "@/lib/auth/session";
  3. import { filterBranchesForSession } from "@/lib/auth/permissions";
  4. import {
  5. withErrorHandling,
  6. json,
  7. unauthorized,
  8. ApiError,
  9. } from "@/lib/api/errors";
  10. /**
  11. * GET /api/branches
  12. *
  13. * Returns the list of branches (e.g. ["NL01", "NL02", ...]) based on the
  14. * directory names under NAS_ROOT_PATH.
  15. *
  16. * RBAC:
  17. * - 401 if no session
  18. * - branch role: only returns its own branch
  19. * - admin/dev: returns all branches
  20. *
  21. * Happy-path response must remain unchanged:
  22. * { "branches": ["NL01", ...] }
  23. */
  24. export const GET = withErrorHandling(
  25. async function GET() {
  26. const session = await getSession();
  27. if (!session) {
  28. throw unauthorized("AUTH_UNAUTHENTICATED", "Unauthorized");
  29. }
  30. try {
  31. const branches = await listBranches();
  32. const visibleBranches = filterBranchesForSession(session, branches);
  33. return json({ branches: visibleBranches }, 200);
  34. } catch (err) {
  35. // Treat any storage read failures as internal server errors.
  36. // We do NOT expose filesystem error messages to the client.
  37. throw new ApiError({
  38. status: 500,
  39. code: "FS_STORAGE_ERROR",
  40. message: "Internal server error",
  41. cause: err,
  42. });
  43. }
  44. },
  45. { logPrefix: "[api/branches]" }
  46. );