Files
calendar/packages/features/bookings/lib/handleNewBooking/getRequiresConfirmationFlags.ts
T
Joe Au-YeungandGitHub 8dda418127 feat: Salesforce skip ownership check if attendee email is a free domain (#17916)
* Add email domain array

* Create numbered email domain object

* Check email domain

* Rename function

* Add tests

* Frontend enable skip ownership check if free email domain

* Backend ignore adding ownership to return records if free email domain check is enabled

* feat: Only require confirmation for free email domains (#17917)

* Add requiresConfirmationForFreeEmail to db

* Add option to event type settings

* Get requiresConfirmationForFreeEmail for event type page

* Include requiresConfirmationForFreeEmail in fetching event type

* Pass bookerEmail to `getRequiresConfirmationFlags`

* Add free email domain check to `determineRequiresConfirmation`

* Add `requiresConfirmationForFreeEmail` to types

* Add severity to Watchlist table

* Add migration for watchlist severity

* Add `getEmailDomainInWatchlist` method to watchlist repository

* Use watchlist repository to check for free email domain

* Mock watchlist repository in test

* Update test

* Rename method

* Add severity to blocked list

* Move check free email domain to async

* Type checks

* Adjust for promise returned

* Fix tests

* Fix

* Fix tests
2024-12-18 15:02:42 +00:00

87 lines
2.7 KiB
TypeScript

import dayjs from "@calcom/dayjs";
import { checkIfFreeEmailDomain } from "@calcom/lib/freeEmailDomainCheck/checkIfFreeEmailDomain";
import type { getEventTypeResponse } from "./getEventTypesFromDB";
type EventType = Pick<
getEventTypeResponse,
"metadata" | "requiresConfirmation" | "requiresConfirmationForFreeEmail"
>;
type PaymentAppData = { price: number };
export async function getRequiresConfirmationFlags({
eventType,
bookingStartTime,
userId,
paymentAppData,
originalRescheduledBookingOrganizerId,
bookerEmail,
}: {
eventType: EventType;
bookingStartTime: string;
userId: number | undefined;
paymentAppData: PaymentAppData;
originalRescheduledBookingOrganizerId: number | undefined;
bookerEmail: string;
}) {
const requiresConfirmation = await determineRequiresConfirmation(eventType, bookingStartTime, bookerEmail);
const userReschedulingIsOwner = isUserReschedulingOwner(userId, originalRescheduledBookingOrganizerId);
const isConfirmedByDefault = determineIsConfirmedByDefault(
requiresConfirmation,
paymentAppData.price,
userReschedulingIsOwner
);
return {
/**
* Organizer of the booking is rescheduling
*/
userReschedulingIsOwner,
/**
* Booking won't need confirmation to be ACCEPTED
*/
isConfirmedByDefault,
};
}
async function determineRequiresConfirmation(
eventType: EventType,
bookingStartTime: string,
bookerEmail: string
): Promise<boolean> {
let requiresConfirmation = eventType?.requiresConfirmation;
const rcThreshold = eventType?.metadata?.requiresConfirmationThreshold;
const requiresConfirmationForFreeEmail = eventType?.requiresConfirmationForFreeEmail;
if (requiresConfirmationForFreeEmail) {
requiresConfirmation = await checkIfFreeEmailDomain(bookerEmail);
}
if (rcThreshold) {
const timeDifference = dayjs(dayjs(bookingStartTime).utc().format()).diff(dayjs(), rcThreshold.unit);
if (timeDifference > rcThreshold.time) {
requiresConfirmation = false;
}
}
return requiresConfirmation;
}
function isUserReschedulingOwner(
userId: number | undefined,
originalRescheduledBookingOrganizerId: number | undefined
): boolean {
// If the user is not the owner of the event, new booking should be always pending.
// Otherwise, an owner rescheduling should be always accepted.
// Before comparing make sure that userId is set, otherwise undefined === undefined
return !!(userId && originalRescheduledBookingOrganizerId === userId);
}
function determineIsConfirmedByDefault(
requiresConfirmation: boolean,
price: number,
userReschedulingIsOwner: boolean
): boolean {
return (!requiresConfirmation && price === 0) || userReschedulingIsOwner;
}