Skip to content

Commit 7fbeeae

Browse files
emrysalUdit-takkarThyMinimalDev
authored
fix: event type not found 400 and other (calcom#23904)
* fix: various fixes specifically to event-types * Revamp error handling a little; highly flawed * fix: Test cases that depended on defaultResponder behaviour --------- Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
1 parent 5cf0553 commit 7fbeeae

13 files changed

Lines changed: 158 additions & 174 deletions

File tree

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
import { captureException as SentryCaptureException } from "@sentry/nextjs";
22
import type { NextMiddleware } from "next-api-middleware";
33

4-
import { redactError } from "@calcom/lib/redactError";
5-
64
export const captureErrors: NextMiddleware = async (_req, res, next) => {
75
try {
86
// Catch any errors that are thrown in remaining
97
// middleware and the API route handler
108
await next();
119
} catch (error) {
10+
console.error(error);
1211
SentryCaptureException(error);
13-
const redactedError = redactError(error);
14-
if (redactedError instanceof Error) {
15-
res.status(400).json({ message: redactedError.message, error: redactedError });
16-
return;
17-
}
18-
res.status(400).json({ message: "Something went wrong", error });
12+
res.status(500).json({ message: "Something went wrong" });
1913
}
2014
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { Prisma } from "@calcom/prisma/client";
2+
3+
export const eventTypeSelect = {
4+
id: true,
5+
title: true,
6+
slug: true,
7+
length: true,
8+
hidden: true,
9+
position: true,
10+
userId: true,
11+
teamId: true,
12+
scheduleId: true,
13+
eventName: true,
14+
timeZone: true,
15+
periodType: true,
16+
periodStartDate: true,
17+
periodEndDate: true,
18+
periodDays: true,
19+
periodCountCalendarDays: true,
20+
requiresConfirmation: true,
21+
recurringEvent: true,
22+
disableGuests: true,
23+
hideCalendarNotes: true,
24+
minimumBookingNotice: true,
25+
beforeEventBuffer: true,
26+
afterEventBuffer: true,
27+
schedulingType: true,
28+
price: true,
29+
currency: true,
30+
slotInterval: true,
31+
parentId: true,
32+
successRedirectUrl: true,
33+
description: true,
34+
locations: true,
35+
metadata: true,
36+
seatsPerTimeSlot: true,
37+
seatsShowAttendees: true,
38+
seatsShowAvailabilityCount: true,
39+
bookingFields: true,
40+
bookingLimits: true,
41+
onlyShowFirstAvailableSlot: true,
42+
durationLimits: true,
43+
customInputs: {
44+
select: { id: true, label: true, required: true, options: true, type: true, placeholder: true },
45+
},
46+
hashedLink: {
47+
select: { link: true },
48+
},
49+
team: {
50+
select: { slug: true },
51+
},
52+
hosts: {
53+
select: {
54+
userId: true,
55+
isFixed: true,
56+
scheduleId: true,
57+
},
58+
},
59+
owner: {
60+
select: { username: true, id: true },
61+
},
62+
children: {
63+
select: {
64+
id: true,
65+
userId: true,
66+
},
67+
},
68+
} satisfies Prisma.EventTypeSelect;

apps/api/v1/lib/validations/event-type.ts

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ import {
66
MIN_EVENT_DURATION_MINUTES,
77
} from "@calcom/lib/constants";
88
import slugify from "@calcom/lib/slugify";
9-
import { customInputSchema, eventTypeBookingFields } from "@calcom/prisma/zod-utils";
9+
import { eventTypeBookingFields } from "@calcom/prisma/zod-utils";
1010
import { EventTypeSchema } from "@calcom/prisma/zod/modelSchema/EventTypeSchema";
1111
import { HostSchema } from "@calcom/prisma/zod/modelSchema/HostSchema";
1212

1313
import { Frequency } from "~/lib/types";
1414

15-
import { jsonSchema } from "./shared/jsonSchema";
1615
import { schemaQueryUserId } from "./shared/queryUserId";
1716
import { timeZone } from "./shared/timeZone";
1817

@@ -118,67 +117,3 @@ const schemaEventTypeEditParams = z
118117
.strict();
119118

120119
export const schemaEventTypeEditBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeEditParams);
121-
export const schemaEventTypeReadPublic = EventTypeSchema.pick({
122-
id: true,
123-
title: true,
124-
slug: true,
125-
length: true,
126-
hidden: true,
127-
position: true,
128-
userId: true,
129-
teamId: true,
130-
scheduleId: true,
131-
eventName: true,
132-
timeZone: true,
133-
periodType: true,
134-
periodStartDate: true,
135-
periodEndDate: true,
136-
periodDays: true,
137-
periodCountCalendarDays: true,
138-
requiresConfirmation: true,
139-
recurringEvent: true,
140-
disableGuests: true,
141-
hideCalendarNotes: true,
142-
minimumBookingNotice: true,
143-
beforeEventBuffer: true,
144-
afterEventBuffer: true,
145-
schedulingType: true,
146-
price: true,
147-
currency: true,
148-
slotInterval: true,
149-
parentId: true,
150-
successRedirectUrl: true,
151-
description: true,
152-
locations: true,
153-
metadata: true,
154-
seatsPerTimeSlot: true,
155-
seatsShowAttendees: true,
156-
seatsShowAvailabilityCount: true,
157-
bookingFields: true,
158-
bookingLimits: true,
159-
onlyShowFirstAvailableSlot: true,
160-
durationLimits: true,
161-
}).merge(
162-
z.object({
163-
children: z.array(childrenSchema).optional().default([]),
164-
hosts: z.array(hostSchema).optional().default([]),
165-
locations: z
166-
.array(
167-
z.object({
168-
link: z.string().optional(),
169-
address: z.string().optional(),
170-
hostPhoneNumber: z.string().optional(),
171-
type: z.any().optional(),
172-
})
173-
)
174-
.nullable(),
175-
metadata: jsonSchema.nullable(),
176-
customInputs: customInputSchema.array().optional(),
177-
link: z.string().optional(),
178-
hashedLink: z
179-
.array(z.object({ link: z.string() }))
180-
.optional()
181-
.default([]),
182-
bookingFields: eventTypeBookingFields.optional().nullable(),
183-
})
184-
);

apps/api/v1/pages/api/event-types/[id]/_delete.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { NextApiRequest } from "next";
22

33
import { HttpError } from "@calcom/lib/http-error";
4-
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
5-
import prisma from "@calcom/prisma";
4+
import { prisma } from "@calcom/prisma";
65

76
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
87

@@ -66,4 +65,4 @@ async function checkPermissions(req: NextApiRequest) {
6665
throw new HttpError({ statusCode: 403, message: "Forbidden" });
6766
}
6867

69-
export default defaultResponder(deleteHandler);
68+
export default deleteHandler;

apps/api/v1/pages/api/event-types/[id]/_get.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import type { NextApiRequest } from "next";
22

33
import { HttpError } from "@calcom/lib/http-error";
4-
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
5-
import prisma from "@calcom/prisma";
4+
import { prisma } from "@calcom/prisma";
65
import { MembershipRole } from "@calcom/prisma/enums";
76

8-
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
7+
import { eventTypeSelect } from "~/lib/selects/event-type";
98
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
109
import { checkPermissions as canAccessTeamEventOrThrow } from "~/pages/api/teams/[teamId]/_auth-middleware";
1110

@@ -49,15 +48,13 @@ export async function getHandler(req: NextApiRequest) {
4948

5049
const eventType = await prisma.eventType.findUnique({
5150
where: { id },
52-
include: {
53-
customInputs: true,
54-
hashedLink: { select: { link: true } },
55-
team: { select: { slug: true } },
56-
hosts: { select: { userId: true, isFixed: true } },
57-
owner: { select: { username: true, id: true } },
58-
children: { select: { id: true, userId: true } },
59-
},
51+
select: eventTypeSelect,
6052
});
53+
54+
if (!eventType) {
55+
throw new HttpError({ statusCode: 404, message: "Event type not found" });
56+
}
57+
6158
await checkPermissions(req, eventType);
6259

6360
const link = eventType ? getCalLink(eventType) : null;
@@ -74,9 +71,12 @@ export async function getHandler(req: NextApiRequest) {
7471
eventType.scheduleId = user.defaultScheduleId;
7572
}
7673

77-
// TODO: eventType when not found should be a 404
78-
// but API consumers may depend on the {} behaviour.
79-
return { event_type: schemaEventTypeReadPublic.parse({ ...eventType, link }) };
74+
return {
75+
event_type: {
76+
...eventType,
77+
link,
78+
},
79+
};
8080
}
8181

8282
type BaseEventTypeCheckPermissions = {
@@ -100,4 +100,4 @@ async function checkPermissions<T extends BaseEventTypeCheckPermissions>(
100100
throw new HttpError({ statusCode: 403, message: "Forbidden" });
101101
}
102102

103-
export default defaultResponder(getHandler);
103+
export default getHandler;

apps/api/v1/pages/api/event-types/[id]/_patch.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import type { NextApiRequest } from "next";
22
import type { z } from "zod";
33

44
import { HttpError } from "@calcom/lib/http-error";
5-
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
6-
import prisma from "@calcom/prisma";
5+
import { prisma } from "@calcom/prisma";
76
import { Prisma } from "@calcom/prisma/client";
87
import { SchedulingType } from "@calcom/prisma/enums";
98

9+
import { eventTypeSelect } from "~/lib/selects/event-type";
1010
import type { schemaEventTypeBaseBodyParams } from "~/lib/validations/event-type";
11-
import { schemaEventTypeEditBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
11+
import { schemaEventTypeEditBodyParams } from "~/lib/validations/event-type";
1212
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
1313
import ensureOnlyMembersAsHosts from "~/pages/api/event-types/_utils/ensureOnlyMembersAsHosts";
1414

@@ -235,8 +235,8 @@ export async function patchHandler(req: NextApiRequest) {
235235
};
236236
}
237237
await checkPermissions(req, parsedBody);
238-
const eventType = await prisma.eventType.update({ where: { id }, data });
239-
return { event_type: schemaEventTypeReadPublic.parse(eventType) };
238+
const eventType = await prisma.eventType.update({ where: { id }, data, select: eventTypeSelect });
239+
return { event_type: eventType };
240240
}
241241

242242
async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schemaEventTypeBaseBodyParams>) {
@@ -249,4 +249,4 @@ async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schema
249249
await checkTeamEventEditPermission(req, body);
250250
}
251251

252-
export default defaultResponder(patchHandler);
252+
export default patchHandler;

apps/api/v1/pages/api/event-types/_get.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { NextApiRequest } from "next";
22

33
import { HttpError } from "@calcom/lib/http-error";
44
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
5-
import prisma from "@calcom/prisma";
5+
import { prisma } from "@calcom/prisma";
66
import type { PrismaClient } from "@calcom/prisma";
77

8-
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
8+
import { eventTypeSelect } from "~/lib/selects/event-type";
99
import { schemaQuerySlug } from "~/lib/validations/shared/querySlug";
1010
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
1111

@@ -54,23 +54,15 @@ async function getHandler(req: NextApiRequest) {
5454
userId: shouldUseUserId ? { in: userIds } : undefined,
5555
slug: slug, // slug will be undefined if not provided in query
5656
},
57-
include: {
58-
// eslint-disable-next-line @calcom/eslint/no-prisma-include-true
59-
customInputs: true,
60-
hashedLink: { select: { link: true } },
61-
team: { select: { slug: true } },
62-
hosts: { select: { userId: true, isFixed: true } },
63-
owner: { select: { username: true, id: true } },
64-
children: { select: { id: true, userId: true } },
65-
},
57+
select: eventTypeSelect,
6658
});
6759
// this really should return [], but backwards compatibility..
6860
if (data.length === 0) new HttpError({ statusCode: 404, message: "No event types were found" });
6961
return {
7062
event_types: (await defaultScheduleId<(typeof data)[number]>({ eventTypes: data, prisma, userIds })).map(
7163
(eventType) => {
7264
const link = getCalLink(eventType);
73-
return schemaEventTypeReadPublic.parse({ ...eventType, link });
65+
return { ...eventType, link };
7466
}
7567
),
7668
};

apps/api/v1/pages/api/event-types/_post.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import type { NextApiRequest } from "next";
22

33
import { HttpError } from "@calcom/lib/http-error";
44
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
5-
import prisma from "@calcom/prisma";
5+
import { prisma } from "@calcom/prisma";
66
import { Prisma } from "@calcom/prisma/client";
77
import { MembershipRole } from "@calcom/prisma/enums";
88

9-
import { schemaEventTypeCreateBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
9+
import { eventTypeSelect } from "~/lib/selects/event-type";
10+
import { schemaEventTypeCreateBodyParams } from "~/lib/validations/event-type";
1011
import { canUserAccessTeamWithRole } from "~/pages/api/teams/[teamId]/_auth-middleware";
1112

1213
import checkParentEventOwnership from "./_utils/checkParentEventOwnership";
@@ -306,10 +307,10 @@ async function postHandler(req: NextApiRequest) {
306307
data.hosts = { createMany: { data: hosts } };
307308
}
308309

309-
const eventType = await prisma.eventType.create({ data, include: { hosts: true } });
310+
const eventType = await prisma.eventType.create({ data, select: eventTypeSelect });
310311

311312
return {
312-
event_type: schemaEventTypeReadPublic.parse(eventType),
313+
event_type: eventType,
313314
message: "Event type created successfully",
314315
};
315316
}

apps/api/v1/pages/api/teams/[teamId]/event-types/_get.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { NextApiRequest } from "next";
22
import { z } from "zod";
33

44
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
5-
import prisma from "@calcom/prisma";
5+
import { prisma } from "@calcom/prisma";
66
import type { Prisma } from "@calcom/prisma/client";
77

8-
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
8+
import { eventTypeSelect } from "~/lib/selects/event-type";
99

1010
const querySchema = z.object({
1111
teamId: z.coerce.number(),
@@ -57,17 +57,11 @@ async function getHandler(req: NextApiRequest) {
5757
members: { some: { userId } },
5858
},
5959
},
60-
include: {
61-
customInputs: true,
62-
team: { select: { slug: true } },
63-
hosts: { select: { userId: true, isFixed: true } },
64-
owner: { select: { username: true, id: true } },
65-
children: { select: { id: true, userId: true } },
66-
},
60+
select: eventTypeSelect,
61+
};
62+
return {
63+
event_types: await prisma.eventType.findMany(args),
6764
};
68-
69-
const data = await prisma.eventType.findMany(args);
70-
return { event_types: data.map((eventType) => schemaEventTypeReadPublic.parse(eventType)) };
7165
}
7266

7367
export default defaultResponder(getHandler);

0 commit comments

Comments
 (0)