From 480977c2b54056cb484121fd26edfc81c43d7029 Mon Sep 17 00:00:00 2001 From: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:43:17 +0300 Subject: [PATCH] fix: api v2 - platform users can disable emails and display their links (#14604) * fix: disable emails with oauthCLient settings and hide empty links * fixup! fix: disable emails with oauthCLient settings and hide empty links * feat: enable to display booking success page link in emails * fixup! feat: enable to display booking success page link in emails * fixup! Merge branch 'fix-no-email-booking-hide-empty-links' of github.com:calcom/cal.com into fix-no-email-booking-hide-empty-links * fixup! fixup! Merge branch 'fix-no-email-booking-hide-empty-links' of github.com:calcom/cal.com into fix-no-email-booking-hide-empty-links * fixup! Merge branch 'main' into fix-no-email-booking-hide-empty-links * fixup! Merge branch 'main' into fix-no-email-booking-hide-empty-links * fixup! Merge branch 'fix-no-email-booking-hide-empty-links' of github.com:calcom/cal.com into fix-no-email-booking-hide-empty-links --------- Co-authored-by: Lauris Skraucis --- .../controllers/bookings.controller.ts | 13 ++-- packages/emails/src/components/ManageLink.tsx | 72 ++++++++++++++----- .../bookings/lib/handleCancelBooking.ts | 5 +- packages/lib/CalEventParser.ts | 29 ++++++-- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts index 2733b76926..5981893abb 100644 --- a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts +++ b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts @@ -58,6 +58,7 @@ type OAuthRequestParams = { platformCancelUrl: string; platformBookingUrl: string; platformBookingLocation?: string; + arePlatformEmailsEnabled: boolean; }; const DEFAULT_PLATFORM_PARAMS = { @@ -65,7 +66,7 @@ const DEFAULT_PLATFORM_PARAMS = { platformCancelUrl: "", platformRescheduleUrl: "", platformBookingUrl: "", - areEmailsEnabled: true, + arePlatformEmailsEnabled: false, platformBookingLocation: undefined, }; @@ -172,6 +173,7 @@ export class BookingsController { const oAuthClientId = clientId?.toString(); if (bookingId) { try { + req.body.id = parseInt(bookingId); await handleCancelBooking(await this.createNextApiBookingRequest(req, oAuthClientId)); return { status: SUCCESS_STATUS, @@ -239,10 +241,7 @@ export class BookingsController { } } - async getOAuthClientsParams( - req: BookingRequest, - clientId: string - ): Promise { + async getOAuthClientsParams(req: BookingRequest, clientId: string): Promise { const res = DEFAULT_PLATFORM_PARAMS; try { const client = await this.oAuthClientRepository.getOAuthClient(clientId); @@ -252,7 +251,7 @@ export class BookingsController { res.platformCancelUrl = client.bookingCancelRedirectUri ?? ""; res.platformRescheduleUrl = client.bookingRescheduleRedirectUri ?? ""; res.platformBookingUrl = client.bookingRedirectUri ?? ""; - res.areEmailsEnabled = client.areEmailsEnabled; + res.arePlatformEmailsEnabled = client.areEmailsEnabled ?? false; } return res; } catch (err) { @@ -271,7 +270,7 @@ export class BookingsController { ? await this.getOAuthClientsParams(req, oAuthClientId) : DEFAULT_PLATFORM_PARAMS; Object.assign(req, { userId, ...oAuthParams, platformBookingLocation }); - req.body = { ...req.body, areEmailsEnabled: oAuthParams.areEmailsEnabled }; + req.body = { ...req.body, noEmail: !oAuthParams.arePlatformEmailsEnabled }; return req as unknown as NextApiRequest & { userId?: number } & OAuthRequestParams; } } diff --git a/packages/emails/src/components/ManageLink.tsx b/packages/emails/src/components/ManageLink.tsx index 15967077be..4db512107a 100644 --- a/packages/emails/src/components/ManageLink.tsx +++ b/packages/emails/src/components/ManageLink.tsx @@ -1,13 +1,25 @@ -import { getCancelLink, getRescheduleLink } from "@calcom/lib/CalEventParser"; +import { getCancelLink, getRescheduleLink, getBookingUrl } from "@calcom/lib/CalEventParser"; import type { CalendarEvent, Person } from "@calcom/types/Calendar"; export function ManageLink(props: { calEvent: CalendarEvent; attendee: Person }) { // Only the original attendee can make changes to the event // Guests cannot const t = props.attendee.language.translate; + const cancelLink = getCancelLink(props.calEvent); + const rescheduleLink = getRescheduleLink(props.calEvent); + const bookingLink = getBookingUrl(props.calEvent); + + const isOriginalAttendee = props.attendee.email === props.calEvent.attendees[0]?.email; + const isOrganizer = props.calEvent.organizer.email === props.attendee.email; + const hasCancelLink = Boolean(cancelLink); + const hasRescheduleLink = Boolean(rescheduleLink); + const hasBookingLink = Boolean(bookingLink); + const isRecurringEvent = props.calEvent.recurringEvent; + const shouldDisplayRescheduleLink = Boolean(hasRescheduleLink && !isRecurringEvent); + if ( - props.attendee.email === props.calEvent.attendees[0]?.email || - props.calEvent.organizer.email === props.attendee.email + (isOriginalAttendee || isOrganizer) && + (hasCancelLink || (!isRecurringEvent && hasRescheduleLink) || hasBookingLink) ) { return (
<>{t("need_to_make_a_change")} - {!props.calEvent.recurringEvent && ( + {shouldDisplayRescheduleLink && ( <>{t("reschedule")} - <>{t("or_lowercase")} + {hasCancelLink && <>{t("or_lowercase")}} + + )} + {hasCancelLink && ( + + + <>{t("cancel")} + + + )} + + {props.calEvent.platformClientId && hasBookingLink && ( + + {(hasCancelLink || shouldDisplayRescheduleLink) && ( + + {t("or_lowercase")} + + )} + + <>{t("check_here")} + )} - - - <>{t("cancel")} - -

); } - // Dont have the rights to the manage link + // Don't have the rights to the manage link return null; } diff --git a/packages/features/bookings/lib/handleCancelBooking.ts b/packages/features/bookings/lib/handleCancelBooking.ts index b67d8b6ad8..68fbad3946 100644 --- a/packages/features/bookings/lib/handleCancelBooking.ts +++ b/packages/features/bookings/lib/handleCancelBooking.ts @@ -129,6 +129,7 @@ export type CustomRequest = NextApiRequest & { platformRescheduleUrl?: string; platformCancelUrl?: string; platformBookingUrl?: string; + arePlatformEmailsEnabled?: boolean; }; async function handler(req: CustomRequest) { @@ -142,6 +143,7 @@ async function handler(req: CustomRequest) { platformCancelUrl, platformClientId, platformRescheduleUrl, + arePlatformEmailsEnabled, } = req; if (!bookingToDelete || !bookingToDelete.user) { @@ -559,7 +561,8 @@ async function handler(req: CustomRequest) { } // TODO: if emails fail try to requeue them - await sendCancelledEmails(evt, { eventName: bookingToDelete?.eventType?.eventName }); + if (!platformClientId || (platformClientId && arePlatformEmailsEnabled)) + await sendCancelledEmails(evt, { eventName: bookingToDelete?.eventType?.eventName }); } catch (error) { console.error("Error deleting event", error); } diff --git a/packages/lib/CalEventParser.ts b/packages/lib/CalEventParser.ts index 5b64e0f670..2a655fa9b6 100644 --- a/packages/lib/CalEventParser.ts +++ b/packages/lib/CalEventParser.ts @@ -154,18 +154,33 @@ const getSeatReferenceId = (calEvent: CalendarEvent): string => { return calEvent.attendeeSeatId ? calEvent.attendeeSeatId : ""; }; -export const getPlatformManageLink = (calEvent: CalendarEvent, t: TFunction) => { - if (calEvent.platformBookingUrl) { - return `${t("need_to_reschedule_or_cancel")} ${calEvent.platformBookingUrl}/${getUid(calEvent)}?slug=${ - calEvent.type - }&username=${calEvent.organizer.username}&changes=true`; +export const getBookingUrl = (calEvent: CalendarEvent) => { + if (calEvent.platformClientId) { + if (!calEvent.platformBookingUrl) return ""; + return `${calEvent.platformBookingUrl}/${getUid(calEvent)}?slug=${calEvent.type}&username=${ + calEvent.organizer.username + }&changes=true`; + } + + return `${calEvent.bookerUrl ?? WEBAPP_URL}/booking/${getUid(calEvent)}?changes=true`; +}; + +export const getPlatformManageLink = (calEvent: CalendarEvent, t: TFunction) => { + const shouldDisplayReschedule = !calEvent.recurringEvent && calEvent.platformRescheduleUrl; + let res = + calEvent.platformBookingUrl || shouldDisplayReschedule || calEvent.platformCancelUrl + ? `${t("need_to_reschedule_or_cancel")} ` + : ``; + if (calEvent.platformBookingUrl) { + res += `Check Here: ${calEvent.platformBookingUrl}/${getUid(calEvent)}?slug=${calEvent.type}&username=${ + calEvent.organizer.username + }&changes=true${calEvent.platformCancelUrl || shouldDisplayReschedule ? ` ${t("or_lowercase")} ` : ""}`; } - let res = ""; if (calEvent.platformCancelUrl) { res += `${t("cancel")}: ${getCancelLink(calEvent)}`; } - if (calEvent.platformRescheduleUrl) { + if (!calEvent.recurringEvent && calEvent.platformRescheduleUrl) { res += `${calEvent.platformCancelUrl ? ` ${t("or_lowercase")} ` : ""}${t( "reschedule" )}: ${getRescheduleLink(calEvent)}`;