import type { AuthUser } from "@/auth/types"; import type { RuleEngineResourceSlug } from "@/types/rule-engine"; export const FREIGHT_PERMS = { bookings: { view: "edr_freight_app:bookings:view", clearanceView: "edr_freight_app:bookings:clearance_view", staffAccept: "edr_freight_app:bookings:staff_accept", requestChanges: "edr_freight_app:bookings:request_changes", reject: "edr_freight_app:bookings:reject", approveLineStaff: "edr_freight_app:bookings:approve_line_staff", approveDirector: "edr_freight_app:bookings:approve_director", approveCeo: "edr_freight_app:bookings:approve_ceo", rejectApproval: "edr_freight_app:bookings:reject_approval", generateContract: "edr_freight_app:bookings:generate_contract", signStaff: "edr_freight_app:bookings:sign_staff", operations: "edr_freight_app:bookings:operations", cancel: "edr_freight_app:bookings:cancel", reviewDocuments: "edr_freight_app:bookings:review_documents", uploadClearanceOutput: "edr_freight_app:bookings:upload_clearance_output", finalizeClearance: "edr_freight_app:bookings:finalize_clearance", }, trainScheduling: { view: "edr_freight_app:train_scheduling:view", manage: "edr_freight_app:train_scheduling:manage", }, fleet: { view: "edr_freight_app:fleet:view", manage: "edr_freight_app:fleet:manage", }, admin: "edr_freight_app:admin", } as const; const slugToResourceKey = (slug: RuleEngineResourceSlug): string => slug.replace(/-/g, "_"); export function getPermissionKeys(user: AuthUser | null | undefined): string[] { if (!user) return []; if (user.permissionKeys?.length) return user.permissionKeys; const keys = new Set(); for (const p of user.permissions ?? []) { if (p.key) keys.add(p.key); } for (const emp of user.employee ?? []) { for (const pos of emp.positions ?? []) { for (const p of pos.permissions ?? []) { if (p.key) keys.add(p.key); } } } return [...keys]; } export function isSuperAdmin(user: AuthUser | null | undefined): boolean { if (user?.isSuperAdmin) return true; return Boolean(user?.roles?.some((r) => r.key === "super_admin")); } /** Org-level admins may act on any approval step in the chain. */ export function isOrganizationAdmin( user: AuthUser | null | undefined, ): boolean { return Boolean(user?.roles?.some((r) => r.key === "organization_admin")); } export function isFreightApprovalAdmin( user: AuthUser | null | undefined, ): boolean { return isSuperAdmin(user) || isOrganizationAdmin(user); } export function hasPermission( user: AuthUser | null | undefined, key: string, ): boolean { if (!user) return false; if (isSuperAdmin(user)) return true; return getPermissionKeys(user).includes(key); } export function canAccessBookings(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.bookings.view); } /** Can see/manage the customs document-clearance queue (Global Logistics). */ export function canViewClearance(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.bookings.reviewDocuments); } export function canViewScheduling(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.trainScheduling.view); } export function canManageScheduling(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.trainScheduling.manage); } export function canViewFleet(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.fleet.view); } export function isFreightAdmin(user: AuthUser | null | undefined): boolean { return hasPermission(user, FREIGHT_PERMS.admin); } export function ruleEngineViewKey(slug: RuleEngineResourceSlug): string { return `edr_freight_app:rule_engine:${slugToResourceKey(slug)}:view`; } export function ruleEngineManageKey(slug: RuleEngineResourceSlug): string { return `edr_freight_app:rule_engine:${slugToResourceKey(slug)}:manage`; } export function canAccessRuleEngineResource( user: AuthUser | null | undefined, slug: RuleEngineResourceSlug, mode: "view" | "manage", ): boolean { const key = mode === "manage" ? ruleEngineManageKey(slug) : ruleEngineViewKey(slug); return hasPermission(user, key); } export function canAccessAnyRuleEngineView( user: AuthUser | null | undefined, slugs: RuleEngineResourceSlug[], ): boolean { return slugs.some((slug) => canAccessRuleEngineResource(user, slug, "view")); }