Skip to content

Add guest management functionality to existing bookings#9

Draft
ShashankFC wants to merge 1 commit into
guest-management-basefrom
guest-management-enhanced
Draft

Add guest management functionality to existing bookings#9
ShashankFC wants to merge 1 commit into
guest-management-basefrom
guest-management-enhanced

Conversation

@ShashankFC

Copy link
Copy Markdown
Collaborator

Test 10nn---nReplicated from ai-code-review-evaluation/cal.com-greptile#10

* feat: ability to add guests via app.cal.com/bookings

* fix: some update

* fix: minor issue

* fix: final update

* update

* update

* add requested changes

* fix type error

* small update

* final update

* fix type error

* fix location

* update calender event

---------

Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
@github-actions

Copy link
Copy Markdown
Contributor

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "Add guest management functionality to existing bookings". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@ShashankFC

Copy link
Copy Markdown
Collaborator Author

@claude

@claude

claude Bot commented Jan 7, 2026

Copy link
Copy Markdown

Claude finished @ShashankFC's task in 2m 37s —— View job


Code Review Complete ✓

Tasks

  • Read repository guidelines (CLAUDE.md)
  • Get PR diff and understand changes
  • Review UI components (AddGuestsDialog, MultiEmail)
  • Review backend logic (addGuests handler)
  • Review email templates
  • Check for security issues
  • Check for bugs and edge cases
  • Provide comprehensive feedback

Overview

This PR adds functionality to add guests to existing bookings. The implementation includes a UI dialog, tRPC endpoint, email notifications, and calendar event updates. Overall, the feature is well-structured, but there are several critical security issues, bugs, and code quality concerns that need to be addressed.


🔴 Critical Issues

1. Authorization Logic Bug (Security)

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:46-48

const isTeamAdminOrOwner =
  (await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) &&
  (await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));

Problem: Uses && (AND) instead of || (OR). This means a user must be both an admin AND an owner, which is likely impossible. This breaks team admin/owner permissions entirely.

Fix: Should be || (OR) - a user should be authorized if they are either an admin OR an owner.

Fix this →

2. Missing Email Validation in Frontend Schema

File: apps/web/components/dialog/AddGuestsDialog.tsx:26-29

const ZAddGuestsInputSchema = z.array(z.string().email()).refine((emails) => {
  const uniqueEmails = new Set(emails);
  return uniqueEmails.size === emails.length;
});

Problem: The frontend validates uniqueness but doesn't filter out empty strings before validation. The initial state is ["""], which can pass through if the user clicks "Add" without entering any email.

Impact: Line 49 checks multiEmailValue.length === 0, but an array with empty strings has length > 0, so the check doesn't catch this case.

Fix this →


🟡 Important Issues

3. Poor Error Handling in Email Sending

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:167-171

try {
  await sendAddGuestsEmails(evt, guests);
} catch (err) {
  console.log("Error sending AddGuestsEmails");
}

Problems:

  • Error is silently swallowed - guests are added to booking, but they won't receive emails
  • Uses console.log instead of proper logging
  • No error details logged (should log err)
  • User gets success message even if emails fail

Suggestion: Either propagate the error or log properly with the logger that's already imported but unused.

Fix this →

4. Unused Import

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:1

The logger is imported but never used (related to issue #3).

5. Case-Sensitive Email Filtering Issue

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:74-78

const uniqueGuests = guests.filter(
  (guest) =>
    !booking.attendees.some((attendee) => guest === attendee.email) &&
    !blacklistedGuestEmails.includes(guest)
);

Problem: The guest === attendee.email comparison is case-sensitive, but emails should be case-insensitive. A user could add User@Example.com when user@example.com is already an attendee.

Note: Blacklisted emails are lowercased (line 71), but incoming guests are not lowercased before comparison.

Fix this →

6. Calendar Update Error Handling

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:165

await eventManager.updateCalendarAttendees(evt, booking);

Problem: No error handling. If calendar provider (Google Calendar, etc.) fails, the database will have the guests added, but the calendar event won't be updated. This creates data inconsistency.

Suggestion: Wrap in try-catch and decide whether to rollback the database changes or just log/warn the user.


🔵 Code Quality Issues

7. Missing Required Translations

File: apps/web/public/static/locales/en/common.json

New translation keys added:

  • additional_guests
  • add_emails
  • guests_added
  • unable_to_add_guests
  • emails_must_be_unique_valid
  • guests_added_event_type_subject

Problem: Only English translations are added. Other locales need these keys too, or they'll fall back to the key name for non-English users.

8. Inconsistent Error State Reset

File: apps/web/components/dialog/AddGuestsDialog.tsx:89-93

The cancel button resets isInvalidEmail to false, but the main dialog close (clicking outside or X button) via onOpenChange doesn't reset this state. If a user sees an error, closes the dialog by clicking outside, and reopens it, the error message will still be visible.

Fix this →

9. Potential Race Condition

File: apps/web/components/dialog/AddGuestsDialog.tsx:35-46

The success handler calls setIsOpenDialog(false) and setMultiEmailValue([""]) immediately, then invalidates queries. If the dialog closes before invalidation completes, the user might not see updated data.

Low priority but consider awaiting the invalidation.

10. Empty Name for New Guests

File: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts:83-90

const guestsFullDetails = uniqueGuests.map((guest) => {
  return {
    name: "",
    email: guest,
    timeZone: organizer.timeZone,
    locale: organizer.locale,
  };
});

All new guests get an empty string for name. While this might be intentional (since we only have emails), it could cause display issues in UIs that expect names. Consider using the email username part or "Guest" as a fallback.

11. Missing Accessibility Label

File: packages/ui/form/MultiEmail.tsx:46

<Tooltip content="Remove email">

The remove button inside the tooltip doesn't have an aria-label. Screen reader users might not understand what the X button does.

12. PR Title Doesn't Follow Convention

As noted by the bot, the PR title should follow Conventional Commits. It should be:

feat: add guest management functionality to existing bookings

✅ Positive Aspects

  1. Good Authorization Check Structure: The handler properly checks if the user is an organizer, attendee, or team admin/owner (despite the bug in the logic).

  2. Blacklist Feature: Good security measure with BLACKLISTED_GUEST_EMAILS environment variable.

  3. Duplicate Prevention: Frontend validates unique emails, and backend filters out existing attendees.

  4. Comprehensive Email Notifications: Sends different emails to organizers (notification of new guests) and new guests (invitation) vs. existing attendees (notification).

  5. Calendar Sync: Updates calendar events via EventManager, keeping external calendars in sync.

  6. Lazy Loading: Uses MultiEmailLazy.tsx for code splitting.

  7. Good Type Safety: Uses Zod schemas for validation on both frontend and backend.


Summary

Must Fix Before Merge:

Should Fix:

Nice to Have:


@github-actions

Copy link
Copy Markdown
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions Bot added the Stale label Jan 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants