fix(auth): stop class guards shadowing route permission keys

Nest runs class and method guards together, so a class-level view key
ANDs with every action key below it. Staff granted only an action were
denied before their key was ever checked: OCC could not fulfil wagon
transfers, dispatchers could not create a yard, and track staff could not
assign first/last-mile vehicles. Reads now carry the view key themselves,
and the warehouses baseline lists every key its routes use.
This commit is contained in:
Nathnael
2026-08-07 07:40:50 +00:00
parent 2a0810e734
commit 87e2edcbde
4 changed files with 26 additions and 5 deletions

View File

@@ -28,7 +28,9 @@ import { FirstMileInvoiceService } from './first-mile-invoice.service';
@ApiTags('first-mile')
@ApiBearerAuth()
@Controller('first-mile')
@BookingStaff(FREIGHT_PERMS.firstMile.view)
// No class-level key: Nest stacks class and method guards, so a class-level
// `view` would AND with every action key below and lock out staff granted only
// an action (e.g. assign_vehicles). Each route carries its own key instead.
export class FirstMileController {
constructor(
private readonly firstMileService: FirstMileService,
@@ -36,6 +38,7 @@ export class FirstMileController {
) { }
@Get()
@BookingStaff(FREIGHT_PERMS.firstMile.view)
@ApiOperation({ summary: 'List first-mile legs' })
findAll(
@Query('status') status?: string,
@@ -58,6 +61,7 @@ export class FirstMileController {
}
@Get(':id')
@BookingStaff(FREIGHT_PERMS.firstMile.view)
@ApiOperation({ summary: 'Get a first-mile leg by ID' })
findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.firstMileService.findById(id);