feat: ( permissions ) enforce specific permission keys across API and backoffice

This commit is contained in:
Abubeker Yasin
2026-09-04 15:44:28 +03:00
parent 7c7f5a7a70
commit 7a61ebcb27
69 changed files with 1061 additions and 251 deletions

View File

@@ -25,7 +25,7 @@ import { AutoAssignHoldDto, BlockSeatDto, HoldSeatsDto, ReleaseHoldDto, SetMaint
import { resolveActingUser, RequestWithActingUser } from "../../common/acting-user";
import { GetDuplicateSeatsQuery, ResolveDuplicatesDto } from "./duplicate-seats.dto";
import { JwtGuard } from "../../common/jwt.guard";
import { PassengerStaff } from "../../common/passenger-guards";
import { PassengerDelete, PassengerWrite } from "../../common/passenger-guards";
import { PASSENGER_PERMS } from "../../seed/passenger-permissions.registry";
@ApiTags("Seats")
@@ -35,7 +35,7 @@ export class SeatsController {
// ── Blocked Seats ─────────────────────────────────────────────────────────
@Get('blocks')
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.block, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth('IAM-auth')
@ApiOperation({ summary: 'List all blocked seats with reason and coach info' })
@ApiResponse({ status: 200, description: 'Blocked seat records' })
@@ -187,7 +187,7 @@ This makes it clear which segment of the route each seat is held for, enabling s
}
@Post("auto-assign-hold")
@PassengerStaff([PASSENGER_PERMS.bookings.manage])
@PassengerWrite(PASSENGER_PERMS.bookings.create, PASSENGER_PERMS.bookings.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({
summary: "Auto-assign and hold N seats of a class — staff bulk/group booking only",
@@ -247,7 +247,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
// ── Seat Block / Unblock ───────────────────────────────────────────────────
@Post(":seatId/block")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.block, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({
summary: "Block a seat (e.g., maintenance, damage)",
@@ -268,7 +268,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Delete(":seatId/block")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.block, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({ summary: "Unblock a seat" })
@ApiParam({ name: "seatId", description: "Seat UUID" })
@@ -279,7 +279,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
// ── Maintenance ───────────────────────────────────────────────────────────
@Post(":seatId/maintenance")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({ summary: "Set seat status to Under Maintenance" })
@ApiParam({ name: "seatId", description: "Seat UUID" })
@@ -294,7 +294,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Delete(":seatId/maintenance")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({ summary: "Clear seat maintenance status" })
@ApiParam({ name: "seatId", description: "Seat UUID" })
@@ -305,7 +305,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
// ── Remove Seat ────────────────────────────────────────────────────────────
@Patch(":seatId/remove")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerDelete(PASSENGER_PERMS.seats.delete)
@ApiBearerAuth("IAM-auth")
@ApiOperation({
summary: "Remove a seat by marking with negative seatNumber",
@@ -321,7 +321,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Patch(":seatId/undo-remove")
@PassengerStaff([PASSENGER_PERMS.seats.manage, PASSENGER_PERMS.admin])
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("IAM-auth")
@ApiOperation({
summary: "Undo seat removal by restoring original seatNumber",
@@ -338,7 +338,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Get("export/csv/:scheduleId")
@UseGuards(JwtGuard)
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("JWT-auth")
@ApiOperation({ summary: "Export seats as CSV" })
async exportCSV(@Param("scheduleId") scheduleId: string) {
@@ -347,7 +347,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Post("import/preview")
@UseGuards(JwtGuard)
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("JWT-auth")
@ApiOperation({ summary: "Preview CSV import" })
previewCSV(@Body() body: { csv: string }) {
@@ -355,7 +355,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Post("import/commit")
@UseGuards(JwtGuard)
@PassengerWrite(PASSENGER_PERMS.seats.create, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("JWT-auth")
@ApiOperation({ summary: "Commit CSV import" })
importCSV(
@@ -367,7 +367,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
// ── Duplicate seat management (backoffice) ────────────────────────────────
@Get("duplicates")
@UseGuards(JwtGuard)
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("JWT-auth")
@ApiOperation({
summary: "List duplicate seat assignments by schedule date",
@@ -418,7 +418,7 @@ Throws 409 with no partial hold created if fewer than the requested seats are av
}
@Post("duplicates/resolve")
@UseGuards(JwtGuard)
@PassengerWrite(PASSENGER_PERMS.seats.edit, PASSENGER_PERMS.seats.manage)
@ApiBearerAuth("JWT-auth")
@ApiOperation({
summary: "Auto-assign duplicate bookings to seats in selected coaches",