import { applyDecorators, UseGuards } from '@nestjs/common'; import { FreightJwtGuard } from './freight-jwt.guard'; import { FreightPermissionGuard, MixedAudienceGuard, PortalCustomerGuard, } from './freight-permission.guard'; import { FREIGHT_PERMS } from '../seed/freight-permissions.registry'; export const BookingStaff = (permission: string | string[]) => applyDecorators( UseGuards( FreightJwtGuard, FreightPermissionGuard( Array.isArray(permission) ? permission : [permission], ), ), ); /** * Read-only reference data (yard dropdowns, search filters): any signed-in * staff. Menu/page visibility stays permission-gated in the frontend — this * only lets forms populate their lookups. * Deprecated for new routes — it never checked the caller was staff. Prefer * BookingStaff() or MixedAudience(); kept for routes not yet swept. */ export const StaffReference = () => applyDecorators(UseGuards(FreightJwtGuard, FreightPermissionGuard([]))); /** Portal routes: customer accounts only; ownership scoping stays in services. */ export const PortalCustomer = () => applyDecorators(UseGuards(FreightJwtGuard, PortalCustomerGuard)); /** * Routes both audiences call (sign, shared document reads, handover): staff * need one of the given permissions, customers pass through to the service's * ownership checks. */ export const MixedAudience = (permission: string | string[]) => applyDecorators( UseGuards( FreightJwtGuard, MixedAudienceGuard( Array.isArray(permission) ? permission : [permission], ), ), ); export const BookingView = () => BookingStaff(FREIGHT_PERMS.bookings.view); export const ChatSync = () => BookingStaff(FREIGHT_PERMS.chat.sync); /** * The document-review countdown in the backoffice header. Its own permission so * it can be granted to exactly the position types that decide operation * requests, instead of every holder of bookings:view. */ export const BookingDocReviewAlert = () => BookingStaff(FREIGHT_PERMS.bookings.docReviewAlert); /** Staff wagon-cancellation history list (admin side). */ export const WagonCancellationView = () => BookingStaff(FREIGHT_PERMS.bookings.wagonCancellationView); /** Staff void of a customer's pending (fee-unpaid) wagon cancellation. */ export const WagonCancellationVoid = () => BookingStaff(FREIGHT_PERMS.bookings.wagonCancellationVoid); /** Staff rebook of a customer's wagon-cancellation credit on their behalf. */ export const WagonCancellationRebook = () => BookingStaff(FREIGHT_PERMS.bookings.wagonCancellationRebook); export const TrainSchedulingView = () => BookingStaff(FREIGHT_PERMS.trainScheduling.view); // Granular train-scheduling actions replace the retired coarse manage: // create a schedule, update (assign/consist/finalize/dispatch/arrive…), // cancel a schedule, reschedule (+ maintenance), and manage global rules. export const TrainSchedulingCreate = () => BookingStaff(FREIGHT_PERMS.trainScheduling.create); export const TrainSchedulingUpdate = () => BookingStaff(FREIGHT_PERMS.trainScheduling.update); /** * Confirm a booking's cargo loaded/unloaded at a yard — carved out of the * coarse `update` so it can be granted independently of general schedule * editing. Same two keys gate import, export, and intercity movements alike: * the generic per-booking route and the intercity-specific one both use them. */ export const TrainSchedulingLoad = () => BookingStaff(FREIGHT_PERMS.trainScheduling.load); export const TrainSchedulingUnload = () => BookingStaff(FREIGHT_PERMS.trainScheduling.unload); /** * Per-station loading/unloading time windows — the four buttons are four * permissions so start and end can be granted to different people. The same * endpoint that records a click also edits it (explicit `at`), so each * permission covers editing its own timestamp too. */ export const TrainSchedulingLoadingStart = () => BookingStaff(FREIGHT_PERMS.trainScheduling.loadingStart); export const TrainSchedulingLoadingEnd = () => BookingStaff(FREIGHT_PERMS.trainScheduling.loadingEnd); export const TrainSchedulingUnloadingStart = () => BookingStaff(FREIGHT_PERMS.trainScheduling.unloadingStart); export const TrainSchedulingUnloadingEnd = () => BookingStaff(FREIGHT_PERMS.trainScheduling.unloadingEnd); export const TrainSchedulingCancel = () => BookingStaff(FREIGHT_PERMS.trainScheduling.cancel); export const TrainSchedulingReschedule = () => BookingStaff(FREIGHT_PERMS.trainScheduling.reschedule); export const TrainSchedulingRulesManage = () => BookingStaff(FREIGHT_PERMS.trainScheduling.rulesManage); /** Edit a schedule's operational run numbers (train + voyage) before dispatch. */ export const TrainSchedulingEditTrainNumber = () => BookingStaff(FREIGHT_PERMS.trainScheduling.editTrainNumber); /** * Fleet guards take an optional granular per-resource key (locomotives:create, * wagons:delete, …). The legacy coarse fleet:view / fleet:manage keys remain * valid as a one-of fallback so existing role grants keep working. */ export const FleetView = (granular?: string | string[]) => BookingStaff( granular ? [ ...(Array.isArray(granular) ? granular : [granular]), FREIGHT_PERMS.fleet.view, ] : FREIGHT_PERMS.fleet.view, ); export const FleetManage = (granular?: string) => BookingStaff( granular ? [granular, FREIGHT_PERMS.fleet.manage] : FREIGHT_PERMS.fleet.manage, ); /** Requester creates a wagon-transfer request (count-only, no wagon picks). */ export const WagonTransferRequest = () => BookingStaff(FREIGHT_PERMS.wagons.transferRequest); /** OCC fulfils a wagon-transfer request — picks the wagons and executes the move. */ export const WagonTransferFulfill = () => BookingStaff(FREIGHT_PERMS.wagons.transferFulfill); /** Admin: read every staffer's wagon-transfer history (not just one's own). */ export const WagonTransferHistoryAll = () => BookingStaff(FREIGHT_PERMS.wagons.transferHistoryAll); /** * Open the transfer-requests desk. `wagons:view` is accepted as a one-of * fallback so staff who could already reach the queue keep it without a * re-grant — same pattern the granular fleet keys use. */ export const WagonTransferView = () => BookingStaff([FREIGHT_PERMS.wagons.transferView, FREIGHT_PERMS.wagons.view]); /** Withdraw a request that has not moved any wagon yet. */ export const WagonTransferCancel = () => BookingStaff([ FREIGHT_PERMS.wagons.transferCancel, FREIGHT_PERMS.wagons.transferRequest, ]); /** * End a request short of the requested count. Whoever may move wagons may also * declare the yard has no more to give, so fulfil is accepted alongside the * dedicated key. */ export const WagonTransferCloseShort = () => BookingStaff([ FREIGHT_PERMS.wagons.transferCloseShort, FREIGHT_PERMS.wagons.transferFulfill, ]); /** Org-administration endpoints (user mgmt, billing config, company CRUD, settings). */ export const FreightAdmin = () => BookingStaff(FREIGHT_PERMS.admin); /** Container allocation on a booking (allocate-containers endpoint). */ export const AllocationManage = () => BookingStaff(FREIGHT_PERMS.allocation.manage);