import { buildSidebarSections, filterSidebarByPermission, flattenSidebarItems, } from "@/components/layout/sidebar-sections"; import type { AuthUser } from "@/auth/types"; import { isSuperAdmin } from "./permissions"; /** * IAM roles that grant the user-management subtree but no freight permissions. * Mirrors the `allowedRoles` on the org-admin route group in * `user-management/route.tsx` — a role outside this list is bounced by its * PrivateRoute, so landing anyone else there would just bounce again. */ const IAM_ADMIN_ROLES = ["admin", "organization_admin", "unit_admin"]; /** Terminal page for accounts with nothing granted. Never permission-gated. */ export const NO_ACCESS_PATH = "/no-access"; /** * The first route a user can actually reach. * * Every redirect in the app funnels through here instead of hardcoding * `/dashboard/overview`: that page is itself gated on `overview:view`, so * sending a user who lacks the key there redirects them to the page that just * rejected them — React Router renders nothing and the user sees a blank frame. * A pure `unit_admin` holds only `can:*` IAM keys and no `edr_freight_app:*` * key at all, so this hit them on every login. */ export function resolveLandingPath(user: AuthUser | null | undefined): string { const visible = filterSidebarByPermission(buildSidebarSections([]), user); // Only /dashboard/* items are safe landings. The "Staff" item points at // /user-management, which re-redirects by ROLE — a freight user holding // staff:* keys but no IAM role would ping-pong between the two. const firstFreightPage = flattenSidebarItems(visible).find((item) => item.href.startsWith("/dashboard/"), )?.href; if (firstFreightPage) return firstFreightPage; if (isSuperAdmin(user)) return "/user-management/dashboard"; const roleKeys = (user?.roles ?? []).map((role) => role.key ?? ""); if (roleKeys.some((key) => IAM_ADMIN_ROLES.includes(key))) { return "/user-management/user_management-dashboard"; } return NO_ACCESS_PATH; }