fix: add guest limits and rate limiting to booking-guests endpoint (#27494)
* fix: add guest limits and rate limiting to booking-guests endpoint - Add ArrayMaxSize(10) validation to limit guests per request to 10 - Add aggressive rate limiting (5 requests/minute) via @Throttle decorator - Add total guest limit check (max 30 guests per booking) to prevent abuse - Update API documentation to reflect new limits This prevents scammers from using the endpoint to send spam emails to hundreds of guests through our system. Co-Authored-By: [email protected] <[email protected]> * docs: update openapi.json with guest limits and rate limiting info Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
f91511b927
commit
d29c8a4fa2
@@ -3,6 +3,7 @@ import { AddGuestsOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/add
|
||||
import { BookingGuestsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/booking-guests.service";
|
||||
import { VERSION_2024_08_13_VALUE, VERSION_2024_08_13 } from "@/lib/api-versions";
|
||||
import { API_KEY_OR_ACCESS_TOKEN_HEADER } from "@/lib/docs/headers";
|
||||
import { Throttle } from "@/lib/endpoint-throttler-decorator";
|
||||
import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator";
|
||||
import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator";
|
||||
import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard";
|
||||
@@ -35,10 +36,19 @@ export class BookingGuestsController_2024_08_13 {
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Permissions([BOOKING_WRITE])
|
||||
@UseGuards(ApiAuthGuard, BookingUidGuard)
|
||||
@Throttle({
|
||||
limit: 5,
|
||||
ttl: 60000,
|
||||
blockDuration: 60000,
|
||||
name: "booking_guests_add",
|
||||
})
|
||||
@ApiHeader(API_KEY_OR_ACCESS_TOKEN_HEADER)
|
||||
@ApiOperation({
|
||||
summary: "Add guests to an existing booking",
|
||||
description: `Add one or more guests to an existing booking.
|
||||
description: `Add one or more guests to an existing booking. Maximum 10 guests per request, with a limit of 30 total guests per booking.
|
||||
|
||||
**Rate Limiting:**
|
||||
This endpoint is rate limited to 5 requests per minute to prevent abuse.
|
||||
|
||||
**Email Notifications:**
|
||||
When guests are added, the following notifications are sent (unless disabled by event type settings):
|
||||
|
||||
@@ -2,11 +2,13 @@ import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/reposito
|
||||
import { BookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/bookings.service";
|
||||
import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service";
|
||||
import { ApiAuthGuardUser } from "@/modules/auth/strategies/api-auth/api-auth.strategy";
|
||||
import { Injectable, Logger, HttpException, NotFoundException } from "@nestjs/common";
|
||||
import { Injectable, Logger, HttpException, NotFoundException, BadRequestException } from "@nestjs/common";
|
||||
|
||||
import { addGuestsHandler } from "@calcom/platform-libraries/bookings";
|
||||
import type { AddGuestsInput_2024_08_13 } from "@calcom/platform-types";
|
||||
|
||||
const MAX_TOTAL_GUESTS_PER_BOOKING = 30;
|
||||
|
||||
@Injectable()
|
||||
export class BookingGuestsService_2024_08_13 {
|
||||
private readonly logger = new Logger("BookingGuestsService_2024_08_13");
|
||||
@@ -23,6 +25,18 @@ export class BookingGuestsService_2024_08_13 {
|
||||
throw new NotFoundException(`Booking with uid ${bookingUid} not found`);
|
||||
}
|
||||
|
||||
const currentGuestCount = booking.attendees.length;
|
||||
const newGuestCount = input.guests.length;
|
||||
const totalGuestCount = currentGuestCount + newGuestCount;
|
||||
|
||||
if (totalGuestCount > MAX_TOTAL_GUESTS_PER_BOOKING) {
|
||||
const remainingSlots = Math.max(0, MAX_TOTAL_GUESTS_PER_BOOKING - currentGuestCount);
|
||||
throw new BadRequestException(
|
||||
`Cannot add ${newGuestCount} guests. This booking already has ${currentGuestCount} attendees. ` +
|
||||
`Maximum total guests allowed is ${MAX_TOTAL_GUESTS_PER_BOOKING}. You can add up to ${remainingSlots} more guests.`
|
||||
);
|
||||
}
|
||||
|
||||
const platformClientParams = booking.eventTypeId
|
||||
? await this.platformBookingsService.getOAuthClientParams(booking.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
@@ -10170,7 +10170,7 @@
|
||||
"post": {
|
||||
"operationId": "BookingGuestsController_2024_08_13_addGuests",
|
||||
"summary": "Add guests to an existing booking",
|
||||
"description": "Add one or more guests to an existing booking.\n \n **Email Notifications:**\n When guests are added, the following notifications are sent (unless disabled by event type settings):\n \n - **Organizer & Team Members:** Receive an \"Add Guests\" notification email informing them that new guests have been added to the booking.\n \n - **New Guests:** Receive a \"Scheduled Event\" email with full booking details and calendar invite. If they have a phone number, they also receive an SMS notification.\n \n - **Existing Guests:** Receive an \"Add Guests\" notification email informing them that additional guests have been added to the booking.\n \n <Note>The cal-api-version header is required for this endpoint. Without it, the request will fail with a 404 error.</Note>\n ",
|
||||
"description": "Add one or more guests to an existing booking. Maximum 10 guests per request, with a limit of 30 total guests per booking.\n \n **Rate Limiting:**\n This endpoint is rate limited to 5 requests per minute to prevent abuse.\n \n **Email Notifications:**\n When guests are added, the following notifications are sent (unless disabled by event type settings):\n \n - **Organizer & Team Members:** Receive an \"Add Guests\" notification email informing them that new guests have been added to the booking.\n \n - **New Guests:** Receive a \"Scheduled Event\" email with full booking details and calendar invite. If they have a phone number, they also receive an SMS notification.\n \n - **Existing Guests:** Receive an \"Add Guests\" notification email informing them that additional guests have been added to the booking.\n \n <Note>The cal-api-version header is required for this endpoint. Without it, the request will fail with a 404 error.</Note>\n ",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "cal-api-version",
|
||||
@@ -31182,7 +31182,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"guests": {
|
||||
"description": "Array of guests to add to the booking",
|
||||
"description": "Array of guests to add to the booking. Maximum 10 guests per request.",
|
||||
"example": [
|
||||
{
|
||||
"email": "[email protected]",
|
||||
@@ -31195,6 +31195,8 @@
|
||||
}
|
||||
],
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Guest"
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
IsArray,
|
||||
IsEmail,
|
||||
ArrayMinSize,
|
||||
ArrayMaxSize,
|
||||
IsString,
|
||||
IsOptional,
|
||||
IsTimeZone,
|
||||
@@ -67,12 +68,13 @@ class Guest {
|
||||
|
||||
export class AddGuestsInput_2024_08_13 {
|
||||
@ArrayMinSize(1)
|
||||
@ArrayMaxSize(10, { message: "Cannot add more than 10 guests at a time" })
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => Guest)
|
||||
@ApiProperty({
|
||||
type: [Guest],
|
||||
description: "Array of guests to add to the booking",
|
||||
description: "Array of guests to add to the booking. Maximum 10 guests per request.",
|
||||
example: [
|
||||
{
|
||||
email: "[email protected]",
|
||||
|
||||
Reference in New Issue
Block a user