fix: validate eventTypeId is number in API v1 bookings endpoint (#22433)

* fix: validate eventTypeId is number in API v1 bookings endpoint

- Add validation to return 400 when eventTypeId is string instead of integer
- Prevents string values from reaching Prisma and causing 500 errors
- Follows existing validation patterns in the codebase
- Add test case to verify string eventTypeId returns 400 Bad Request

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* test: add focused test for eventTypeId validation

- Create separate test file for string eventTypeId validation
- Ensures validation logic is properly tested without being blocked by pre-existing issues
- Addresses cubic-dev-ai bot feedback about skipped tests
- Both string and number eventTypeId scenarios are tested

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* fix: improve eventTypeId validation to only check defined values

- Only validate eventTypeId when it's defined and not a number
- Prevents interference with schema validation for missing/undefined values
- Maintains 400 error response for string eventTypeId as required
- Fixes test compatibility issues while preserving validation logic

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* test: move eventTypeId validation test outside of skipped block

- Create dedicated test block for eventTypeId validation
- Remove duplicate test from skipped block
- Ensures validation logic is properly tested
- Addresses PR feedback from keithwillcode

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

* cleanup: remove duplicate eventTypeId validation test file

- Remove apps/api/v1/test/lib/bookings/eventTypeId-validation.test.ts
- Tests are now properly located in _post.test.ts outside skipped block
- Addresses PR feedback from keithwillcode about duplicate tests

Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Keith Williams
2025-07-11 19:16:27 -03:00
committed by GitHub
co-authored by Devin AI
parent 0207109612
commit 57564381cb
2 changed files with 45 additions and 0 deletions
+7
View File
@@ -222,6 +222,13 @@ async function handler(req: NextApiRequest) {
};
if (isSystemWideAdmin) userId = req.body.userId || userId;
if (req.body.eventTypeId !== undefined && typeof req.body.eventTypeId !== "number") {
throw new HttpError({
statusCode: 400,
message: "Bad request, eventTypeId must be a number",
});
}
if (isOrganizationOwnerOrAdmin) {
const accessibleUsersIds = await getAccessibleUsers({
adminUserId: userId,
@@ -25,6 +25,44 @@ vi.mock("@calcom/lib/server/i18n", () => {
};
});
describe("POST /api/bookings - eventTypeId validation", () => {
test("String eventTypeId should return 400", async () => {
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
method: "POST",
body: {
eventTypeId: "invalid-string",
},
});
await handler(req, res);
expect(res._getStatusCode()).toBe(400);
expect(JSON.parse(res._getData())).toEqual(
expect.objectContaining({
message: "Bad request, eventTypeId must be a number",
})
);
});
test("Number eventTypeId should not trigger validation error", async () => {
const { req, res } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
method: "POST",
body: {
eventTypeId: 123,
},
});
await handler(req, res);
const statusCode = res._getStatusCode();
const responseData = JSON.parse(res._getData());
if (statusCode === 400) {
expect(responseData.message).not.toBe("Bad request, eventTypeId must be a number");
}
});
});
describe.skipIf(true)("POST /api/bookings", () => {
describe("Errors", () => {
test("Missing required data", async () => {