feat(bookings): restrict management to assigned PIC or super admin

Secure API endpoints with requireBookingManager authorization check
Update confirmation page to prompt for login if unauthorized
Add safe redirect handling to login and guest middleware
This commit is contained in:
2026-05-09 13:28:50 +08:00
parent a56a6706b0
commit cb683d6b3d
11 changed files with 102 additions and 13 deletions

View File

@@ -1,5 +1,6 @@
import type { CancelBookingConfirmationResponse } from '~~/shared/booking'
import { requireBookingManager } from '../../../../utils/auth'
import { cancelBookingConfirmationByConfirmationToken, getBookingByConfirmationToken } from '../../../../utils/booking-repository'
import { getRequiredRouteParam, httpError } from '../../../../utils/http'
@@ -11,6 +12,8 @@ export default defineEventHandler(async (event): Promise<CancelBookingConfirmati
httpError(404, 'Booking not found')
}
await requireBookingManager(event, existingBooking)
if (existingBooking.status === 'pending') {
return {
booking: existingBooking,

View File

@@ -1,5 +1,6 @@
import type { ConfirmBookingResponse } from '~~/shared/booking'
import { requireBookingManager } from '../../../../utils/auth'
import { confirmBookingByConfirmationToken, getBookingByConfirmationToken, getBookingInventorySummary } from '../../../../utils/booking-repository'
import { getRequiredRouteParam, httpError } from '../../../../utils/http'
import { sendBookingTicketReceiptViaWhatsApp } from '../../../../utils/whatsapp'
@@ -12,6 +13,8 @@ export default defineEventHandler(async (event): Promise<ConfirmBookingResponse>
httpError(404, 'Booking not found')
}
await requireBookingManager(event, existingBooking)
if (existingBooking.status === 'confirmed') {
return {
booking: existingBooking,

View File

@@ -1,5 +1,6 @@
import type { UpdateBookingDetailsResponse } from '~~/shared/booking'
import { requireBookingManager } from '../../../../utils/auth'
import {
clearBookingTransactionDocumentByConfirmationToken,
getBookingByConfirmationToken,
@@ -17,6 +18,8 @@ export default defineEventHandler(async (event): Promise<UpdateBookingDetailsRes
httpError(404, 'Booking not found')
}
await requireBookingManager(event, existingBooking)
if (existingBooking.status !== 'pending') {
httpError(409, 'Payment details can only be changed before confirmation')
}

View File

@@ -1,5 +1,6 @@
import type { UpdateBookingDetailsResponse } from '~~/shared/booking'
import { requireBookingManager } from '../../../../utils/auth'
import {
clearBookingTransactionDocumentByConfirmationToken,
getBookingByConfirmationToken
@@ -15,6 +16,8 @@ export default defineEventHandler(async (event): Promise<UpdateBookingDetailsRes
httpError(404, 'Booking not found')
}
await requireBookingManager(event, booking)
if (booking.status !== 'pending') {
httpError(409, 'Transaction document can only be changed before confirmation')
}

View File

@@ -1,6 +1,7 @@
import { sendStream, setHeader } from 'h3'
import { getBookingTransactionDocumentByConfirmationToken } from '../../../../utils/booking-repository'
import { requireBookingManager } from '../../../../utils/auth'
import { getBookingByConfirmationToken, getBookingTransactionDocumentByConfirmationToken } from '../../../../utils/booking-repository'
import { getRequiredRouteParam, httpError } from '../../../../utils/http'
import {
getSafeDownloadName,
@@ -9,6 +10,14 @@ import {
export default defineEventHandler(async (event) => {
const token = getRequiredRouteParam(event, 'token', 'Confirmation token')
const booking = await getBookingByConfirmationToken(token)
if (!booking) {
httpError(404, 'Booking not found')
}
await requireBookingManager(event, booking)
const document = await getBookingTransactionDocumentByConfirmationToken(token)
if (!document) {

View File

@@ -2,6 +2,7 @@ import type { UpdateBookingDetailsResponse } from '~~/shared/booking'
import { getHeader, readMultipartFormData } from 'h3'
import { requireBookingManager } from '../../../../utils/auth'
import {
getBookingByConfirmationToken,
replaceBookingTransactionDocumentByConfirmationToken
@@ -22,6 +23,8 @@ export default defineEventHandler(async (event): Promise<UpdateBookingDetailsRes
httpError(404, 'Booking not found')
}
await requireBookingManager(event, booking)
if (booking.status !== 'pending') {
httpError(409, 'Transaction document can only be changed before confirmation')
}