Skip to content

Conversation

@akshayutture-augment
Copy link

* 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 <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@akshayutture-augment
Copy link
Author

@greptileai

@greptile-apps
Copy link

greptile-apps bot commented Nov 14, 2025

Greptile Overview

Confidence Score: 1/5

  • This PR has a critical authorization bug that breaks team admin/owner permissions
  • The authorization logic in addGuests.handler.ts:46-48 uses AND (&&) instead of OR (||), making it impossible for team admins or owners to add guests unless they're both admin AND owner simultaneously. This is a logical impossibility that will cause runtime failures for legitimate users. Additionally, the empty string validation issue could cause unexpected behavior.
  • Critical attention required for packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts - fix the authorization logic before merging

Important Files Changed

File Analysis

Filename Score Overview
packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts 1/5 Core handler with critical authorization bug (AND instead of OR) and missing empty string filtering
apps/web/components/dialog/AddGuestsDialog.tsx 3/5 Dialog component with validation that doesn't filter empty strings before checking emails
packages/ui/form/MultiEmail.tsx 4/5 Multi-email input component allowing empty strings in array
packages/emails/email-manager.ts 5/5 Email sending logic correctly differentiates between new and existing attendees
packages/trpc/server/routers/viewer/bookings/_router.tsx 5/5 Router setup follows existing async import pattern correctly

Sequence Diagram

sequenceDiagram
    participant User
    participant BookingListItem
    participant AddGuestsDialog
    participant MultiEmail
    participant tRPC
    participant addGuestsHandler
    participant Prisma
    participant EventManager
    participant EmailService

    User->>BookingListItem: Click "Additional Guests"
    BookingListItem->>AddGuestsDialog: Open dialog
    AddGuestsDialog->>MultiEmail: Render email inputs
    User->>MultiEmail: Enter guest emails
    MultiEmail->>AddGuestsDialog: Update email array
    User->>AddGuestsDialog: Click "Add"
    AddGuestsDialog->>AddGuestsDialog: Validate emails (zod)
    AddGuestsDialog->>tRPC: addGuests.mutate({bookingId, guests})
    tRPC->>addGuestsHandler: Route to handler
    addGuestsHandler->>Prisma: Fetch booking with attendees
    Prisma-->>addGuestsHandler: Return booking data
    addGuestsHandler->>addGuestsHandler: Check authorization (admin/owner/organizer/attendee)
    addGuestsHandler->>addGuestsHandler: Filter unique guests & blacklist
    addGuestsHandler->>Prisma: Create new attendees
    Prisma-->>addGuestsHandler: Return updated booking
    addGuestsHandler->>EventManager: updateCalendarAttendees(evt, booking)
    EventManager-->>addGuestsHandler: Calendar updated
    addGuestsHandler->>EmailService: sendAddGuestsEmails(evt, guests)
    EmailService->>EmailService: Send OrganizerAddGuestsEmail
    EmailService->>EmailService: Send AttendeeScheduledEmail (new guests)
    EmailService->>EmailService: Send AttendeeAddGuestsEmail (existing)
    EmailService-->>addGuestsHandler: Emails sent
    addGuestsHandler-->>tRPC: Success response
    tRPC-->>AddGuestsDialog: onSuccess callback
    AddGuestsDialog->>AddGuestsDialog: Show success toast
    AddGuestsDialog->>AddGuestsDialog: Close dialog & reset
    AddGuestsDialog->>tRPC: Invalidate bookings cache
    tRPC->>BookingListItem: Refresh booking data
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

15 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +46 to +48
const isTeamAdminOrOwner =
(await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) &&
(await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));
Copy link

Choose a reason for hiding this comment

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

logic: incorrect logic - user must be both admin AND owner (impossible), should be OR

Suggested change
const isTeamAdminOrOwner =
(await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) &&
(await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));
const isTeamAdminOrOwner =
(await isTeamAdmin(user.id, booking.eventType?.teamId ?? 0)) ||
(await isTeamOwner(user.id, booking.eventType?.teamId ?? 0));
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
Line: 46:48

Comment:
**logic:** incorrect logic - user must be both admin AND owner (impossible), should be OR

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

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +74 to +78
const uniqueGuests = guests.filter(
(guest) =>
!booking.attendees.some((attendee) => guest === attendee.email) &&
!blacklistedGuestEmails.includes(guest)
);
Copy link

Choose a reason for hiding this comment

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

logic: empty strings not filtered - if user enters and removes emails in UI, empty strings reach backend

Suggested change
const uniqueGuests = guests.filter(
(guest) =>
!booking.attendees.some((attendee) => guest === attendee.email) &&
!blacklistedGuestEmails.includes(guest)
);
const uniqueGuests = guests
.filter((guest) => guest.trim().length > 0)
.filter(
(guest) =>
!booking.attendees.some((attendee) => guest === attendee.email) &&
!blacklistedGuestEmails.includes(guest.toLowerCase())
);
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/server/routers/viewer/bookings/addGuests.handler.ts
Line: 74:78

Comment:
**logic:** empty strings not filtered - if user enters and removes emails in UI, empty strings reach backend

```suggestion
  const uniqueGuests = guests
    .filter((guest) => guest.trim().length > 0)
    .filter(
      (guest) =>
        !booking.attendees.some((attendee) => guest === attendee.email) &&
        !blacklistedGuestEmails.includes(guest.toLowerCase())
    );
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +52 to +57
const validationResult = ZAddGuestsInputSchema.safeParse(multiEmailValue);
if (validationResult.success) {
addGuestsMutation.mutate({ bookingId, guests: multiEmailValue });
} else {
setIsInvalidEmail(true);
}
Copy link

Choose a reason for hiding this comment

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

logic: validation doesn't filter empty strings before checking uniqueness and emails

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/components/dialog/AddGuestsDialog.tsx
Line: 52:57

Comment:
**logic:** validation doesn't filter empty strings before checking uniqueness and emails

How can I resolve this? If you propose a fix, please make it concise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants