From 66c5f810ea181aa9d2e32b331411e21d968f25d0 Mon Sep 17 00:00:00 2001 From: Rodrigo Ehlers Date: Mon, 27 Oct 2025 18:11:05 +0100 Subject: [PATCH] fix: remove singular query that was using slow OR query (#24715) ## What does this PR do? Removes and replaces the singular query that was still using the slow OR query from prisma. It was mainly used on the public booking page and triggered after someone entered their email (600ms debounce delay). ## Visual Demo (For contributors especially) Internal change only nothing changes on the UI or business logic. #### Video Demo (if applicable): N/A #### Image Demo (if applicable): N/A ## Mandatory Tasks (DO NOT REMOVE) - [x] I have self-reviewed the code (A decent size PR without self-review might be rejected). - [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox. - [x] I confirm automated tests are in place that prove my fix is effective or that my feature works. ## How should this be tested? Basically the same as https://github.com/calcom/cal.com/pull/24298 since it touches relevant code. 1. Have a user that has the setting to prevent impersonation on. 2. Go to another users public booking page of any meeting. 3. Try to enter the email of the first user into the booking for. 4. Wait 1 second and make sure the button shows "Verify email". ## Checklist - I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md) - My code doesn't follow the style guidelines of this project - I haven't commented my code, particularly in hard-to-understand areas - I haven't checked if my changes generate no new warnings --- .../test/booking-validations.test.ts | 10 +++---- .../users/repositories/UserRepository.ts | 26 ------------------- ...IfUserEmailVerificationRequired.handler.ts | 3 ++- 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/packages/features/bookings/lib/handleNewBooking/test/booking-validations.test.ts b/packages/features/bookings/lib/handleNewBooking/test/booking-validations.test.ts index 1d4cddcc82..5a1962dac9 100644 --- a/packages/features/bookings/lib/handleNewBooking/test/booking-validations.test.ts +++ b/packages/features/bookings/lib/handleNewBooking/test/booking-validations.test.ts @@ -28,11 +28,9 @@ vi.mock("@calcom/trpc/server/routers/viewer/auth/util", () => ({ verifyCodeUnAuthenticated: vi.fn(), })); -const { mockFindManyByEmailsWithEmailVerificationSettings, mockFindByEmailWithEmailVerificationSetting } = - vi.hoisted(() => ({ - mockFindManyByEmailsWithEmailVerificationSettings: vi.fn(), - mockFindByEmailWithEmailVerificationSetting: vi.fn(), - })); +const { mockFindManyByEmailsWithEmailVerificationSettings } = vi.hoisted(() => ({ + mockFindManyByEmailsWithEmailVerificationSettings: vi.fn(), +})); vi.mock("@calcom/features/users/repositories/UserRepository", async (importOriginal) => { const actual = await importOriginal(); @@ -45,7 +43,6 @@ vi.mock("@calcom/features/users/repositories/UserRepository", async (importOrigi const realInstance = new OriginalUserRepository(prisma); realInstance.findManyByEmailsWithEmailVerificationSettings = mockFindManyByEmailsWithEmailVerificationSettings; - realInstance.findByEmailWithEmailVerificationSetting = mockFindByEmailWithEmailVerificationSetting; return realInstance; }), }; @@ -61,7 +58,6 @@ function resetBlacklistedEmails() { beforeEach(() => { mockFindManyByEmailsWithEmailVerificationSettings.mockResolvedValue([]); - mockFindByEmailWithEmailVerificationSetting.mockResolvedValue(null); }); afterEach(() => { diff --git a/packages/features/users/repositories/UserRepository.ts b/packages/features/users/repositories/UserRepository.ts index 8333d236ad..99070eec1c 100644 --- a/packages/features/users/repositories/UserRepository.ts +++ b/packages/features/users/repositories/UserRepository.ts @@ -276,32 +276,6 @@ export class UserRepository { }); return user; } - async findByEmailWithEmailVerificationSetting({ email }: { email: string }) { - const user = await this.prismaClient.user.findFirst({ - where: { - OR: [ - { - email: email.toLowerCase(), - emailVerified: { not: null }, - }, - { - secondaryEmails: { - some: { - email: email.toLowerCase(), - emailVerified: { not: null }, - }, - }, - }, - ], - }, - select: { - id: true, - email: true, - requiresBookerEmailVerification: true, - }, - }); - return user; - } async findManyByEmailsWithEmailVerificationSettings({ emails }: { emails: string[] }) { const normalizedEmails = emails.map((e) => e.toLowerCase()); diff --git a/packages/trpc/server/routers/publicViewer/checkIfUserEmailVerificationRequired.handler.ts b/packages/trpc/server/routers/publicViewer/checkIfUserEmailVerificationRequired.handler.ts index b6975ad81a..ed9b68f1cd 100644 --- a/packages/trpc/server/routers/publicViewer/checkIfUserEmailVerificationRequired.handler.ts +++ b/packages/trpc/server/routers/publicViewer/checkIfUserEmailVerificationRequired.handler.ts @@ -34,7 +34,8 @@ export const checkEmailVerificationRequired = async ({ } const userRepo = new UserRepository(prisma); - const user = await userRepo.findByEmailWithEmailVerificationSetting({ email: baseEmail }); + const users = await userRepo.findManyByEmailsWithEmailVerificationSettings({ emails: [baseEmail] }); + const user = users[0]; if (user?.requiresBookerEmailVerification && baseEmail.toLowerCase() !== userSessionEmail?.toLowerCase()) { log.warn(`user email requiring verification: ${baseEmail}`);