Implement user-based booking access control and enhance booking filtering options

This commit is contained in:
Marshal
2026-06-17 12:35:29 +00:00
parent 31710494d4
commit cd31f3612c
9 changed files with 530 additions and 137 deletions

View File

@@ -11,6 +11,7 @@ import {
Query,
Request,
Res,
UnauthorizedException,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
@@ -117,8 +118,22 @@ export class BookingsController {
@Get()
@ApiOperation({ summary: 'List freight bookings (paginated)' })
findAll(@Query() filter: FilterBookingDto) {
return this.bookingsService.findAll(filter);
async findAll(
@Query() filter: FilterBookingDto,
@CurrentUser() user: TCurrentUser,
) {
// Staff (backoffice) see every booking. Customers (portal) are always
// force-scoped to their own company, regardless of any companyId they pass.
if (hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
return this.bookingsService.findAll(filter);
}
const userId = user?.id;
if (!userId) throw new UnauthorizedException('Authentication required');
const companyId =
await this.bookingsService.resolveCustomerCompanyId(userId);
// No linked company yet → no bookings to show (avoids leaking all bookings).
if (!companyId) return { items: [], total: 0 };
return this.bookingsService.findAll(filter, companyId);
}
@Get('list-summary')
@@ -166,15 +181,35 @@ export class BookingsController {
@Get('by-reference/:reference')
@ApiOperation({ summary: 'Get booking by reference' })
async findByReference(@Param('reference') reference: string) {
async findByReference(
@Param('reference') reference: string,
@CurrentUser() user: TCurrentUser,
) {
const booking = await this.bookingsService.findByReference(reference);
// Staff see any booking; customers only their own company's.
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
await this.bookingsService.assertCustomerCanAccessBooking(
user?.id,
booking,
);
}
return this.transitionService.enrichBookingResponse(booking);
}
@Get(':id')
@ApiOperation({ summary: 'Get booking by ID' })
async findOne(@Param('id', ParseUUIDPipe) id: string) {
async findOne(
@Param('id', ParseUUIDPipe) id: string,
@CurrentUser() user: TCurrentUser,
) {
const booking = await this.bookingsService.findById(id);
// Staff see any booking; customers only their own company's.
if (!hasFreightPermission(user, FREIGHT_PERMS.bookings.view)) {
await this.bookingsService.assertCustomerCanAccessBooking(
user?.id,
booking,
);
}
return this.transitionService.enrichBookingResponse(booking);
}