diff --git a/README.md b/README.md index 19baacdf58..17082202cd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Cal.com Public API (Enterprise Only) -This is the public REST api for cal.com. -It exposes CRUD Endpoints of all our most important resources. +This is the public REST api for cal.com. +It exposes CRUD Endpoints of all our most important resources. And it makes it easy for anyone to integrate with Cal.com at the application programming level. ## Stack @@ -63,9 +63,10 @@ API Keys optionally may have expiry dates, if they are expired they won't work. In the future we might add support for header Bearer Auth if we need to or if our customers require it. ## Middlewares + We don't use the new NextJS 12 Beta Middlewares, mainly because they run on the edge, and are not able to call prisma from api endpoints. We use instead a very nifty library called next-api-middleware that let's us use a similar approach building our own middlewares and applying them as we see fit. -* withMiddleware() requires some default middlewares (verifyApiKey, etc...) +- withMiddleware() requires some default middlewares (verifyApiKey, etc...) ## Next.config.js @@ -121,21 +122,21 @@ We aim to provide a fully tested API for our peace of mind, this is accomplished ## Endpoints matrix -| resource | get [id] | get all | create | edit | delete | -|--------------------------|----------|----------|---------|-------|--------| -| attendees | ✅ | ✅ | ✅ | ✅ | ✅ | -| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ | -| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ | -| daily-event-references | ✅ | ✅ | ✅ | ✅ | ✅ | -| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ | -| event-type-custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ | -| event-types | ✅ | ✅ | ✅ | ✅ | ✅ | -| memberships | ✅ | ✅ | ✅ | ✅ | ✅ | -| payments | ✅ | ✅ | ❌ | ❌ | ❌ | -| schedules | ✅ | ✅ | ✅ | ✅ | ✅ | -| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ | -| teams | ✅ | ✅ | ✅ | ✅ | ✅ | -| users | ✅ | 👤[1] | ✅ | ✅ | ✅ | +| resource | get [id] | get all | create | edit | delete | +| ------------------------ | -------- | ------- | ------ | ---- | ------ | +| attendees | ✅ | ✅ | ✅ | ✅ | ✅ | +| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ | +| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ | +| daily-event-references | ✅ | ✅ | ✅ | ✅ | ✅ | +| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ | +| event-type-custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ | +| event-types | ✅ | ✅ | ✅ | ✅ | ✅ | +| memberships | ✅ | ✅ | ✅ | ✅ | ✅ | +| payments | ✅ | ✅ | ❌ | ❌ | ❌ | +| schedules | ✅ | ✅ | ✅ | ✅ | ✅ | +| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ | +| teams | ✅ | ✅ | ✅ | ✅ | ✅ | +| users | ✅ | 👤[1] | ✅ | ✅ | ✅ | ## Models from database that are not exposed @@ -170,5 +171,6 @@ DATABASE_URL=DATABASE_URL="postgresql://postgres:@localhost:5450/calendso" ## Optional -API_KEY_PREFIX=cal_# This can be changed per envirorment so cal_test_ for staging for example. -> If you're self-hosting under our commercial license, you can use any prefix you want for api keys. either leave the default cal_ (not providing any envirorment variable) or modify it +API*KEY_PREFIX=cal*# This can be changed per envirorment so cal*test* for staging for example. + +> If you're self-hosting under our commercial license, you can use any prefix you want for api keys. either leave the default cal\_ (not providing any envirorment variable) or modify it diff --git a/lib/validations/attendee.ts b/lib/validations/attendee.ts index 290ea16adf..70444437aa 100644 --- a/lib/validations/attendee.ts +++ b/lib/validations/attendee.ts @@ -1,23 +1,39 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _AttendeeModel as Attendee } from "@calcom/prisma/zod"; -export const schemaAttendeeBaseBodyParams = Attendee.omit({ id: true }).partial(); +import { timeZone } from "@lib/validations/shared/timeZone"; -export const schemaAttendeePublic = Attendee.omit({}); +export const schemaAttendeeBaseBodyParams = Attendee.pick({ + bookingId: true, + email: true, + name: true, + timeZone: true, +}).partial(); -const schemaAttendeeRequiredParams = z.object({ - bookingId: z.any(), - email: z.string().email(), - name: z.string(), - timeZone: z.string(), -}); - -export const schemaAttendeeBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeRequiredParams); - -export const withValidAttendee = withValidation({ - schema: schemaAttendeeBodyParams, - type: "Zod", - mode: "body", +const schemaAttendeeCreateParams = z + .object({ + bookingId: z.number().int(), + email: z.string().email(), + name: z.string().optional(), + timeZone: timeZone, + }) + .strict(); + +const schemaAttendeeEditParams = z + .object({ + name: z.string().optional(), + email: z.string().email().optional(), + timeZone: timeZone.optional(), + }) + .strict(); +export const schemaAttendeeEditBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeEditParams); +export const schemaAttendeeCreateBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeCreateParams); + +export const schemaAttendeeReadPublic = Attendee.pick({ + id: true, + bookingId: true, + name: true, + email: true, + timeZone: true, }); diff --git a/lib/validations/availability.ts b/lib/validations/availability.ts index 20e3c61c94..a6ddf4b5c6 100644 --- a/lib/validations/availability.ts +++ b/lib/validations/availability.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _AvailabilityModel as Availability } from "@calcom/prisma/zod"; @@ -11,21 +10,38 @@ export const schemaAvailabilityBaseBodyParams = Availability.pick({ days: true, }).partial(); -export const schemaAvailabilityPublic = Availability.omit({}); - -const schemaAvailabilityRequiredParams = z.object({ - startTime: z.date().or(z.string()).optional(), - endTime: z.date().or(z.string()).optional(), - days: z.array(z.number()).optional(), - eventTypeId: z.number().optional(), +export const schemaAvailabilityReadPublic = Availability.pick({ + id: true, + startTime: true, + endTime: true, + date: true, + scheduleId: true, + days: true, + userId: true, + eventTypeId: true, }); -export const schemaAvailabilityBodyParams = schemaAvailabilityBaseBodyParams.merge( - schemaAvailabilityRequiredParams +const schemaAvailabilityCreateParams = z + .object({ + startTime: z.date().or(z.string()), + endTime: z.date().or(z.string()), + days: z.array(z.number()).optional(), + eventTypeId: z.number().optional(), + }) + .strict(); + +const schemaAvailabilityEditParams = z + .object({ + startTime: z.date().or(z.string()).optional(), + endTime: z.date().or(z.string()).optional(), + days: z.array(z.number()).optional(), + eventTypeId: z.number().optional(), + }) + .strict(); + +export const schemaAvailabilityEditBodyParams = schemaAvailabilityBaseBodyParams.merge( + schemaAvailabilityEditParams +); +export const schemaAvailabilityCreateBodyParams = schemaAvailabilityBaseBodyParams.merge( + schemaAvailabilityCreateParams ); - -export const withValidAvailability = withValidation({ - schema: schemaAvailabilityBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/booking-reference.ts b/lib/validations/booking-reference.ts index 75a7d95f0c..66aabc3d88 100644 --- a/lib/validations/booking-reference.ts +++ b/lib/validations/booking-reference.ts @@ -1,23 +1,53 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _BookingReferenceModel as BookingReference } from "@calcom/prisma/zod"; -export const schemaBookingReferenceBaseBodyParams = BookingReference.omit({ id: true }).partial(); +export const schemaBookingReferenceBaseBodyParams = BookingReference.pick({ + type: true, + bookingId: true, + uid: true, + meetingId: true, + meetingPassword: true, + meetingUrl: true, + deleted: true, +}).partial(); -export const schemaBookingReferencePublic = BookingReference.omit({}); - -const schemaBookingReferenceRequiredParams = z.object({ - type: z.string(), - uid: z.string(), +export const schemaBookingReferenceReadPublic = BookingReference.pick({ + id: true, + type: true, + bookingId: true, + uid: true, + meetingId: true, + meetingPassword: true, + meetingUrl: true, + deleted: true, }); -export const schemaBookingReferenceBodyParams = schemaBookingReferenceBaseBodyParams.merge( - schemaBookingReferenceRequiredParams +const schemaBookingReferenceCreateParams = z + .object({ + type: z.string(), + uid: z.string(), + meetingId: z.string(), + meetingPassword: z.string(), + meetingUrl: z.string(), + deleted: z.boolean(), + }) + .strict(); + +const schemaBookingReferenceEditParams = z + .object({ + type: z.string().optional(), + uid: z.string().optional(), + meetingId: z.string().optional(), + meetingPassword: z.string().optional(), + meetingUrl: z.string().optional(), + deleted: z.boolean().optional(), + }) + .strict(); + +export const schemaBookingCreateBodyParams = schemaBookingReferenceBaseBodyParams.merge( + schemaBookingReferenceCreateParams +); +export const schemaBookingEditBodyParams = schemaBookingReferenceBaseBodyParams.merge( + schemaBookingReferenceEditParams ); - -export const withValidBookingReference = withValidation({ - schema: schemaBookingReferenceBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/booking.ts b/lib/validations/booking.ts index 77eca1d156..60c231efa5 100644 --- a/lib/validations/booking.ts +++ b/lib/validations/booking.ts @@ -1,23 +1,46 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _BookingModel as Booking } from "@calcom/prisma/zod"; -const schemaBookingBaseBodyParams = Booking.omit({ id: true }).partial(); +const schemaBookingBaseBodyParams = Booking.pick({ + uid: true, + userId: true, + eventTypeId: true, + title: true, + startTime: true, + endTime: true, +}).partial(); -const schemaBookingRequiredParams = z.object({ - uid: z.string(), - title: z.string(), - startTime: z.date(), - endTime: z.date(), -}); - -export const schemaBookingBodyParams = schemaBookingBaseBodyParams.merge(schemaBookingRequiredParams); - -export const schemaBookingPublic = Booking.omit({}); - -export const withValidBooking = withValidation({ - schema: schemaBookingBodyParams, - type: "Zod", - mode: "body", +const schemaBookingCreateParams = z + .object({ + uid: z.string(), + userId: z.number(), + eventTypeId: z.number(), + title: z.string(), + startTime: z.date(), + endTime: z.date(), + }) + .strict(); + +export const schemaBookingCreateBodyParams = schemaBookingBaseBodyParams.merge(schemaBookingCreateParams); + +const schemaBookingEditParams = z + .object({ + uid: z.string().optional(), + title: z.string().optional(), + startTime: z.date().optional(), + endTime: z.date().optional(), + }) + .strict(); + +export const schemaBookingEditBodyParams = schemaBookingBaseBodyParams.merge(schemaBookingEditParams); + +export const schemaBookingReadPublic = Booking.pick({ + id: true, + userId: true, + eventTypeId: true, + uid: true, + title: true, + startTime: true, + endTime: true, }); diff --git a/lib/validations/credential.ts b/lib/validations/credential.ts deleted file mode 100644 index 9397ef2577..0000000000 --- a/lib/validations/credential.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { withValidation } from "next-validations"; -import { z } from "zod"; - -import { _CredentialModel as Credential } from "@calcom/prisma/zod"; - -import { jsonSchema } from "./shared/jsonSchema"; - -const schemaCredentialBaseBodyParams = Credential.omit({ id: true, userId: true }).partial(); - -const schemaCredentialRequiredParams = z.object({ - type: z.string(), - key: jsonSchema, -}); - -export const schemaCredentialBodyParams = schemaCredentialBaseBodyParams.merge( - schemaCredentialRequiredParams -); - -export const schemaCredentialPublic = Credential.omit({}); - -export const withValidCredential = withValidation({ - schema: schemaCredentialBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/daily-event-reference.ts b/lib/validations/daily-event-reference.ts index f477f6bec6..0ce79e6324 100644 --- a/lib/validations/daily-event-reference.ts +++ b/lib/validations/daily-event-reference.ts @@ -1,22 +1,38 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _DailyEventReferenceModel as DailyEventReference } from "@calcom/prisma/zod"; -export const schemaDailyEventReferenceBaseBodyParams = DailyEventReference.omit({ id: true }); +export const schemaDailyEventReferenceBaseBodyParams = DailyEventReference.pick({ + dailytoken: true, + dailyurl: true, + bookingId: true, +}).partial(); -const schemaDailyEventReferenceRequiredParams = z.object({ - email: z.string().email(), -}); +const schemaDailyEventReferenceCreateParams = z + .object({ + dailytoken: z.string(), + dailyurl: z.string(), + bookingId: z.number(), + }) + .strict(); -export const schemaDailyEventReferenceBodyParams = schemaDailyEventReferenceBaseBodyParams.merge( - schemaDailyEventReferenceRequiredParams +export const schemaDailyEventReferenceCreateBodyParams = schemaDailyEventReferenceBaseBodyParams.merge( + schemaDailyEventReferenceCreateParams ); -export const schemaDailyEventReferencePublic = DailyEventReference.omit({}); +const schemaDailyEventReferenceEditParams = z + .object({ + dailytoken: z.string().optional(), + dailyurl: z.string().optional(), + }) + .strict(); -export const withValidDailyEventReference = withValidation({ - schema: schemaDailyEventReferenceBodyParams, - type: "Zod", - mode: "body", +export const schemaDailyEventReferenceEditBodyParams = schemaDailyEventReferenceBaseBodyParams.merge( + schemaDailyEventReferenceEditParams +); +export const schemaDailyEventReferenceReadPublic = DailyEventReference.pick({ + id: true, + dailytoken: true, + dailyurl: true, + bookingId: true, }); diff --git a/lib/validations/destination-calendar.ts b/lib/validations/destination-calendar.ts index 87e367ee19..7f90cd0002 100644 --- a/lib/validations/destination-calendar.ts +++ b/lib/validations/destination-calendar.ts @@ -1,23 +1,48 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _DestinationCalendarModel as DestinationCalendar } from "@calcom/prisma/zod"; -export const schemaDestinationCalendarBaseBodyParams = DestinationCalendar.omit({ id: true }).partial(); +export const schemaDestinationCalendarBaseBodyParams = DestinationCalendar.pick({ + integration: true, + externalId: true, + eventTypeId: true, + bookingId: true, + userId: true, +}).partial(); -const schemaDestinationCalendarRequiredParams = z.object({ - integration: z.string(), - externalId: z.string(), -}); +const schemaDestinationCalendarCreateParams = z + .object({ + integration: z.string(), + externalId: z.string(), + eventTypeId: z.number(), + bookingId: z.number(), + userId: z.number(), + }) + .strict(); -export const schemaDestinationCalendarBodyParams = schemaDestinationCalendarBaseBodyParams.merge( - schemaDestinationCalendarRequiredParams +export const schemaDestinationCalendarCreateBodyParams = schemaDestinationCalendarBaseBodyParams.merge( + schemaDestinationCalendarCreateParams ); -export const schemaDestinationCalendarPublic = DestinationCalendar.omit({}); +const schemaDestinationCalendarEditParams = z + .object({ + integration: z.string().optional(), + externalId: z.string().optional(), + eventTypeId: z.number().optional(), + bookingId: z.number().optional(), + userId: z.number().optional(), + }) + .strict(); -export const withValidDestinationCalendar = withValidation({ - schema: schemaDestinationCalendarBodyParams, - type: "Zod", - mode: "body", +export const schemaDestinationCalendarEditBodyParams = schemaDestinationCalendarBaseBodyParams.merge( + schemaDestinationCalendarEditParams +); + +export const schemaDestinationCalendarReadPublic = DestinationCalendar.pick({ + id: true, + integration: true, + externalId: true, + eventTypeId: true, + bookingId: true, + userId: true, }); diff --git a/lib/validations/event-type-custom-input.ts b/lib/validations/event-type-custom-input.ts index 73555285e4..560d3d7684 100644 --- a/lib/validations/event-type-custom-input.ts +++ b/lib/validations/event-type-custom-input.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _EventTypeCustomInputModel as EventTypeCustomInput } from "@calcom/prisma/zod"; @@ -17,8 +16,6 @@ const schemaEventTypeCustomInputRequiredParams = z.object({ eventType: z.object({ connect: z.object({ id: z.number().optional(), - // username: z.string().optional(), - // email: z.string().optional(), }), // FIXME: Provide valid EventTypeModel schema here, but not sure how yet. create: z.any(), @@ -28,9 +25,3 @@ const schemaEventTypeCustomInputRequiredParams = z.object({ export const schemaEventTypeCustomInputBodyParams = schemaEventTypeCustomInputBaseBodyParams.merge( schemaEventTypeCustomInputRequiredParams ); - -export const withValidEventTypeCustomInput = withValidation({ - schema: schemaEventTypeCustomInputBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/event-type.ts b/lib/validations/event-type.ts index 119edcb248..e8665a9e3b 100644 --- a/lib/validations/event-type.ts +++ b/lib/validations/event-type.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _EventTypeModel as EventType } from "@calcom/prisma/zod"; @@ -14,9 +13,3 @@ const schemaEventTypeRequiredParams = z.object({ export const schemaEventTypeBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeRequiredParams); // @NOTE: Removing locations and metadata properties before validation, add them later if required export const schemaEventTypePublic = EventType.omit({ locations: true, metadata: true }); - -export const withValidEventType = withValidation({ - schema: schemaEventTypeBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/membership.ts b/lib/validations/membership.ts index bb5d7cb7fc..d58eea2c33 100644 --- a/lib/validations/membership.ts +++ b/lib/validations/membership.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _MembershipModel as Membership } from "@calcom/prisma/zod"; @@ -13,9 +12,3 @@ export const schemaMembershipBodyParams = schemaMembershipBaseBodyParams.merge( ); export const schemaMembershipPublic = Membership.omit({}); - -export const withValidMembership = withValidation({ - schema: schemaMembershipBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/payment.ts b/lib/validations/payment.ts index 5789d4a092..32c5d8d641 100644 --- a/lib/validations/payment.ts +++ b/lib/validations/payment.ts @@ -1,13 +1,5 @@ -import { withValidation } from "next-validations"; - import { _PaymentModel as Payment } from "@calcom/prisma/zod"; // FIXME: Payment seems a delicate endpoint, do we need to remove anything here? export const schemaPaymentBodyParams = Payment.omit({ id: true }); export const schemaPaymentPublic = Payment.omit({ externalId: true }); - -export const withValidPayment = withValidation({ - schema: schemaPaymentBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/reminder-mail.ts b/lib/validations/reminder-mail.ts index d97c65c2b1..635dc84dac 100644 --- a/lib/validations/reminder-mail.ts +++ b/lib/validations/reminder-mail.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _ReminderMailModel as ReminderMail } from "@calcom/prisma/zod"; @@ -16,9 +15,3 @@ const schemaReminderMailRequiredParams = z.object({ export const schemaReminderMailBodyParams = schemaReminderMailBaseBodyParams.merge( schemaReminderMailRequiredParams ); - -export const withValidReminderMail = withValidation({ - schema: schemaReminderMailBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/schedule.ts b/lib/validations/schedule.ts index e5782a08d7..176d972da1 100644 --- a/lib/validations/schedule.ts +++ b/lib/validations/schedule.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _ScheduleModel as Schedule } from "@calcom/prisma/zod"; @@ -13,9 +12,3 @@ const schemaScheduleRequiredParams = z.object({ export const schemaScheduleBodyParams = schemaScheduleBaseBodyParams.merge(schemaScheduleRequiredParams); export const schemaSchedulePublic = Schedule.omit({}); - -export const withValidSchedule = withValidation({ - schema: schemaScheduleBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/selected-calendar.ts b/lib/validations/selected-calendar.ts index 4eab89d937..ffdc54b96a 100644 --- a/lib/validations/selected-calendar.ts +++ b/lib/validations/selected-calendar.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _SelectedCalendarModel as SelectedCalendar } from "@calcom/prisma/zod"; @@ -24,9 +23,3 @@ const schemaSelectedCalendarRequiredParams = z.object({ export const schemaSelectedCalendarBodyParams = schemaSelectedCalendarBaseBodyParams.merge( schemaSelectedCalendarRequiredParams ); - -export const withValidSelectedCalendar = withValidation({ - schema: schemaSelectedCalendarBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/shared/timeZone.ts b/lib/validations/shared/timeZone.ts new file mode 100644 index 0000000000..9dfa98003d --- /dev/null +++ b/lib/validations/shared/timeZone.ts @@ -0,0 +1,5 @@ +import * as tzdb from "tzdata"; +import * as z from "zod"; + +// @note: This is a custom validation that checks if the timezone is valid and exists in the tzdb library +export const timeZone = z.string().refine((tz: string) => Object.keys(tzdb.zones).includes(tz)); diff --git a/lib/validations/team.ts b/lib/validations/team.ts index ec6cbf35ec..d980607f87 100644 --- a/lib/validations/team.ts +++ b/lib/validations/team.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _TeamModel as Team } from "@calcom/prisma/zod"; @@ -10,9 +9,3 @@ const schemaTeamRequiredParams = z.object({}); export const schemaTeamBodyParams = schemaTeamBaseBodyParams.merge(schemaTeamRequiredParams); export const schemaTeamPublic = Team.omit({}); - -export const withValidTeam = withValidation({ - schema: schemaTeamBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/lib/validations/user.ts b/lib/validations/user.ts index 7452c6ad44..9eb7b05094 100644 --- a/lib/validations/user.ts +++ b/lib/validations/user.ts @@ -1,9 +1,9 @@ -import { withValidation } from "next-validations"; -import * as tzdb from "tzdata"; import { z } from "zod"; import { _UserModel as User } from "@calcom/prisma/zod"; +import { timeZone } from "@lib/validations/shared/timeZone"; + // @note: These are the ONLY values allowed as weekStart. So user don't introduce bad data. enum weekdays { MONDAY = "Monday", @@ -74,14 +74,10 @@ export const schemaUserBaseBodyParams = User.pick({ // Here we can both require or not (adding optional or nullish) and also rewrite validations for any value // for example making weekStart only accept weekdays as input -const schemaUserRequiredParams = z.object({ +const schemaUserEditParams = z.object({ weekStart: z.nativeEnum(weekdays).optional(), brandColor: z.string().min(4).max(9).regex(/^#/).optional(), - timeZone: z - .string() - // @note: This is a custom validation that checks if the timezone is valid and exists in the tzdb library - .refine((tz: string) => Object.keys(tzdb.zones).includes(tz)) - .optional(), + timeZone: timeZone.optional(), bufferTime: z.number().min(0).max(86400).optional(), startTime: z.number().min(0).max(86400).optional(), endTime: z.number().min(0).max(86400).optional(), @@ -96,7 +92,7 @@ const schemaUserRequiredParams = z.object({ // @note: These are the values that are editable via PATCH method on the user Model, // merging both BaseBodyParams with RequiredParams, and omiting whatever we want at the end. -export const schemaUserEditBodyParams = schemaUserBaseBodyParams.merge(schemaUserRequiredParams).omit({}); +export const schemaUserEditBodyParams = schemaUserBaseBodyParams.merge(schemaUserEditParams).omit({}); // @note: These are the values that are always returned when reading a user export const schemaUserReadPublic = User.pick({ @@ -123,6 +119,3 @@ export const schemaUserReadPublic = User.pick({ verified: true, invitedTo: true, }); - -// @note: This is the validation for the PATCH method on the user Model. Not used for now. -export const withValidUser = withValidation({ schema: schemaUserEditBodyParams, type: "Zod", mode: "body" }); diff --git a/lib/validations/webhook.ts b/lib/validations/webhook.ts index 746443213d..40b0731507 100644 --- a/lib/validations/webhook.ts +++ b/lib/validations/webhook.ts @@ -1,13 +1,5 @@ -import { withValidation } from "next-validations"; - import { _WebhookModel as Webhook } from "@calcom/prisma/zod"; export const schemaWebhookBodyParams = Webhook.omit({ id: true }).partial(); export const schemaWebhookPublic = Webhook.omit({}); - -export const withValidWebhook = withValidation({ - schema: schemaWebhookBodyParams, - type: "Zod", - mode: "body", -}); diff --git a/pages/api/attendees/[id].ts b/pages/api/attendees/[id].ts index e6780c6929..ce41228cd0 100644 --- a/pages/api/attendees/[id].ts +++ b/pages/api/attendees/[id].ts @@ -4,7 +4,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { AttendeeResponse } from "@lib/types"; -import { schemaAttendeeBodyParams, schemaAttendeePublic } from "@lib/validations/attendee"; +import { schemaAttendeeEditBodyParams, schemaAttendeeReadPublic } from "@lib/validations/attendee"; import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt, @@ -14,7 +14,7 @@ import { * @swagger * /attendees/{id}: * get: - * summary: Get an attendee by ID + * summary: Find an attendee by ID * parameters: * - in: path * name: id @@ -22,6 +22,7 @@ import { * type: integer * required: true * description: Numeric ID of the attendee to get + * example: 3 * security: * - ApiKeyAuth: [] * tags: @@ -37,18 +38,34 @@ import { * summary: Edit an existing attendee * consumes: * - application/json + * requestBody: + * description: Edit an existing attendee related to one of your bookings + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - bookingId + * - name + * - email + * - timeZone + * properties: + * email: + * type: string + * example: email@example.com + * name: + * type: string + * example: John Doe + * timeZone: + * type: string + * example: Europe/London * parameters: - * - in: body - * name: attendee - * description: The attendee to edit - * schema: - * type: object - * $ref: '#/components/schemas/Attendee' - * required: true * - in: path * name: id * schema: * type: integer + * example: 3 * required: true * description: Numeric ID of the attendee to edit * security: @@ -88,7 +105,6 @@ import { export async function attendeeById(req: NextApiRequest, res: NextApiResponse) { const { method, query, body, userId } = req; const safeQuery = schemaQueryIdParseInt.safeParse(query); - const safeBody = schemaAttendeeBodyParams.safeParse(body); if (!safeQuery.success) { res.status(400).json({ error: safeQuery.error }); throw new Error("Invalid request query", safeQuery.error); @@ -106,7 +122,7 @@ export async function attendeeById(req: NextApiRequest, res: NextApiResponse schemaAttendeePublic.parse(data)) + .then((data) => schemaAttendeeReadPublic.parse(data)) .then((attendee) => res.status(200).json({ attendee })) .catch((error: Error) => res.status(404).json({ @@ -117,13 +133,14 @@ export async function attendeeById(req: NextApiRequest, res: NextApiResponse schemaAttendeePublic.parse(data)) + .then((data) => schemaAttendeeReadPublic.parse(data)) .then((attendee) => res.status(200).json({ attendee })) .catch((error: Error) => res.status(404).json({ diff --git a/pages/api/attendees/index.ts b/pages/api/attendees/index.ts index 8705fea6a8..3adbc8a78c 100644 --- a/pages/api/attendees/index.ts +++ b/pages/api/attendees/index.ts @@ -4,13 +4,13 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { AttendeeResponse, AttendeesResponse } from "@lib/types"; -import { schemaAttendeeBodyParams, schemaAttendeePublic, withValidAttendee } from "@lib/validations/attendee"; +import { schemaAttendeeCreateBodyParams, schemaAttendeeReadPublic } from "@lib/validations/attendee"; /** * @swagger * /attendees: * get: - * summary: Get all attendees + * summary: Find all attendees * security: * - ApiKeyAuth: [] * tags: @@ -26,6 +26,33 @@ import { schemaAttendeeBodyParams, schemaAttendeePublic, withValidAttendee } fro * summary: Creates a new attendee * security: * - ApiKeyAuth: [] + * consumes: + * - application/json + * requestBody: + * description: Create a new attendee related to one of your bookings + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - bookingId + * - name + * - email + * - timeZone + * properties: + * bookingId: + * type: number + * example: 1 + * email: + * type: string + * example: email@example.com + * name: + * type: string + * example: John Doe + * timeZone: + * type: string + * example: Europe/London * tags: * - attendees * responses: @@ -61,11 +88,12 @@ async function createOrlistAllAttendees( error, }); } else if (method === "POST") { - const safe = schemaAttendeeBodyParams.safeParse(req.body); - if (!safe.success) { - throw new Error("Invalid request body", safe.error); + const safePost = schemaAttendeeCreateBodyParams.safeParse(req.body); + if (!safePost.success) { + console.log(safePost.error); + res.status(400).json({ error: safePost.error }); + throw new Error("Invalid request body", safePost.error); } - const bookingId = safe.data.bookingId; const userId = req.userId; const userWithBookings = await prisma.user.findUnique({ where: { id: userId }, @@ -76,18 +104,17 @@ async function createOrlistAllAttendees( } const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat(); // Here we make sure to only return attendee's of the user's own bookings. - if (!userBookingIds.includes(parseInt(safe.data.bookingId))) - res.status(401).json({ message: "Unauthorized" }); + if (!userBookingIds.includes(safePost.data.bookingId)) res.status(401).json({ message: "Unauthorized" }); else { - delete safe.data.bookingId; - const noBookingId = safe.data; const data = await prisma.attendee.create({ data: { - ...noBookingId, - booking: { connect: { id: parseInt(bookingId) } }, + email: safePost.data.email, + name: safePost.data.name, + timeZone: safePost.data.timeZone, + booking: { connect: { id: safePost.data.bookingId } }, }, }); - const attendee = schemaAttendeePublic.parse(data); + const attendee = schemaAttendeeReadPublic.parse(data); if (attendee) { res.status(201).json({ diff --git a/pages/api/availabilities/[id].ts b/pages/api/availabilities/[id].ts index cd277b058e..65f750dba7 100644 --- a/pages/api/availabilities/[id].ts +++ b/pages/api/availabilities/[id].ts @@ -4,7 +4,10 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { AvailabilityResponse } from "@lib/types"; -import { schemaAvailabilityBodyParams, schemaAvailabilityPublic } from "@lib/validations/availability"; +import { + schemaAvailabilityEditBodyParams, + schemaAvailabilityReadPublic, +} from "@lib/validations/availability"; import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt, @@ -14,7 +17,7 @@ import { * @swagger * /availabilities/{id}: * get: - * summary: Get an availability by ID + * summary: Find an availability by ID * parameters: * - in: path * name: id @@ -93,7 +96,6 @@ import { */ export async function availabilityById(req: NextApiRequest, res: NextApiResponse) { const { method, query, body } = req; - const safeBody = schemaAvailabilityBodyParams.safeParse(body); const safeQuery = schemaQueryIdParseInt.safeParse(query); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); const userId = req.userId; @@ -105,7 +107,7 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse case "GET": await prisma.availability .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaAvailabilityPublic.parse(data)) + .then((data) => schemaAvailabilityReadPublic.parse(data)) .then((availability) => res.status(200).json({ availability })) .catch((error: Error) => res.status(404).json({ message: `Availability with id: ${safeQuery.data.id} not found`, error }) @@ -113,7 +115,7 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse break; case "PATCH": - + const safeBody = schemaAvailabilityEditBodyParams.safeParse(body); if (!safeBody.success) throw new Error("Invalid request body"); const userEventTypes = await prisma.eventType.findMany({ where: { userId } }); const userEventTypesIds = userEventTypes.map((event) => event.id); @@ -127,7 +129,7 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse where: { id: safeQuery.data.id }, data: safeBody.data, }) - .then((data) => schemaAvailabilityPublic.parse(data)) + .then((data) => schemaAvailabilityReadPublic.parse(data)) .then((availability) => res.status(200).json({ availability })) .catch((error: Error) => { console.log(error); diff --git a/pages/api/availabilities/index.ts b/pages/api/availabilities/index.ts index ab7aa3b388..3e519bc6ad 100644 --- a/pages/api/availabilities/index.ts +++ b/pages/api/availabilities/index.ts @@ -4,13 +4,16 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { AvailabilityResponse, AvailabilitiesResponse } from "@lib/types"; -import { schemaAvailabilityBodyParams, schemaAvailabilityPublic } from "@lib/validations/availability"; +import { + schemaAvailabilityCreateBodyParams, + schemaAvailabilityReadPublic, +} from "@lib/validations/availability"; /** * @swagger * /availabilities: * get: - * summary: Get all availabilities + * summary: Find all availabilities * security: * - ApiKeyAuth: [] * tags: @@ -50,7 +53,7 @@ async function createOrlistAllAvailabilities( if (method === "GET") { const data = await prisma.availability.findMany({ where: { userId } }); - const availabilities = data.map((availability) => schemaAvailabilityPublic.parse(availability)); + const availabilities = data.map((availability) => schemaAvailabilityReadPublic.parse(availability)); if (availabilities) res.status(200).json({ availabilities }); else (error: Error) => @@ -59,13 +62,12 @@ async function createOrlistAllAvailabilities( error, }); } else if (method === "POST") { - console.log(req.body); - const safe = schemaAvailabilityBodyParams.safeParse(req.body); + const safe = schemaAvailabilityCreateBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); const data = await prisma.availability.create({ data: { ...safe.data, userId } }); console.log(data); - const availability = schemaAvailabilityPublic.parse(data); + const availability = schemaAvailabilityReadPublic.parse(data); if (availability) res.status(201).json({ availability, message: "Availability created successfully" }); else diff --git a/pages/api/booking-references/[id].ts b/pages/api/booking-references/[id].ts index 5f08ab4c0d..21b314f728 100644 --- a/pages/api/booking-references/[id].ts +++ b/pages/api/booking-references/[id].ts @@ -6,8 +6,8 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { BookingReferenceResponse } from "@lib/types"; import { - schemaBookingReferenceBodyParams, - schemaBookingReferencePublic, + schemaBookingEditBodyParams, + schemaBookingReferenceReadPublic, } from "@lib/validations/booking-reference"; import { schemaQueryIdParseInt, @@ -18,14 +18,14 @@ import { * @swagger * /booking-references/{id}: * get: - * summary: Get a daily event reference by ID + * summary: Find a booking reference by ID * parameters: * - in: path * name: id * schema: * type: integer * required: true - * description: Numeric ID of the daily event reference to get + * description: Numeric ID of the booking reference to get * security: * - ApiKeyAuth: [] * tags: @@ -38,7 +38,7 @@ import { * 404: * description: BookingReference was not found * patch: - * summary: Edit an existing daily event reference + * summary: Edit an existing booking reference * consumes: * - application/json * parameters: @@ -54,7 +54,7 @@ import { * schema: * type: integer * required: true - * description: Numeric ID of the daily event reference to edit + * description: Numeric ID of the booking reference to edit * security: * - ApiKeyAuth: [] * tags: @@ -68,14 +68,14 @@ import { * 401: * description: Authorization information is missing or invalid. * delete: - * summary: Remove an existing daily event reference + * summary: Remove an existing booking reference * parameters: * - in: path * name: id * schema: * type: integer * required: true - * description: Numeric ID of the daily event reference to delete + * description: Numeric ID of the booking reference to delete * security: * - ApiKeyAuth: [] * tags: @@ -95,7 +95,6 @@ export async function bookingReferenceById( ) { const { method, query, body } = req; const safeQuery = schemaQueryIdParseInt.safeParse(query); - const safeBody = schemaBookingReferenceBodyParams.safeParse(body); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); const userId = req.userId; const userWithBookings = await prisma.user.findUnique({ @@ -111,7 +110,7 @@ export async function bookingReferenceById( case "GET": await prisma.bookingReference .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaBookingReferencePublic.parse(data)) + .then((data) => schemaBookingReferenceReadPublic.parse(data)) .then((booking_reference) => res.status(200).json({ booking_reference })) .catch((error: Error) => res.status(404).json({ @@ -122,12 +121,14 @@ export async function bookingReferenceById( break; case "PATCH": + const safeBody = schemaBookingEditBodyParams.safeParse(body); + if (!safeBody.success) { throw new Error("Invalid request body"); } await prisma.bookingReference .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) - .then((data) => schemaBookingReferencePublic.parse(data)) + .then((data) => schemaBookingReferenceReadPublic.parse(data)) .then((booking_reference) => res.status(200).json({ booking_reference })) .catch((error: Error) => res.status(404).json({ diff --git a/pages/api/booking-references/index.ts b/pages/api/booking-references/index.ts index f77b0c586d..bc82f23701 100644 --- a/pages/api/booking-references/index.ts +++ b/pages/api/booking-references/index.ts @@ -5,15 +5,15 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { BookingReferenceResponse, BookingReferencesResponse } from "@lib/types"; import { - schemaBookingReferenceBodyParams, - schemaBookingReferencePublic, + schemaBookingCreateBodyParams, + schemaBookingReferenceReadPublic, } from "@lib/validations/booking-reference"; /** * @swagger * /booking-references: * get: - * summary: Get all booking references + * summary: Find all booking references * security: * - ApiKeyAuth: [] * tags: @@ -55,7 +55,7 @@ async function createOrlistAllBookingReferences( if (method === "GET") { const data = await prisma.bookingReference.findMany({ where: { id: { in: userBookingIds } } }); const booking_references = data.map((bookingReference) => - schemaBookingReferencePublic.parse(bookingReference) + schemaBookingReferenceReadPublic.parse(bookingReference) ); if (booking_references) res.status(200).json({ booking_references }); else @@ -65,7 +65,7 @@ async function createOrlistAllBookingReferences( error, }); } else if (method === "POST") { - const safe = schemaBookingReferenceBodyParams.safeParse(req.body); + const safe = schemaBookingCreateBodyParams.safeParse(req.body); if (!safe.success) { throw new Error("Invalid request body"); } diff --git a/pages/api/bookings/[id].ts b/pages/api/bookings/[id].ts index c0b74d09f8..21be432cd1 100644 --- a/pages/api/bookings/[id].ts +++ b/pages/api/bookings/[id].ts @@ -4,7 +4,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { BookingResponse } from "@lib/types"; -import { schemaBookingBodyParams, schemaBookingPublic } from "@lib/validations/booking"; +import { schemaBookingEditBodyParams, schemaBookingReadPublic } from "@lib/validations/booking"; import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt, @@ -14,7 +14,7 @@ import { * @swagger * /bookings/{id}: * get: - * summary: Get a booking by ID + * summary: Find a booking by ID * parameters: * - in: path * name: id @@ -88,7 +88,6 @@ import { export async function bookingById(req: NextApiRequest, res: NextApiResponse) { const { method, query, body } = req; const safeQuery = schemaQueryIdParseInt.safeParse(query); - const safeBody = schemaBookingBodyParams.safeParse(body); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); const userId = req.userId; const userWithBookings = await prisma.user.findUnique({ @@ -103,7 +102,7 @@ export async function bookingById(req: NextApiRequest, res: NextApiResponse schemaBookingPublic.parse(data)) + .then((data) => schemaBookingReadPublic.parse(data)) .then((booking) => res.status(200).json({ booking })) .catch((error: Error) => res.status(404).json({ @@ -114,6 +113,8 @@ export async function bookingById(req: NextApiRequest, res: NextApiResponse schemaBookingPublic.parse(data)) + .then((data) => schemaBookingReadPublic.parse(data)) .then((booking) => res.status(200).json({ booking })) .catch((error: Error) => res.status(404).json({ diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index cb0f2089ed..8bb9cae30d 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -4,13 +4,13 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { BookingResponse, BookingsResponse } from "@lib/types"; -import { schemaBookingBodyParams, schemaBookingPublic, withValidBooking } from "@lib/validations/booking"; +import { schemaBookingCreateBodyParams, schemaBookingReadPublic } from "@lib/validations/booking"; /** * @swagger * /bookings: * get: - * summary: Get all bookings + * summary: Find all bookings * security: * - ApiKeyAuth: [] * tags: @@ -46,7 +46,7 @@ async function createOrlistAllBookings( if (method === "GET") { const data = await prisma.booking.findMany({ where: { userId } }); - const bookings = data.map((booking) => schemaBookingPublic.parse(booking)); + const bookings = data.map((booking) => schemaBookingReadPublic.parse(booking)); if (bookings) res.status(200).json({ bookings }); else (error: Error) => @@ -55,11 +55,11 @@ async function createOrlistAllBookings( error, }); } else if (method === "POST") { - const safe = schemaBookingBodyParams.safeParse(req.body); + const safe = schemaBookingCreateBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); const data = await prisma.booking.create({ data: { ...safe.data, userId } }); - const booking = schemaBookingPublic.parse(data); + const booking = schemaBookingReadPublic.parse(data); if (booking) res.status(201).json({ booking, message: "Booking created successfully" }); else diff --git a/pages/api/daily-event-references/[id].ts b/pages/api/daily-event-references/[id].ts index 280ad0c623..6ef4ac01e2 100644 --- a/pages/api/daily-event-references/[id].ts +++ b/pages/api/daily-event-references/[id].ts @@ -5,8 +5,8 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { DailyEventReferenceResponse } from "@lib/types"; import { - schemaDailyEventReferenceBodyParams, - schemaDailyEventReferencePublic, + schemaDailyEventReferenceEditBodyParams, + schemaDailyEventReferenceReadPublic, } from "@lib/validations/daily-event-reference"; import { schemaQueryIdParseInt, @@ -17,7 +17,7 @@ import { * @swagger * /daily-event-references/{id}: * get: - * summary: Get a daily event reference by ID + * summary: Find a daily event reference by ID * parameters: * - in: path * name: id @@ -94,7 +94,7 @@ export async function dailyEventReferenceById( ) { const { method, query, body } = req; const safeQuery = schemaQueryIdParseInt.safeParse(query); - const safeBody = schemaDailyEventReferenceBodyParams.safeParse(body); + const safeBody = schemaDailyEventReferenceEditBodyParams.safeParse(body); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); const userId = req.userId; const userBookings = await prisma.booking.findMany({ where: { userId } }); @@ -112,7 +112,7 @@ export async function dailyEventReferenceById( case "GET": await prisma.dailyEventReference .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaDailyEventReferencePublic.parse(data)) + .then((data) => schemaDailyEventReferenceReadPublic.parse(data)) .then((daily_event_reference) => res.status(200).json({ daily_event_reference })) .catch((error: Error) => res.status(404).json({ @@ -128,7 +128,7 @@ export async function dailyEventReferenceById( } await prisma.dailyEventReference .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) - .then((data) => schemaDailyEventReferencePublic.parse(data)) + .then((data) => schemaDailyEventReferenceReadPublic.parse(data)) .then((daily_event_reference) => res.status(200).json({ daily_event_reference })) .catch((error: Error) => res.status(404).json({ diff --git a/pages/api/daily-event-references/index.ts b/pages/api/daily-event-references/index.ts index 670b18421c..dfafe246ce 100644 --- a/pages/api/daily-event-references/index.ts +++ b/pages/api/daily-event-references/index.ts @@ -5,15 +5,15 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { DailyEventReferenceResponse, DailyEventReferencesResponse } from "@lib/types"; import { - schemaDailyEventReferenceBodyParams, - schemaDailyEventReferencePublic, + schemaDailyEventReferenceCreateBodyParams, + schemaDailyEventReferenceReadPublic, } from "@lib/validations/daily-event-reference"; /** * @swagger * /daily-event-references: * get: - * summary: Get all daily event reference + * summary: Find all daily event reference * security: * - ApiKeyAuth: [] * tags: @@ -54,7 +54,7 @@ async function createOrlistAllDailyEventReferences( where: { bookingId: { in: userBookingIds } }, }); const daily_event_references = data.map((dailyEventReference) => - schemaDailyEventReferencePublic.parse(dailyEventReference) + schemaDailyEventReferenceReadPublic.parse(dailyEventReference) ); if (daily_event_references) res.status(200).json({ daily_event_references }); else @@ -64,11 +64,11 @@ async function createOrlistAllDailyEventReferences( error, }); } else if (method === "POST") { - const safe = schemaDailyEventReferenceBodyParams.safeParse(req.body); + const safe = schemaDailyEventReferenceCreateBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); const data = await prisma.dailyEventReference.create({ data: safe.data }); - const daily_event_reference = schemaDailyEventReferencePublic.parse(data); + const daily_event_reference = schemaDailyEventReferenceReadPublic.parse(data); if (daily_event_reference) res.status(201).json({ daily_event_reference, message: "DailyEventReference created successfully" }); diff --git a/pages/api/destination-calendars/[id].ts b/pages/api/destination-calendars/[id].ts index f5ba4d90ee..60982a7058 100644 --- a/pages/api/destination-calendars/[id].ts +++ b/pages/api/destination-calendars/[id].ts @@ -5,8 +5,8 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { DestinationCalendarResponse } from "@lib/types"; import { - schemaDestinationCalendarBodyParams, - schemaDestinationCalendarPublic, + schemaDestinationCalendarEditBodyParams, + schemaDestinationCalendarReadPublic, } from "@lib/validations/destination-calendar"; import { schemaQueryIdParseInt, @@ -17,7 +17,7 @@ import { * @swagger * /destination-calendars/{id}: * get: - * summary: Get a destination calendar by ID + * summary: Find a destination calendar by ID * parameters: * - in: path * name: id @@ -94,7 +94,7 @@ export async function destionationCalendarById( ) { const { method, query, body } = req; const safeQuery = schemaQueryIdParseInt.safeParse(query); - const safeBody = schemaDestinationCalendarBodyParams.safeParse(body); + const safeBody = schemaDestinationCalendarEditBodyParams.safeParse(body); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); const userId = req.userId; const data = await prisma.destinationCalendar.findMany({ where: { userId } }); @@ -107,7 +107,7 @@ export async function destionationCalendarById( case "GET": await prisma.destinationCalendar .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaDestinationCalendarPublic.parse(data)) + .then((data) => schemaDestinationCalendarReadPublic.parse(data)) .then((destination_calendar) => res.status(200).json({ destination_calendar })) .catch((error: Error) => res.status(404).json({ @@ -123,7 +123,7 @@ export async function destionationCalendarById( } await prisma.destinationCalendar .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) - .then((data) => schemaDestinationCalendarPublic.parse(data)) + .then((data) => schemaDestinationCalendarReadPublic.parse(data)) .then((destination_calendar) => res.status(200).json({ destination_calendar })) .catch((error: Error) => res.status(404).json({ diff --git a/pages/api/destination-calendars/index.ts b/pages/api/destination-calendars/index.ts index 782612518c..d7921491c9 100644 --- a/pages/api/destination-calendars/index.ts +++ b/pages/api/destination-calendars/index.ts @@ -5,15 +5,15 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { DestinationCalendarResponse, DestinationCalendarsResponse } from "@lib/types"; import { - schemaDestinationCalendarBodyParams, - schemaDestinationCalendarPublic, + schemaDestinationCalendarCreateBodyParams, + schemaDestinationCalendarReadPublic, } from "@lib/validations/destination-calendar"; /** * @swagger * /destination-calendars: * get: - * summary: Get all destination calendars + * summary: Find all destination calendars * security: * - ApiKeyAuth: [] * tags: @@ -50,7 +50,7 @@ async function createOrlistAllDestinationCalendars( if (method === "GET") { const data = await prisma.destinationCalendar.findMany({ where: { userId } }); const destination_calendars = data.map((destinationCalendar) => - schemaDestinationCalendarPublic.parse(destinationCalendar) + schemaDestinationCalendarReadPublic.parse(destinationCalendar) ); if (data) res.status(200).json({ destination_calendars }); else @@ -60,11 +60,11 @@ async function createOrlistAllDestinationCalendars( error, }); } else if (method === "POST") { - const safe = schemaDestinationCalendarBodyParams.safeParse(req.body); + const safe = schemaDestinationCalendarCreateBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); const data = await prisma.destinationCalendar.create({ data: { ...safe.data, userId } }); - const destination_calendar = schemaDestinationCalendarPublic.parse(data); + const destination_calendar = schemaDestinationCalendarReadPublic.parse(data); if (destination_calendar) res.status(201).json({ destination_calendar, message: "DestinationCalendar created successfully" }); diff --git a/pages/api/docs.ts b/pages/api/docs.ts index 25d9c7ce1b..7dd7afa65d 100644 --- a/pages/api/docs.ts +++ b/pages/api/docs.ts @@ -20,6 +20,7 @@ const swaggerHandler = withSwagger({ }, components: { securitySchemes: { ApiKeyAuth: { type: "apiKey", in: "query", name: "apiKey" } }, + security: { ApiKeyAuth: [] }, schemas: { ...jsonSchema.definitions }, }, }, diff --git a/pages/api/event-type-custom-inputs/[id].ts b/pages/api/event-type-custom-inputs/[id].ts index 23e4c73a9a..7d3ffa7a5d 100644 --- a/pages/api/event-type-custom-inputs/[id].ts +++ b/pages/api/event-type-custom-inputs/[id].ts @@ -17,7 +17,7 @@ import { * @swagger * /event-type-custom-inputs/{id}: * get: - * summary: Get a eventTypeCustomInput by ID + * summary: Find a eventTypeCustomInput by ID * parameters: * - in: path * name: id diff --git a/pages/api/event-type-custom-inputs/index.ts b/pages/api/event-type-custom-inputs/index.ts index f1931b8b12..01f5af921f 100644 --- a/pages/api/event-type-custom-inputs/index.ts +++ b/pages/api/event-type-custom-inputs/index.ts @@ -13,7 +13,7 @@ import { * @swagger * /event-type-custom-inputs: * get: - * summary: Get all eventTypeCustomInputs + * summary: Find all eventTypeCustomInputs * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/event-types/[id].ts b/pages/api/event-types/[id].ts index 465e85b428..37a5b38be7 100644 --- a/pages/api/event-types/[id].ts +++ b/pages/api/event-types/[id].ts @@ -14,7 +14,7 @@ import { * @swagger * /event-types/{id}: * get: - * summary: Get a eventType by ID + * summary: Find a eventType by ID * parameters: * - in: path * name: id diff --git a/pages/api/event-types/index.ts b/pages/api/event-types/index.ts index 9d73be9458..9e1e83c038 100644 --- a/pages/api/event-types/index.ts +++ b/pages/api/event-types/index.ts @@ -10,7 +10,7 @@ import { schemaEventTypeBodyParams, schemaEventTypePublic } from "@lib/validatio * @swagger * /event-types: * get: - * summary: Get all event types + * summary: Find all event types * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/index.ts b/pages/api/index.ts index 94461cedce..3f72b7eaef 100644 --- a/pages/api/index.ts +++ b/pages/api/index.ts @@ -1,5 +1,10 @@ import type { NextApiRequest, NextApiResponse } from "next"; +/** + * @swagger + * security: + * - ApiKeyAuth: [] + */ export default async function CalcomApi(_: NextApiRequest, res: NextApiResponse) { res.status(201).json({ message: "Welcome to Cal.com API - docs are at https://docs.cal.com/api" }); } diff --git a/pages/api/memberships/[id].ts b/pages/api/memberships/[id].ts index c4a1d362f7..0e7498d16c 100644 --- a/pages/api/memberships/[id].ts +++ b/pages/api/memberships/[id].ts @@ -11,7 +11,7 @@ import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/ * @swagger * /memberships/{userId}_{teamId}: * get: - * summary: Get a membership by userID and teamID + * summary: Find a membership by userID and teamID * parameters: * - in: path * name: userId diff --git a/pages/api/memberships/index.ts b/pages/api/memberships/index.ts index 702effdfd6..3df3b56d13 100644 --- a/pages/api/memberships/index.ts +++ b/pages/api/memberships/index.ts @@ -10,7 +10,7 @@ import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validat * @swagger * /memberships: * get: - * summary: Get all memberships + * summary: Find all memberships * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/payments/[id].ts b/pages/api/payments/[id].ts index 6ccf227641..8ab4d5eab9 100644 --- a/pages/api/payments/[id].ts +++ b/pages/api/payments/[id].ts @@ -14,7 +14,7 @@ import { * @swagger * /payments/{id}: * get: - * summary: Get one of your own payments by ID + * summary: Find one of your own payments by ID * parameters: * - in: path * name: id diff --git a/pages/api/payments/index.ts b/pages/api/payments/index.ts index 2b00d85ebb..db0cd349ca 100644 --- a/pages/api/payments/index.ts +++ b/pages/api/payments/index.ts @@ -10,7 +10,7 @@ import { schemaPaymentPublic } from "@lib/validations/payment"; * @swagger * /payments: * get: - * summary: Get all payments + * summary: Find all payments * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/schedules/[id].ts b/pages/api/schedules/[id].ts index 154dfa41f1..8a08128f4f 100644 --- a/pages/api/schedules/[id].ts +++ b/pages/api/schedules/[id].ts @@ -14,7 +14,7 @@ import { * @swagger * /schedules/{id}: * get: - * summary: Get a schedule by ID + * summary: Find a schedule by ID * parameters: * - in: path * name: id diff --git a/pages/api/schedules/index.ts b/pages/api/schedules/index.ts index d04d35cccb..228599eef3 100644 --- a/pages/api/schedules/index.ts +++ b/pages/api/schedules/index.ts @@ -4,13 +4,13 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { ScheduleResponse, SchedulesResponse } from "@lib/types"; -import { schemaScheduleBodyParams, schemaSchedulePublic, withValidSchedule } from "@lib/validations/schedule"; +import { schemaScheduleBodyParams, schemaSchedulePublic } from "@lib/validations/schedule"; /** * @swagger * /schedules: * get: - * summary: Get all schedules + * summary: Find all schedules * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/selected-calendars/[id].ts b/pages/api/selected-calendars/[id].ts index 1b3e5e9cd5..6efbca86ee 100644 --- a/pages/api/selected-calendars/[id].ts +++ b/pages/api/selected-calendars/[id].ts @@ -14,7 +14,7 @@ import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/ * @swagger * /selected-calendars/{userId}_{integration}_{externalId}: * get: - * summary: Get a selected-calendar by userID and teamID + * summary: Find a selected-calendar by userID and teamID * parameters: * - in: path * name: userId diff --git a/pages/api/selected-calendars/index.ts b/pages/api/selected-calendars/index.ts index d9b80a8541..83537208ba 100644 --- a/pages/api/selected-calendars/index.ts +++ b/pages/api/selected-calendars/index.ts @@ -13,7 +13,7 @@ import { * @swagger * /selected-calendars: * get: - * summary: Get all selected calendars + * summary: Find all selected calendars * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/teams/[id].ts b/pages/api/teams/[id].ts index 2990d3642b..0fead8e066 100644 --- a/pages/api/teams/[id].ts +++ b/pages/api/teams/[id].ts @@ -14,7 +14,7 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team"; * @swagger * /teams/{id}: * get: - * summary: Get a team by ID + * summary: Find a team by ID * parameters: * - in: path * name: id diff --git a/pages/api/teams/index.ts b/pages/api/teams/index.ts index d6392e0c1b..ce335fff9d 100644 --- a/pages/api/teams/index.ts +++ b/pages/api/teams/index.ts @@ -5,13 +5,13 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { TeamResponse, TeamsResponse } from "@lib/types"; import { schemaMembershipPublic } from "@lib/validations/membership"; -import { schemaTeamBodyParams, schemaTeamPublic, withValidTeam } from "@lib/validations/team"; +import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team"; /** * @swagger * /teams: * get: - * summary: Get all teams + * summary: Find all teams * security: * - ApiKeyAuth: [] * tags: diff --git a/pages/api/users/[id].ts b/pages/api/users/[id].ts index 24bf1075ed..06e5612dd0 100644 --- a/pages/api/users/[id].ts +++ b/pages/api/users/[id].ts @@ -8,13 +8,13 @@ import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt, } from "@lib/validations/shared/queryIdTransformParseInt"; -import { schemaUserEditBodyParams, schemaUserReadPublic, withValidUser } from "@lib/validations/user"; +import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations/user"; /** * @swagger * /users/{id}: * get: - * summary: Get a user by ID, returns your user if regular user. + * summary: Find a user by ID, returns your user if regular user. * parameters: * - in: path * name: id diff --git a/pages/api/users/index.ts b/pages/api/users/index.ts index aa35dca042..fa28b36f5e 100644 --- a/pages/api/users/index.ts +++ b/pages/api/users/index.ts @@ -10,7 +10,7 @@ import { schemaUserReadPublic } from "@lib/validations/user"; * @swagger * /users: * get: - * summary: Get all users (admin only), returns your user if regular user. + * summary: Find all users (admin only), returns your user if regular user. * security: * - ApiKeyAuth: [] * tags: diff --git a/templates/endpoints/[id]/delete.ts b/templates/endpoints/[id]/delete.ts index 5cf646aee0..9c5c6f9f7c 100644 --- a/templates/endpoints/[id]/delete.ts +++ b/templates/endpoints/[id]/delete.ts @@ -22,7 +22,7 @@ import { * required: true * description: Numeric ID of the resource to delete * security: - * - ApiKeyAuth: [] + * - ApiKeyAuth: [] * tags: * - resources * responses: diff --git a/templates/endpoints/[id]/edit.ts b/templates/endpoints/[id]/edit.ts index 54b8fec540..8ddad4601d 100644 --- a/templates/endpoints/[id]/edit.ts +++ b/templates/endpoints/[id]/edit.ts @@ -23,7 +23,7 @@ import { * required: true * description: Numeric ID of the resource to edit * security: - * - ApiKeyAuth: [] + * - ApiKeyAuth: [] * tags: * - resources * responses: diff --git a/templates/endpoints/[id]/index.ts b/templates/endpoints/[id]/index.ts index 66e7ab105c..9f4c64f11d 100644 --- a/templates/endpoints/[id]/index.ts +++ b/templates/endpoints/[id]/index.ts @@ -14,7 +14,7 @@ import { * @swagger * /v1/resources/{id}: * get: - * summary: Get a resource by ID + * summary: Find a resource by ID * parameters: * - in: path * name: id diff --git a/templates/endpoints/get_all.ts b/templates/endpoints/get_all.ts index b3b9257e9a..ee66e7c773 100644 --- a/templates/endpoints/get_all.ts +++ b/templates/endpoints/get_all.ts @@ -10,7 +10,7 @@ import { schemaResourcePublic } from "@lib/validations/resource"; * @swagger * /v1/resources: * get: - * summary: Get all resources + * summary: Find all resources * security: * - ApiKeyAuth: [] * tags: diff --git a/templates/endpoints/get_all_and_post.ts b/templates/endpoints/get_all_and_post.ts index bf6fee016f..2ce4b8dfe9 100644 --- a/templates/endpoints/get_all_and_post.ts +++ b/templates/endpoints/get_all_and_post.ts @@ -10,7 +10,7 @@ import { schemaPaymentBodyParams, schemaPaymentPublic } from "@lib/validations/p * @swagger * /v1/payments: * get: - * summary: Get all payments + * summary: Find all payments * security: * - ApiKeyAuth: [] * tags: diff --git a/templates/endpoints/post.ts b/templates/endpoints/post.ts index e2b9e17683..999bce39c1 100644 --- a/templates/endpoints/post.ts +++ b/templates/endpoints/post.ts @@ -19,7 +19,7 @@ import { schemaResourceBodyParams, schemaResourcePublic, withValidResource } fro * schema: * $ref: '#/components/schemas/Resource' * security: - * - ApiKeyAuth: [] + * - ApiKeyAuth: [] * tags: * - resources * responses: diff --git a/templates/zod-validation.ts b/templates/zod-validation.ts index 02b0597529..82a95a97d1 100644 --- a/templates/zod-validation.ts +++ b/templates/zod-validation.ts @@ -1,4 +1,3 @@ -import { withValidation } from "next-validations"; import { z } from "zod"; import { _ModelModel as Model } from "@calcom/prisma/zod"; @@ -15,9 +14,3 @@ export const schemaModelPublic = Model.omit({ id: true, userId: true, }); - -export const withValidModel = withValidation({ - schema: schemaModelBodyParams, - type: "Zod", - mode: "body", -});