This commit is contained in:
Matthias Hochmeister
2026-03-16 15:26:43 +01:00
parent 023bd7acbb
commit c15d4a50e0
13 changed files with 142 additions and 43 deletions

View File

@@ -2,6 +2,7 @@ import { Request, Response } from 'express';
import { ZodError } from 'zod';
import bookingService from '../services/booking.service';
import vehicleService from '../services/vehicle.service';
import { hasPermission, resolveRequestRole } from '../middleware/rbac.middleware';
import {
CreateBuchungSchema,
UpdateBuchungSchema,
@@ -87,7 +88,7 @@ class BookingController {
*/
async checkAvailability(req: Request, res: Response): Promise<void> {
try {
const { fahrzeugId, from, to } = req.query;
const { fahrzeugId, from, to, excludeId } = req.query;
if (!fahrzeugId || !from || !to) {
res
.status(400)
@@ -114,7 +115,7 @@ class BookingController {
}
const hasConflict = await bookingService.checkConflict(
fahrzeugId as string, beginn, ende
fahrzeugId as string, beginn, ende, excludeId as string | undefined
);
res.json({ success: true, data: { available: !hasConflict } });
} catch (error) {
@@ -204,8 +205,9 @@ class BookingController {
}
/**
* DELETE /api/bookings/:id
* DELETE /api/bookings/:id or PATCH /api/bookings/:id/cancel
* Soft-cancels a booking (sets abgesagt=TRUE).
* Allowed for booking creator or users with bookings:write permission.
*/
async cancel(req: Request, res: Response): Promise<void> {
try {
@@ -214,6 +216,20 @@ class BookingController {
res.status(400).json({ success: false, message: 'Ungültige Buchungs-ID' });
return;
}
// Check ownership: creator can always cancel their own booking
const booking = await bookingService.getById(id);
if (!booking) {
res.status(404).json({ success: false, message: 'Buchung nicht gefunden' });
return;
}
const isOwner = booking.gebucht_von === req.user!.id;
const role = resolveRequestRole(req);
if (!isOwner && !hasPermission(role, 'bookings:write')) {
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
return;
}
const parsed = CancelBuchungSchema.safeParse(req.body);
if (!parsed.success) {
handleZodError(res, parsed.error);