From ad126efee8627930ae92deca8bb28853522f0e6e Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Mon, 16 May 2022 16:20:09 -0400 Subject: [PATCH] Add Google cal extneral calendar id to booking reference (#2671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Set google cal event id to use our uid * Save calendar external id to bookingRef * Pass external calendar ids to update and delete * Create migration * Fix type errors * Fix prisma url Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> Co-authored-by: Omar López --- apps/web/pages/api/cancel.ts | 6 +++++- .../app-store/googlecalendar/lib/CalendarService.ts | 13 +++++-------- packages/core/CalendarManager.ts | 5 +++-- packages/core/EventManager.ts | 8 +++++++- .../migration.sql | 2 ++ packages/prisma/schema.prisma | 1 + packages/types/Calendar.d.ts | 8 ++++++-- packages/types/EventManager.d.ts | 1 + 8 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 packages/prisma/migrations/20220503183922_add_external_calendar_id_to_booking_reference/migration.sql diff --git a/apps/web/pages/api/cancel.ts b/apps/web/pages/api/cancel.ts index 9473efba..750fcec7 100644 --- a/apps/web/pages/api/cancel.ts +++ b/apps/web/pages/api/cancel.ts @@ -51,6 +51,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) select: { uid: true, type: true, + externalCalendarId: true, }, }, payment: true, @@ -163,11 +164,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const apiDeletes = async.mapLimit(bookingToDelete.user.credentials, 5, async (credential: Credential) => { const bookingRefUid = bookingToDelete.references.filter((ref) => ref.type === credential.type)[0]?.uid; + const bookingExternalCalendarId = bookingToDelete.references.filter( + (ref) => ref.type === credential.type + )[0]?.externalCalendarId; if (bookingRefUid) { if (credential.type.endsWith("_calendar")) { const calendar = getCalendar(credential); - return calendar?.deleteEvent(bookingRefUid, evt); + return calendar?.deleteEvent(bookingRefUid, evt, bookingExternalCalendarId); } else if (credential.type.endsWith("_video")) { return deleteMeeting(credential, bookingRefUid); } diff --git a/packages/app-store/googlecalendar/lib/CalendarService.ts b/packages/app-store/googlecalendar/lib/CalendarService.ts index 092902b2..8471ab0c 100644 --- a/packages/app-store/googlecalendar/lib/CalendarService.ts +++ b/packages/app-store/googlecalendar/lib/CalendarService.ts @@ -14,6 +14,7 @@ import type { IntegrationCalendar, NewCalendarEventType, } from "@calcom/types/Calendar"; +import type { PartialReference } from "@calcom/types/EventManager"; import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; @@ -162,7 +163,7 @@ export default class GoogleCalendarService implements Calendar { }); } - async updateEvent(uid: string, event: CalendarEvent): Promise { + async updateEvent(uid: string, event: CalendarEvent, externalCalendarId: string): Promise { return new Promise(async (resolve, reject) => { const auth = await this.auth; const myGoogleAuth = await auth.getToken(); @@ -194,9 +195,7 @@ export default class GoogleCalendarService implements Calendar { calendar.events.update( { auth: myGoogleAuth, - calendarId: event.destinationCalendar?.externalId - ? event.destinationCalendar.externalId - : "primary", + calendarId: externalCalendarId ? externalCalendarId : event.destinationCalendar?.externalId, eventId: uid, sendNotifications: true, sendUpdates: "all", @@ -214,7 +213,7 @@ export default class GoogleCalendarService implements Calendar { }); } - async deleteEvent(uid: string, event: CalendarEvent): Promise { + async deleteEvent(uid: string, event: CalendarEvent, externalCalendarId: string): Promise { return new Promise(async (resolve, reject) => { const auth = await this.auth; const myGoogleAuth = await auth.getToken(); @@ -225,9 +224,7 @@ export default class GoogleCalendarService implements Calendar { calendar.events.delete( { auth: myGoogleAuth, - calendarId: event.destinationCalendar?.externalId - ? event.destinationCalendar.externalId - : "primary", + calendarId: externalCalendarId ? externalCalendarId : event.destinationCalendar?.externalId, eventId: uid, sendNotifications: true, sendUpdates: "all", diff --git a/packages/core/CalendarManager.ts b/packages/core/CalendarManager.ts index b3fbfae1..126b21c5 100644 --- a/packages/core/CalendarManager.ts +++ b/packages/core/CalendarManager.ts @@ -128,7 +128,8 @@ export const createEvent = async (credential: Credential, calEvent: CalendarEven export const updateEvent = async ( credential: Credential, calEvent: CalendarEvent, - bookingRefUid: string | null + bookingRefUid: string | null, + externalCalendarId: string | null ): Promise => { const uid = getUid(calEvent); const calendar = getCalendar(credential); @@ -139,7 +140,7 @@ export const updateEvent = async ( const updatedResult = calendar && bookingRefUid ? await calendar - .updateEvent(bookingRefUid, calEvent) + .updateEvent(bookingRefUid, calEvent, externalCalendarId) .then(() => (success = true)) .catch((e) => { log.error("updateEvent failed", e, calEvent); diff --git a/packages/core/EventManager.ts b/packages/core/EventManager.ts index 6e90a130..27adf6fa 100644 --- a/packages/core/EventManager.ts +++ b/packages/core/EventManager.ts @@ -146,6 +146,7 @@ export default class EventManager { meetingId: result.createdEvent?.id.toString(), meetingPassword: result.createdEvent?.password, meetingUrl: result.createdEvent?.url, + externalCalendarId: evt.destinationCalendar?.externalId, }; }); @@ -188,6 +189,7 @@ export default class EventManager { meetingId: true, meetingPassword: true, meetingUrl: true, + externalCalendarId: true, }, }, destinationCalendar: true, @@ -354,7 +356,11 @@ export default class EventManager { ? booking.references.filter((ref) => ref.type === credential.type && !!ref.uid)[0]?.uid : null; - return updateEvent(credential, event, bookingRefUid); + const bookingExternalCalendarId = booking.references + ? booking.references.filter((ref) => ref.type === credential.type)[0].externalCalendarId + : null; + + return updateEvent(credential, event, bookingRefUid, bookingExternalCalendarId!); }); } diff --git a/packages/prisma/migrations/20220503183922_add_external_calendar_id_to_booking_reference/migration.sql b/packages/prisma/migrations/20220503183922_add_external_calendar_id_to_booking_reference/migration.sql new file mode 100644 index 00000000..66960d7d --- /dev/null +++ b/packages/prisma/migrations/20220503183922_add_external_calendar_id_to_booking_reference/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "BookingReference" ADD COLUMN "externalCalendarId" TEXT; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index a6c3cbab..664623bc 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -223,6 +223,7 @@ model BookingReference { meetingUrl String? booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade) bookingId Int? + externalCalendarId String? deleted Boolean? } diff --git a/packages/types/Calendar.d.ts b/packages/types/Calendar.d.ts index 45bd1e0d..2ca2636c 100644 --- a/packages/types/Calendar.d.ts +++ b/packages/types/Calendar.d.ts @@ -140,9 +140,13 @@ export interface IntegrationCalendar extends Ensure, " export interface Calendar { createEvent(event: CalendarEvent): Promise; - updateEvent(uid: string, event: CalendarEvent): Promise; + updateEvent( + uid: string, + event: CalendarEvent, + externalCalendarId?: string | null + ): Promise; - deleteEvent(uid: string, event: CalendarEvent): Promise; + deleteEvent(uid: string, event: CalendarEvent, externalCalendarId?: string | null): Promise; getAvailability( dateFrom: string, diff --git a/packages/types/EventManager.d.ts b/packages/types/EventManager.d.ts index 27298b82..4a68f7b9 100644 --- a/packages/types/EventManager.d.ts +++ b/packages/types/EventManager.d.ts @@ -8,6 +8,7 @@ export interface PartialReference { meetingId?: string | null; meetingPassword?: string | null; meetingUrl?: string | null; + externalCalendarId?: string | null; } export interface EventResult {