Skip to content

Conversation

dhairyashiil
Copy link
Member

What does this PR do?

Visual Demo (For contributors especially)

Screen.Recording.2025-10-09.at.1.19.14.AM.mov

@dhairyashiil dhairyashiil requested a review from a team as a code owner October 8, 2025 19:58
Copy link

vercel bot commented Oct 8, 2025

@dhairyashiil is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added consumer High priority Created by Linear-GitHub Sync ✨ feature New feature or request labels Oct 8, 2025
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Oct 8, 2025
@graphite-app graphite-app bot requested a review from a team October 8, 2025 19:58
@github-actions github-actions bot added ❗️ migrations contains migration files and removed ✨ feature New feature or request High priority Created by Linear-GitHub Sync community Created by Linear-GitHub Sync consumer labels Oct 8, 2025
@keithwillcode keithwillcode added the community-interns The team responsible for reviewing, testing and shipping low/medium community PRs label Oct 8, 2025
Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

Walkthrough

Adds a new per-user boolean setting preventEmailImpersonation (Prisma schema + migration), surfaces it in repository selects and SessionUser, exposes it in viewer/me get handler and updateProfile schema, and adds a toggle and locale strings in the My Account → General UI. Booking paths now treat emails belonging to users with this flag (including verified secondary emails) as protected and exclude them from guest lists in handleNewBooking and addGuests.handler; checkIfBookerEmailIsBlocked was updated to gate on the flag. Also introduces InviteeItem type and includes phoneNumber on invitee objects.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The addition of a phoneNumber field and related type refactoring for InviteeItem in the booking handler is unrelated to the impersonation-prevention objective and therefore constitutes an out-of-scope change. Please extract the phoneNumber enhancement and type restructuring into a separate pull request so this changeset remains focused on the impersonation prevention feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly conveys the introduction of a feature to prevent impersonated bookings and aligns directly with the primary change of adding a per-user impersonation‐prevention toggle.
Linked Issues Check ✅ Passed The changes introduce the UI toggle on the account settings page, persist the new flag in the database and user schema, expose it via the API, and filter bookings and guest additions based on preventEmailImpersonation, fully satisfying the requirements in issues #24365 and CAL-6549.
Description Check ✅ Passed The description references the specific linked issues and provides a relevant visual demo link, demonstrating clear relevance to the implemented impersonation‐prevention feature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot bot added bookings area: bookings, availability, timezones, double booking ✨ feature New feature or request labels Oct 8, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4dfab87 and dfc07c6.

📒 Files selected for processing (10)
  • apps/web/modules/settings/my-account/general-view.tsx (2 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (4 hunks)
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts (1 hunks)
  • packages/lib/server/repository/user.ts (3 hunks)
  • packages/prisma/migrations/20251008191459_add_prevent_impersonated_booking_in_user/migration.sql (1 hunks)
  • packages/prisma/schema.prisma (1 hunks)
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/me/get.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/me/updateProfile.schema.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/me/get.handler.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.schema.ts
  • packages/lib/server/repository/user.ts
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/trpc/server/routers/viewer/me/get.handler.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.schema.ts
  • packages/lib/server/repository/user.ts
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • apps/web/modules/settings/my-account/general-view.tsx
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/trpc/server/routers/viewer/me/get.handler.ts
  • packages/trpc/server/routers/viewer/me/updateProfile.schema.ts
  • packages/lib/server/repository/user.ts
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • apps/web/modules/settings/my-account/general-view.tsx
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • apps/web/modules/settings/my-account/general-view.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (3)
apps/web/modules/settings/my-account/general-view.tsx (1)
packages/ui/components/form/switch/SettingsToggle.tsx (1)
  • SettingsToggle (29-125)
packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts (1)
scripts/prepare-local-for-delegation-credentials-testing.js (1)
  • user (15-17)
packages/features/bookings/lib/handleNewBooking.ts (1)
packages/features/bookings/lib/handleNewBooking/types.ts (1)
  • Invitee (14-25)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (7)
packages/prisma/migrations/20251008191459_add_prevent_impersonated_booking_in_user/migration.sql (1)

2-2: LGTM: adds non-null boolean with safe default.

Looks correct and migration-safe for Postgres.

packages/prisma/schema.prisma (1)

407-408: User.preventEmailImpersonation added — OK.

Schema change aligns with feature; default(false) is appropriate.

packages/trpc/server/routers/viewer/me/updateProfile.schema.ts (1)

24-24: Update profile schema extended — OK.

Optional boolean matches the UI toggle pattern.

packages/trpc/server/routers/viewer/me/get.handler.ts (1)

143-143: preventEmailImpersonation is already selected in the user repository
Default select in packages/lib/server/repository/user.ts (line 914) includes this field—never undefined.

apps/web/modules/settings/my-account/general-view.tsx (1)

150-152: State initialization looks correct

Bootstrapping from user.preventEmailImpersonation is consistent with other toggles.

packages/features/bookings/lib/handleNewBooking.ts (2)

27-29: DI container imports: OK

Imports align with usage of getCacheService/getLuckyUserService/getCheckBookingAndDurationLimitsService.


1532-1533: Non-functional parentheses change: OK

No behavior change; safe.

@github-actions github-actions bot added consumer High priority Created by Linear-GitHub Sync labels Oct 8, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/web/modules/settings/my-account/general-view.tsx (1)

360-372: Consider adding error handling to revert state on mutation failure.

The toggle implementation looks good and addresses the data-testid concern from the previous review. However, the local state is updated optimistically without reverting if the mutation fails, which can lead to UI/server state mismatch.

Optional: Add an onError callback to the mutation to revert the local state:

 const mutation = trpc.viewer.me.updateProfile.useMutation({
   onSuccess: async (res) => {
     await utils.viewer.me.invalidate();
     revalidateSettingsGeneral();
     revalidateTravelSchedules();
     reset(getValues());
     showToast(t("settings_updated_successfully"), "success");
     await update(res);

     if (res.locale) {
       window.calNewLocale = res.locale;
       document.cookie = `calNewLocale=${res.locale}; path=/`;
     }
   },
   onError: () => {
     showToast(t("error_updating_settings"), "error");
   },

Then update the toggle's onCheckedChange:

 onCheckedChange={(checked) => {
+  const previousValue = isPreventEmailImpersonationChecked;
   setIsPreventEmailImpersonationChecked(checked);
-  mutation.mutate({ preventEmailImpersonation: checked });
+  mutation.mutate(
+    { preventEmailImpersonation: checked },
+    {
+      onError: () => {
+        setIsPreventEmailImpersonationChecked(previousValue);
+      },
+    }
+  );
 }}

Note: This pattern should ideally be applied to the other toggles in this file as well for consistency.

packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (1)

83-135: Optional: Precompute normalized guest emails to reduce repeated work.

The extractBaseEmail(g).toLowerCase() call is repeated multiple times: twice in the Prisma query (lines 89, 100) and once per guest in the filter (lines 133-134). While not a functional issue, precomputing could improve performance, especially with large guest lists.

Consider this refactor:

+  const normalizedGuests = guests.map((g) => extractBaseEmail(g).toLowerCase());
+
   // Get emails that have preventEmailImpersonation enabled
   const usersWithPreventImpersonation = await prisma.user.findMany({
     where: {
       OR: [
         {
           email: {
-            in: guests.map((g) => extractBaseEmail(g).toLowerCase()),
+            in: normalizedGuests,
           },
           emailVerified: {
             not: null,
           },
           preventEmailImpersonation: true,
         },
         {
           secondaryEmails: {
             some: {
               email: {
-                in: guests.map((g) => extractBaseEmail(g).toLowerCase()),
+                in: normalizedGuests,
               },
               emailVerified: {
                 not: null,
               },
             },
           },
           preventEmailImpersonation: true,
         },
       ],
     },
     select: {
       email: true,
       secondaryEmails: {
         select: {
           email: true,
           emailVerified: true,
         },
       },
     },
   });

   const protectedEmails = new Set<string>();
   usersWithPreventImpersonation.forEach((user) => {
     protectedEmails.add(user.email.toLowerCase());
     user.secondaryEmails.forEach((se) => {
       if (se.emailVerified) protectedEmails.add(se.email.toLowerCase());
     });
   });

   const uniqueGuests = guests.filter(
     (guest, index, self) =>
       self.indexOf(guest) === index &&
-      !blacklistedGuestEmails.includes(extractBaseEmail(guest).toLowerCase()) &&
-      !protectedEmails.has(extractBaseEmail(guest).toLowerCase())
+      !blacklistedGuestEmails.includes(normalizedGuests[index]) &&
+      !protectedEmails.has(normalizedGuests[index])
   );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dfc07c6 and cec99ca.

📒 Files selected for processing (4)
  • apps/web/modules/settings/my-account/general-view.tsx (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (4 hunks)
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts (1 hunks)
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/features/bookings/lib/handleNewBooking/checkIfBookerEmailIsBlocked.ts
  • packages/features/bookings/lib/handleNewBooking.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • apps/web/modules/settings/my-account/general-view.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/web/modules/settings/my-account/general-view.tsx
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • apps/web/modules/settings/my-account/general-view.tsx
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
🧬 Code graph analysis (2)
apps/web/modules/settings/my-account/general-view.tsx (1)
packages/ui/components/form/switch/SettingsToggle.tsx (1)
  • SettingsToggle (29-125)
packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (1)
scripts/prepare-local-for-delegation-credentials-testing.js (1)
  • user (15-17)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Tests / Unit
  • GitHub Check: Type check / check-types
  • GitHub Check: Linters / lint
🔇 Additional comments (1)
apps/web/modules/settings/my-account/general-view.tsx (1)

150-152: LGTM!

State initialization follows the established pattern for other toggles in this component.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/features/bookings/lib/handleNewBooking.ts (1)

1202-1225: Consider redacting PII in removal logs.

The guest filtering logic correctly excludes blacklisted and protected emails. However, line 1228 logs the full list of removed guest email addresses, which could expose PII in production logs.

Apply this diff to log counts instead of full emails:

   if (guestsRemoved.length > 0) {
-    log.info("Removed guests from the booking", guestsRemoved);
+    log.info(`Removed ${guestsRemoved.length} guest(s) from the booking (blacklisted or impersonation-protected)`);
   }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between cec99ca and 89e5986.

📒 Files selected for processing (3)
  • packages/features/bookings/lib/handleNewBooking.ts (5 hunks)
  • packages/features/bookings/lib/handleNewBooking/types.ts (2 hunks)
  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/types.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/types.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/types.ts
🧠 Learnings (1)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleNewBooking.ts (1)
packages/features/bookings/lib/handleNewBooking/types.ts (1)
  • InviteeItem (14-25)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (5)
packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts (2)

83-129: LGTM! Impersonation protection correctly implemented.

The query properly fetches users with preventEmailImpersonation enabled, checking both verified primary and secondary emails. The protection set correctly excludes unverified addresses by explicitly checking user.emailVerified before adding the primary email. This aligns with the feature requirements and addresses previous review concerns.


131-136: Guest filtering correctly excludes protected emails.

The deduplication logic consistently applies extractBaseEmail normalization and properly checks both blacklisted and protected email sets, preventing impersonation attempts through base-email variants (e.g., Gmail aliases).

packages/features/bookings/lib/handleNewBooking/types.ts (1)

14-27: LGTM! Clean type extraction.

The InviteeItem type clearly defines the attendee structure, and the addition of the optional phoneNumber field properly supports phone-based attendee identification. This refactor improves type reusability across the booking flow.

packages/features/bookings/lib/handleNewBooking.ts (2)

1145-1196: LGTM! Impersonation protection correctly guards booking creation.

The implementation precomputes base emails, guards the query when the guest list is empty (avoiding unnecessary DB hits), and correctly normalizes protected emails using extractBaseEmail. This prevents impersonation through email variants while ensuring only verified addresses are protected.


1247-1253: LGTM! Attendee list construction includes phone numbers.

The mapping correctly includes the phoneNumber field from InviteeItem, ensuring phone-based attendee details flow through the booking system consistently.

@Udit-takkar
Copy link
Contributor

@dhairyashiil there is also one more PR #24373 opened for the same issue.

@dhairyashiil
Copy link
Member Author

dhairyashiil commented Oct 9, 2025

@dhairyashiil there is also one more PR #24373 opened for the same issue.

Actually, I raised it first. At that time, there was no PR from Sargam. Maybe he didn’t know either, since none of us mentioned that we were working on it, communication issue.

Screenshot 2025-10-10 at 12 01 35 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bookings area: bookings, availability, timezones, double booking community-interns The team responsible for reviewing, testing and shipping low/medium community PRs consumer ✨ feature New feature or request High priority Created by Linear-GitHub Sync ❗️ migrations contains migration files size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User setting to prevent malicious impersonated bookings

3 participants