From cd03f5a821e4271df3291b4f1603d1574de9f269 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:06:28 +0530 Subject: [PATCH 01/36] Adds team event type check --- pages/api/hooks/[id].ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pages/api/hooks/[id].ts b/pages/api/hooks/[id].ts index 32a81e7b12..3a14efa592 100644 --- a/pages/api/hooks/[id].ts +++ b/pages/api/hooks/[id].ts @@ -95,6 +95,27 @@ export async function WebhookById( return; } } + if (safeBody.data.eventTypeId) { + const team = await ctx.prisma.team.findFirst({ + where: { + eventTypes: { + some: { + id: safeBody.data.eventTypeId, + }, + }, + }, + include: { + members: true, + }, + }); + + // Team should be available and the user should be a member of the team + if (!team?.members.some((membership) => membership.userId === userId)) { + throw new TRPCError({ + code: "UNAUTHORIZED", + }); + } + } await prisma.webhook .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) .then((data) => schemaWebhookReadPublic.parse(data)) From bae84f2ce4e7daa9fcc3c8984a18997946cdab20 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:12:05 +0530 Subject: [PATCH 02/36] Added team event check to POST --- pages/api/hooks/index.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pages/api/hooks/index.ts b/pages/api/hooks/index.ts index 422a30e419..e92a681080 100644 --- a/pages/api/hooks/index.ts +++ b/pages/api/hooks/index.ts @@ -61,6 +61,27 @@ async function createOrlistAllWebhooks( res.status(400).json({ message: "Invalid request body" }); return; } + if (safe.data.eventTypeId) { + const team = await ctx.prisma.team.findFirst({ + where: { + eventTypes: { + some: { + id: safe.data.eventTypeId, + }, + }, + }, + include: { + members: true, + }, + }); + + // Team should be available and the user should be a member of the team + if (!team?.members.some((membership) => membership.userId === userId)) { + throw new TRPCError({ + code: "UNAUTHORIZED", + }); + } + } const data = await prisma.webhook.create({ data: { id: uuidv4(), ...safe.data, userId } }); if (data) res.status(201).json({ webhook: data, message: "Webhook created successfully" }); else From ef3838b4764cf57d9928fa6581f814652627248b Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:20:09 +0530 Subject: [PATCH 03/36] hotfix ctx removal --- pages/api/hooks/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/hooks/index.ts b/pages/api/hooks/index.ts index e92a681080..f3f3257499 100644 --- a/pages/api/hooks/index.ts +++ b/pages/api/hooks/index.ts @@ -62,7 +62,7 @@ async function createOrlistAllWebhooks( return; } if (safe.data.eventTypeId) { - const team = await ctx.prisma.team.findFirst({ + const team = await prisma.team.findFirst({ where: { eventTypes: { some: { From b881312f1038ea9b67afa52c6a01a9c3c07f8028 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:20:44 +0530 Subject: [PATCH 04/36] hotfix ctx removal --- pages/api/hooks/[id].ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/hooks/[id].ts b/pages/api/hooks/[id].ts index 3a14efa592..7debc7ac8d 100644 --- a/pages/api/hooks/[id].ts +++ b/pages/api/hooks/[id].ts @@ -96,7 +96,7 @@ export async function WebhookById( } } if (safeBody.data.eventTypeId) { - const team = await ctx.prisma.team.findFirst({ + const team = await prisma.team.findFirst({ where: { eventTypes: { some: { From 9b1dffbdb9e64969c79d87c892e4a0083e8e64f1 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:27:48 +0530 Subject: [PATCH 05/36] 401 return fix --- pages/api/hooks/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pages/api/hooks/index.ts b/pages/api/hooks/index.ts index f3f3257499..ec85ab13df 100644 --- a/pages/api/hooks/index.ts +++ b/pages/api/hooks/index.ts @@ -77,9 +77,8 @@ async function createOrlistAllWebhooks( // Team should be available and the user should be a member of the team if (!team?.members.some((membership) => membership.userId === userId)) { - throw new TRPCError({ - code: "UNAUTHORIZED", - }); + res.status(401).json({ message: "Unauthorized" }); + return; } } const data = await prisma.webhook.create({ data: { id: uuidv4(), ...safe.data, userId } }); From db6f5cad1512ac6d6efc8b4c9368634ebcde348b Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:28:22 +0530 Subject: [PATCH 06/36] 401 message fix --- pages/api/hooks/[id].ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pages/api/hooks/[id].ts b/pages/api/hooks/[id].ts index 7debc7ac8d..8f81fc62d1 100644 --- a/pages/api/hooks/[id].ts +++ b/pages/api/hooks/[id].ts @@ -111,9 +111,8 @@ export async function WebhookById( // Team should be available and the user should be a member of the team if (!team?.members.some((membership) => membership.userId === userId)) { - throw new TRPCError({ - code: "UNAUTHORIZED", - }); + res.status(401).json({ message: "Unauthorized" }); + return; } } await prisma.webhook From d569296654495621b0475a4636fa9ac937cccd56 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Thu, 9 Jun 2022 17:09:20 +0530 Subject: [PATCH 07/36] Add webhook trigger --init --- pages/api/bookings/index.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 40f24283ee..1951e4475d 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -81,7 +81,31 @@ async function createOrlistAllBookings( const data = await prisma.booking.create({ data: { ...safe.data } }); const booking = schemaBookingReadPublic.parse(data); - if (booking) res.status(201).json({ booking, message: "Booking created successfully" }); + if (booking) { + res.status(201).json({ booking, message: "Booking created successfully" }); + + // Send Webhook call if hooked to BOOKING_CREATED & BOOKING_RESCHEDULED +// const eventTrigger: WebhookTriggerEvents = rescheduleUid ? "BOOKING_RESCHEDULED" : "BOOKING_CREATED"; +// const subscriberOptions = { +// userId: user.id, +// eventTypeId, +// triggerEvent: eventTrigger, +// }; + +// const subscribers = await getSubscribers(subscriberOptions); +// const bookingId = booking?.id; +// const promises = subscribers.map((sub) => +// sendPayload(eventTrigger, new Date().toISOString(), sub, { +// ...evt, +// bookingId, +// rescheduleUid, +// metadata: reqBody.metadata, +// }).catch((e) => { +// console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`, e); +// }) +// ); +// await Promise.all(promises); + } else (error: Error) => { console.log(error); From cd482cd91a44a4631bb0be0bce4b82968c4c5068 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Fri, 10 Jun 2022 11:40:38 +0530 Subject: [PATCH 08/36] Add getWebhook function --- lib/utils/webhookSubscriptions.ts | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/utils/webhookSubscriptions.ts diff --git a/lib/utils/webhookSubscriptions.ts b/lib/utils/webhookSubscriptions.ts new file mode 100644 index 0000000000..bdf9d95576 --- /dev/null +++ b/lib/utils/webhookSubscriptions.ts @@ -0,0 +1,42 @@ +import { WebhookTriggerEvents } from "@prisma/client"; + +import prisma from "@calcom/prisma"; + +export type GetSubscriberOptions = { + userId: number; + eventTypeId: number; + triggerEvent: WebhookTriggerEvents; +}; + +const getWebhooks = async (options: GetSubscriberOptions) => { + const { userId, eventTypeId } = options; + const allWebhooks = await prisma.webhook.findMany({ + where: { + OR: [ + { + userId, + }, + { + eventTypeId, + }, + ], + AND: { + eventTriggers: { + has: options.triggerEvent, + }, + active: { + equals: true, + }, + }, + }, + select: { + subscriberUrl: true, + payloadTemplate: true, + appId: true, + }, + }); + + return allWebhooks; +}; + +export default getWebhooks; From 664e697d40bc24232102221ed52443562f0b01b5 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Fri, 10 Jun 2022 11:42:01 +0530 Subject: [PATCH 09/36] add sendPayload file --- lib/utils/sendPayload.ts | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lib/utils/sendPayload.ts diff --git a/lib/utils/sendPayload.ts b/lib/utils/sendPayload.ts new file mode 100644 index 0000000000..62cc3f96d2 --- /dev/null +++ b/lib/utils/sendPayload.ts @@ -0,0 +1,77 @@ +import { Webhook } from "@prisma/client"; +import { compile } from "handlebars"; + +import type { CalendarEvent } from "@calcom/types/Calendar"; + +type ContentType = "application/json" | "application/x-www-form-urlencoded"; + +function applyTemplate(template: string, data: CalendarEvent, contentType: ContentType) { + const compiled = compile(template)(data); + if (contentType === "application/json") { + return JSON.stringify(jsonParse(compiled)); + } + return compiled; +} + +function jsonParse(jsonString: string) { + try { + return JSON.parse(jsonString); + } catch (e) { + // don't do anything. + } + return false; +} + +const sendPayload = async ( + triggerEvent: string, + createdAt: string, + webhook: Pick, + data: CalendarEvent & { + metadata?: { [key: string]: string }; + rescheduleUid?: string; + bookingId?: number; + } +) => { + const { subscriberUrl, appId, payloadTemplate: template } = webhook; + if (!subscriberUrl || !data) { + throw new Error("Missing required elements to send webhook payload."); + } + + const contentType = + !template || jsonParse(template) ? "application/json" : "application/x-www-form-urlencoded"; + + data.description = data.description || data.additionalNotes; + + let body; + + /* Zapier id is hardcoded in the DB, we send the raw data for this case */ + if (appId === "zapier") { + body = JSON.stringify(data); + } else if (template) { + body = applyTemplate(template, data, contentType); + } else { + body = JSON.stringify({ + triggerEvent: triggerEvent, + createdAt: createdAt, + payload: data, + }); + } + + const response = await fetch(subscriberUrl, { + method: "POST", + headers: { + "Content-Type": contentType, + }, + body, + }); + + const text = await response.text(); + + return { + ok: response.ok, + status: response.status, + message: text, + }; +}; + +export default sendPayload; From 542beb007938450ab0365aa4c6367a27cf6b5386 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Fri, 10 Jun 2022 11:46:51 +0530 Subject: [PATCH 10/36] adjust booking file --- pages/api/bookings/index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 1951e4475d..2ee5c2da1c 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -84,15 +84,17 @@ async function createOrlistAllBookings( if (booking) { res.status(201).json({ booking, message: "Booking created successfully" }); - // Send Webhook call if hooked to BOOKING_CREATED & BOOKING_RESCHEDULED -// const eventTrigger: WebhookTriggerEvents = rescheduleUid ? "BOOKING_RESCHEDULED" : "BOOKING_CREATED"; +// Create Calendar Event for webhook payload + +// Send Webhook call if hooked to BOOKING_CREATED & BOOKING_RESCHEDULED +// const eventTrigger = WebhookTriggerEvents.BOOKING_CREATED; // const subscriberOptions = { // userId: user.id, // eventTypeId, // triggerEvent: eventTrigger, // }; -// const subscribers = await getSubscribers(subscriberOptions); +// const subscribers = await getWebhooks(subscriberOptions); // const bookingId = booking?.id; // const promises = subscribers.map((sub) => // sendPayload(eventTrigger, new Date().toISOString(), sub, { From 804de678680f2fa991c904e1f0fb62f96a53bee5 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Fri, 10 Jun 2022 12:17:00 +0530 Subject: [PATCH 11/36] Add eventName file --- lib/utils/eventName.ts | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 lib/utils/eventName.ts diff --git a/lib/utils/eventName.ts b/lib/utils/eventName.ts new file mode 100644 index 0000000000..5d7865fe94 --- /dev/null +++ b/lib/utils/eventName.ts @@ -0,0 +1,62 @@ +import { TFunction } from "next-i18next"; + +type EventNameObjectType = { + attendeeName: string; + eventType: string; + eventName?: string | null; + host: string; + location?: string; + t: TFunction; +}; + +export function getEventName(eventNameObj: EventNameObjectType, forAttendeeView = false) { + if (!eventNameObj.eventName) + return eventNameObj.t("event_between_users", { + eventName: eventNameObj.eventType, + host: eventNameObj.host, + attendeeName: eventNameObj.attendeeName, + }); + + let eventName = eventNameObj.eventName; + let locationString = ""; + + if (eventNameObj.eventName.includes("{LOCATION}")) { + switch (eventNameObj.location) { + case "inPerson": + locationString = "In Person"; + break; + case "userPhone": + case "phone": + locationString = "Phone"; + break; + case "integrations:daily": + locationString = "Cal Video"; + break; + case "integrations:zoom": + locationString = "Zoom"; + break; + case "integrations:huddle01": + locationString = "Huddle01"; + break; + case "integrations:tandem": + locationString = "Tandem"; + break; + case "integrations:office365_video": + locationString = "MS Teams"; + break; + case "integrations:jitsi": + locationString = "Jitsi"; + break; + } + eventName = eventName.replace("{LOCATION}", locationString); + } + + return ( + eventName + // Need this for compatibility with older event names + .replace("{USER}", eventNameObj.attendeeName) + .replace("{ATTENDEE}", eventNameObj.attendeeName) + .replace("{HOST}", eventNameObj.host) + .replace("{HOST/ATTENDEE}", forAttendeeView ? eventNameObj.host : eventNameObj.attendeeName) + ); +} From e3822c50d0998312929a3c6b58e9c728c16a58ed Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Fri, 10 Jun 2022 12:43:41 +0530 Subject: [PATCH 12/36] Update booking file with webhook payload --- pages/api/bookings/index.ts | 78 +++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 2ee5c2da1c..f3b9e8c027 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -2,9 +2,14 @@ import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@calcom/prisma"; +import { WebhookTriggerEvents } from "@prisma/client"; + import { withMiddleware } from "@lib/helpers/withMiddleware"; +import sendPayload from "@lib/utils/sendPayload"; +import getWebhooks from "@lib/utils/webhookSubscriptions"; import { BookingResponse, BookingsResponse } from "@lib/types"; import { schemaBookingCreateBodyParams, schemaBookingReadPublic } from "@lib/validations/booking"; +import { schemaEventTypeReadPublic } from "@lib/validations/event-type"; async function createOrlistAllBookings( { method, body, userId }: NextApiRequest, @@ -84,29 +89,60 @@ async function createOrlistAllBookings( if (booking) { res.status(201).json({ booking, message: "Booking created successfully" }); -// Create Calendar Event for webhook payload + // Create Calendar Event for webhook payload + const eventType = await prisma.eventType + .findUnique({ where: { id: booking?.eventTypeId } }) + .then((data) => schemaEventTypeReadPublic.parse(data)) + .then((event_type) => res.status(200).json({ event_type })) + .catch((error: Error) => + res.status(404).json({ + message: `EventType with id: ${booking?.eventTypeId} not found`, + error, + }) + ); + const evt = { + type: eventType.title, + title: booking.title, + description: "", + additionalNotes: "", + customInputs: {}, + startTime: booking.startTime, + endTime: booking.endTime, + organizer: { + name: "", + email: "", + timezone: "", + language: { + locale: "en" + } + }, + attendees: [], + location: "", + destinationCalendar: null, + hideCalendar: false, + uid: booking.uid, + metadata: {} + }; -// Send Webhook call if hooked to BOOKING_CREATED & BOOKING_RESCHEDULED -// const eventTrigger = WebhookTriggerEvents.BOOKING_CREATED; -// const subscriberOptions = { -// userId: user.id, -// eventTypeId, -// triggerEvent: eventTrigger, -// }; + // Send Webhook call if hooked to BOOKING_CREATED + const triggerEvent = WebhookTriggerEvents.BOOKING_CREATED; + const subscriberOptions = { + userId, + eventTypeId: eventType.id, + triggerEvent, + }; -// const subscribers = await getWebhooks(subscriberOptions); -// const bookingId = booking?.id; -// const promises = subscribers.map((sub) => -// sendPayload(eventTrigger, new Date().toISOString(), sub, { -// ...evt, -// bookingId, -// rescheduleUid, -// metadata: reqBody.metadata, -// }).catch((e) => { -// console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`, e); -// }) -// ); -// await Promise.all(promises); + const subscribers = await getWebhooks(subscriberOptions); + const bookingId = booking?.id; + const promises = subscribers.map((sub) => + sendPayload(eventTrigger, new Date().toISOString(), sub, { + ...evt, + bookingId, + }).catch((e) => { + console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`, e); + }) + ); + await Promise.all(promises); } else (error: Error) => { From 4f3668100691dfb0f4fe8c622fd8bce513eed679 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 12:51:24 +0530 Subject: [PATCH 13/36] --fix --- pages/api/bookings/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index f3b9e8c027..2a11672e32 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -135,11 +135,11 @@ async function createOrlistAllBookings( const subscribers = await getWebhooks(subscriberOptions); const bookingId = booking?.id; const promises = subscribers.map((sub) => - sendPayload(eventTrigger, new Date().toISOString(), sub, { + sendPayload(triggerEvent, new Date().toISOString(), sub, { ...evt, bookingId, }).catch((e) => { - console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`, e); + console.error(`Error executing webhook for event: ${triggerEvent}, URL: ${sub.subscriberUrl}`, e); }) ); await Promise.all(promises); From f9c20bc8ce3544508585d8bb0fece077994da833 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 12:53:59 +0530 Subject: [PATCH 14/36] --fix null estimated value --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 2a11672e32..73c4e8d12b 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -91,7 +91,7 @@ async function createOrlistAllBookings( // Create Calendar Event for webhook payload const eventType = await prisma.eventType - .findUnique({ where: { id: booking?.eventTypeId } }) + .findUnique({ where: { id: booking.eventTypeId as number } }) .then((data) => schemaEventTypeReadPublic.parse(data)) .then((event_type) => res.status(200).json({ event_type })) .catch((error: Error) => From 4431142d4e540b8d0135241cff16d0c7d3fbff61 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 12:58:04 +0530 Subject: [PATCH 15/36] remove unnecessary return --- pages/api/bookings/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 73c4e8d12b..322543078f 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -93,10 +93,9 @@ async function createOrlistAllBookings( const eventType = await prisma.eventType .findUnique({ where: { id: booking.eventTypeId as number } }) .then((data) => schemaEventTypeReadPublic.parse(data)) - .then((event_type) => res.status(200).json({ event_type })) .catch((error: Error) => res.status(404).json({ - message: `EventType with id: ${booking?.eventTypeId} not found`, + message: `EventType with id: ${booking.eventTypeId} not found`, error, }) ); From adab79040f37e83e8ddc5aa4b59f079a21cacbc3 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:06:22 +0530 Subject: [PATCH 16/36] --fix --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 322543078f..2db7abac29 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -100,7 +100,7 @@ async function createOrlistAllBookings( }) ); const evt = { - type: eventType.title, + type: eventType?.title || booking.title, title: booking.title, description: "", additionalNotes: "", From cd3a80006c6eb3b44a17273439f729051406f613 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:10:16 +0530 Subject: [PATCH 17/36] --fix --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 2db7abac29..1b23a5e3f3 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -127,7 +127,7 @@ async function createOrlistAllBookings( const triggerEvent = WebhookTriggerEvents.BOOKING_CREATED; const subscriberOptions = { userId, - eventTypeId: eventType.id, + eventTypeId: booking.eventTypeId as number, triggerEvent, }; From a8ad052a037246219eb15cdb82d8dee798b8b057 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:16:58 +0530 Subject: [PATCH 18/36] --convert date to string in calendar event --- pages/api/bookings/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 1b23a5e3f3..0a421298e1 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -105,8 +105,8 @@ async function createOrlistAllBookings( description: "", additionalNotes: "", customInputs: {}, - startTime: booking.startTime, - endTime: booking.endTime, + startTime: booking.startTime.toISOString(), + endTime: booking.endTime.toISOString(), organizer: { name: "", email: "", From ef5bbfe4f96c65480beb7bc88519464368700cdf Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:22:06 +0530 Subject: [PATCH 19/36] fixed timeZone key --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 0a421298e1..a8eaf90662 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -110,7 +110,7 @@ async function createOrlistAllBookings( organizer: { name: "", email: "", - timezone: "", + timeZone: "", language: { locale: "en" } From f1c98181d2daee95d3e16ba25406010914aa8e78 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:30:43 +0530 Subject: [PATCH 20/36] tfunction added --- pages/api/bookings/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index a8eaf90662..f5748daf67 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -1,5 +1,6 @@ -import type { NextApiRequest, NextApiResponse } from "next"; +import { getTranslation } from "@calcom/lib/server/i18n"; +import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@calcom/prisma"; import { WebhookTriggerEvents } from "@prisma/client"; @@ -99,6 +100,7 @@ async function createOrlistAllBookings( error, }) ); + const fallbackTfunction = await getTranslation("en", "common"); const evt = { type: eventType?.title || booking.title, title: booking.title, @@ -112,6 +114,7 @@ async function createOrlistAllBookings( email: "", timeZone: "", language: { + translate: fallbackTfunction, locale: "en" } }, From 54353f99d139395826a270843ad57abd73c38d1d Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:32:47 +0530 Subject: [PATCH 21/36] Calendar event changed to any for loose allowance --- lib/utils/sendPayload.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/sendPayload.ts b/lib/utils/sendPayload.ts index 62cc3f96d2..925be7486a 100644 --- a/lib/utils/sendPayload.ts +++ b/lib/utils/sendPayload.ts @@ -1,11 +1,11 @@ import { Webhook } from "@prisma/client"; import { compile } from "handlebars"; -import type { CalendarEvent } from "@calcom/types/Calendar"; +// import type { CalendarEvent } from "@calcom/types/Calendar"; Add this to make it strict, change data: any to CalendarEvent type type ContentType = "application/json" | "application/x-www-form-urlencoded"; -function applyTemplate(template: string, data: CalendarEvent, contentType: ContentType) { +function applyTemplate(template: string, data: any, contentType: ContentType) { const compiled = compile(template)(data); if (contentType === "application/json") { return JSON.stringify(jsonParse(compiled)); From 8339d339a1ac3f149045e7fa0a180107ea585ce7 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 13:38:45 +0530 Subject: [PATCH 22/36] prettier and payload fix --- lib/utils/sendPayload.ts | 2 +- pages/api/bookings/index.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/utils/sendPayload.ts b/lib/utils/sendPayload.ts index 925be7486a..f40c0ad743 100644 --- a/lib/utils/sendPayload.ts +++ b/lib/utils/sendPayload.ts @@ -26,7 +26,7 @@ const sendPayload = async ( triggerEvent: string, createdAt: string, webhook: Pick, - data: CalendarEvent & { + data: any & { metadata?: { [key: string]: string }; rescheduleUid?: string; bookingId?: number; diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index f5748daf67..7abd8ae5e7 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -1,14 +1,14 @@ -import { getTranslation } from "@calcom/lib/server/i18n"; - -import type { NextApiRequest, NextApiResponse } from "next"; import prisma from "@calcom/prisma"; import { WebhookTriggerEvents } from "@prisma/client"; +import { getTranslation } from "@calcom/lib/server/i18n"; + +import type { NextApiRequest, NextApiResponse } from "next"; import { withMiddleware } from "@lib/helpers/withMiddleware"; +import { BookingResponse, BookingsResponse } from "@lib/types"; import sendPayload from "@lib/utils/sendPayload"; import getWebhooks from "@lib/utils/webhookSubscriptions"; -import { BookingResponse, BookingsResponse } from "@lib/types"; import { schemaBookingCreateBodyParams, schemaBookingReadPublic } from "@lib/validations/booking"; import { schemaEventTypeReadPublic } from "@lib/validations/event-type"; @@ -115,7 +115,7 @@ async function createOrlistAllBookings( timeZone: "", language: { translate: fallbackTfunction, - locale: "en" + locale: "en", } }, attendees: [], From 5453af6d6ee189185b0c467157013d821825d7cd Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 15:57:31 +0530 Subject: [PATCH 23/36] prettier fix attempt --- pages/api/bookings/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 7abd8ae5e7..4db3f3051a 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -1,10 +1,9 @@ -import prisma from "@calcom/prisma"; - import { WebhookTriggerEvents } from "@prisma/client"; -import { getTranslation } from "@calcom/lib/server/i18n"; - import type { NextApiRequest, NextApiResponse } from "next"; +import { getTranslation } from "@calcom/lib/server/i18n"; +import prisma from "@calcom/prisma"; + import { withMiddleware } from "@lib/helpers/withMiddleware"; import { BookingResponse, BookingsResponse } from "@lib/types"; import sendPayload from "@lib/utils/sendPayload"; From 301c132815bd011f47efae13f21b053704664158 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 16:21:55 +0530 Subject: [PATCH 24/36] prettier fix attempt-2 --- pages/api/bookings/index.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 4db3f3051a..b8ef582dc1 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -88,8 +88,7 @@ async function createOrlistAllBookings( if (booking) { res.status(201).json({ booking, message: "Booking created successfully" }); - - // Create Calendar Event for webhook payload + // Create Calendar Event for webhook payload const eventType = await prisma.eventType .findUnique({ where: { id: booking.eventTypeId as number } }) .then((data) => schemaEventTypeReadPublic.parse(data)) @@ -115,24 +114,24 @@ async function createOrlistAllBookings( language: { translate: fallbackTfunction, locale: "en", - } + }, }, attendees: [], location: "", destinationCalendar: null, hideCalendar: false, uid: booking.uid, - metadata: {} + metadata: {}, }; - - // Send Webhook call if hooked to BOOKING_CREATED + + // Send Webhook call if hooked to BOOKING_CREATED const triggerEvent = WebhookTriggerEvents.BOOKING_CREATED; const subscriberOptions = { userId, eventTypeId: booking.eventTypeId as number, triggerEvent, }; - + const subscribers = await getWebhooks(subscriberOptions); const bookingId = booking?.id; const promises = subscribers.map((sub) => From 99e58c414c0419b96d9a0fe0c6e992c62307788f Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Fri, 10 Jun 2022 16:36:28 +0530 Subject: [PATCH 25/36] prettier fix -3 --- pages/api/bookings/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index b8ef582dc1..90f9cf7f22 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -143,8 +143,7 @@ async function createOrlistAllBookings( }) ); await Promise.all(promises); - } - else + } else (error: Error) => { console.log(error); res.status(400).json({ From 110edd7dcce0ae07554857c7a3c18395f3440b5a Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sat, 11 Jun 2022 16:54:30 +0530 Subject: [PATCH 26/36] removed 18next rel --- pages/api/bookings/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 90f9cf7f22..6f8f2ceadc 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -1,7 +1,6 @@ import { WebhookTriggerEvents } from "@prisma/client"; import type { NextApiRequest, NextApiResponse } from "next"; -import { getTranslation } from "@calcom/lib/server/i18n"; import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; @@ -98,7 +97,6 @@ async function createOrlistAllBookings( error, }) ); - const fallbackTfunction = await getTranslation("en", "common"); const evt = { type: eventType?.title || booking.title, title: booking.title, @@ -112,7 +110,6 @@ async function createOrlistAllBookings( email: "", timeZone: "", language: { - translate: fallbackTfunction, locale: "en", }, }, From 61e742ed5ef42d9d2584a92d06c9ec59e2785e5b Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sat, 11 Jun 2022 16:57:35 +0530 Subject: [PATCH 27/36] uuid automate in booking API --- lib/validations/booking.ts | 1 - pages/api/bookings/index.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/validations/booking.ts b/lib/validations/booking.ts index 67b4f1b35a..b61d6913fd 100644 --- a/lib/validations/booking.ts +++ b/lib/validations/booking.ts @@ -13,7 +13,6 @@ const schemaBookingBaseBodyParams = Booking.pick({ const schemaBookingCreateParams = z .object({ - uid: z.string(), eventTypeId: z.number(), title: z.string(), startTime: z.date().or(z.string()), diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 6f8f2ceadc..37fbd94262 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -1,5 +1,6 @@ import { WebhookTriggerEvents } from "@prisma/client"; import type { NextApiRequest, NextApiResponse } from "next"; +import { v4 as uuidv4 } from "uuid"; import prisma from "@calcom/prisma"; @@ -82,7 +83,7 @@ async function createOrlistAllBookings( return; } safe.data.userId = userId; - const data = await prisma.booking.create({ data: { ...safe.data } }); + const data = await prisma.booking.create({ data: { id: uuidv4(), ...safe.data } }); const booking = schemaBookingReadPublic.parse(data); if (booking) { From 3c98c5cefc4db970d674e54b14846504a2c1bf3f Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sat, 11 Jun 2022 16:58:21 +0530 Subject: [PATCH 28/36] fixing id to uid in create body --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 37fbd94262..6bd220aaf5 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -83,7 +83,7 @@ async function createOrlistAllBookings( return; } safe.data.userId = userId; - const data = await prisma.booking.create({ data: { id: uuidv4(), ...safe.data } }); + const data = await prisma.booking.create({ data: { uid: uuidv4(), ...safe.data } }); const booking = schemaBookingReadPublic.parse(data); if (booking) { From 719e21497b58e4a57b6914a6c4000e9443fa5188 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sat, 11 Jun 2022 17:03:11 +0530 Subject: [PATCH 29/36] removed invalid response --- pages/api/bookings/index.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 6bd220aaf5..af20e851fe 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -92,12 +92,9 @@ async function createOrlistAllBookings( const eventType = await prisma.eventType .findUnique({ where: { id: booking.eventTypeId as number } }) .then((data) => schemaEventTypeReadPublic.parse(data)) - .catch((error: Error) => - res.status(404).json({ - message: `EventType with id: ${booking.eventTypeId} not found`, - error, - }) - ); + .catch((e: Error) => { + console.error(`Event type with ID: ${booking.eventTypeId} not found`, e); + }); const evt = { type: eventType?.title || booking.title, title: booking.title, From 910a0f386a116b57284b6b6a99e74ed30c9df16b Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Sat, 11 Jun 2022 22:39:03 +0530 Subject: [PATCH 30/36] Debug booking API --- pages/api/bookings/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index af20e851fe..fc0030b651 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -35,6 +35,7 @@ async function createOrlistAllBookings( */ const data = await prisma.booking.findMany({ where: { userId } }); const bookings = data.map((booking) => schemaBookingReadPublic.parse(booking)); + console.log(`Bookings requested by ${userId}`); if (bookings) res.status(200).json({ bookings }); else (error: Error) => From 470c43befe7f940802fb471f38b7d296c4662446 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sun, 12 Jun 2022 11:16:16 +0530 Subject: [PATCH 31/36] call webhook before sending booking response --- pages/api/bookings/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index fc0030b651..b99b3510d5 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -88,7 +88,6 @@ async function createOrlistAllBookings( const booking = schemaBookingReadPublic.parse(data); if (booking) { - res.status(201).json({ booking, message: "Booking created successfully" }); // Create Calendar Event for webhook payload const eventType = await prisma.eventType .findUnique({ where: { id: booking.eventTypeId as number } }) @@ -139,6 +138,9 @@ async function createOrlistAllBookings( }) ); await Promise.all(promises); + + res.status(201).json({ booking, message: "Booking created successfully" }); + } else (error: Error) => { console.log(error); From bd88bec1d2015a83261ed5cdf14802b057475539 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sun, 12 Jun 2022 11:24:38 +0530 Subject: [PATCH 32/36] fix prettier --- pages/api/bookings/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index b99b3510d5..1bea4249b2 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -140,7 +140,6 @@ async function createOrlistAllBookings( await Promise.all(promises); res.status(201).json({ booking, message: "Booking created successfully" }); - } else (error: Error) => { console.log(error); From 935473cfcd040a178d25b7f813a5ce5acbb076d4 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sun, 12 Jun 2022 11:25:53 +0530 Subject: [PATCH 33/36] removed comment --- pages/api/bookings/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 1bea4249b2..3336098d57 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -88,7 +88,6 @@ async function createOrlistAllBookings( const booking = schemaBookingReadPublic.parse(data); if (booking) { - // Create Calendar Event for webhook payload const eventType = await prisma.eventType .findUnique({ where: { id: booking.eventTypeId as number } }) .then((data) => schemaEventTypeReadPublic.parse(data)) From ecce02ebbf60e6b215ed980f876cb760581609c4 Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz Date: Sun, 12 Jun 2022 11:43:26 +0530 Subject: [PATCH 34/36] debug logs added --- lib/utils/sendPayload.ts | 1 + pages/api/bookings/index.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/lib/utils/sendPayload.ts b/lib/utils/sendPayload.ts index f40c0ad743..a6234a1d37 100644 --- a/lib/utils/sendPayload.ts +++ b/lib/utils/sendPayload.ts @@ -18,6 +18,7 @@ function jsonParse(jsonString: string) { return JSON.parse(jsonString); } catch (e) { // don't do anything. + console.error(`error jsonParsing in sendPayload`); } return false; } diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index 3336098d57..e31a017801 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -94,6 +94,7 @@ async function createOrlistAllBookings( .catch((e: Error) => { console.error(`Event type with ID: ${booking.eventTypeId} not found`, e); }); + console.log(`eventType: ${eventType}`); const evt = { type: eventType?.title || booking.title, title: booking.title, @@ -117,16 +118,20 @@ async function createOrlistAllBookings( uid: booking.uid, metadata: {}, }; + console.log(`evt: ${evt}`); // Send Webhook call if hooked to BOOKING_CREATED const triggerEvent = WebhookTriggerEvents.BOOKING_CREATED; + console.log(`Trigger Event: ${triggerEvent}`); const subscriberOptions = { userId, eventTypeId: booking.eventTypeId as number, triggerEvent, }; + console.log(`subscriberOptions: ${subscriberOptions}`); const subscribers = await getWebhooks(subscriberOptions); + console.log(`subscribers: ${subscribers}`); const bookingId = booking?.id; const promises = subscribers.map((sub) => sendPayload(triggerEvent, new Date().toISOString(), sub, { From b385d3547bf487c341ab20c9a372fdf84af1da5c Mon Sep 17 00:00:00 2001 From: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Date: Mon, 13 Jun 2022 13:24:21 +0530 Subject: [PATCH 35/36] Adds debug console.log --- pages/api/bookings/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/api/bookings/index.ts b/pages/api/bookings/index.ts index e31a017801..ab85b339cd 100644 --- a/pages/api/bookings/index.ts +++ b/pages/api/bookings/index.ts @@ -142,7 +142,7 @@ async function createOrlistAllBookings( }) ); await Promise.all(promises); - + console.log("All promises resolved! About to send the response"); res.status(201).json({ booking, message: "Booking created successfully" }); } else (error: Error) => { From b1dd1b85727d3e0b9b8badfe151c513e7b48eb75 Mon Sep 17 00:00:00 2001 From: Agusti Fernandez Pardo Date: Mon, 13 Jun 2022 23:58:15 +0200 Subject: [PATCH 36/36] fix: make jsonSchema.optional() --- lib/validations/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/validations/user.ts b/lib/validations/user.ts index 528bc2e292..2385224f5a 100644 --- a/lib/validations/user.ts +++ b/lib/validations/user.ts @@ -93,7 +93,7 @@ const schemaUserEditParams = z.object({ .optional() .nullable(), locale: z.nativeEnum(locales).optional().nullable(), - metadata: jsonSchema, + metadata: jsonSchema.optional(), }); // @note: These are the values that are editable via PATCH method on the user Model,