diff --git a/apps/web/app/d/[link]/[slug]/page.tsx b/apps/web/app/d/[link]/[slug]/page.tsx index 0d194c685322de..50984b836a0f02 100644 --- a/apps/web/app/d/[link]/[slug]/page.tsx +++ b/apps/web/app/d/[link]/[slug]/page.tsx @@ -28,6 +28,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) => isTeamEvent, org, fromRedirectOfNonOrgLink: legacyCtx.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile?.name ?? ""; diff --git a/apps/web/app/future/[user]/[type]/page.tsx b/apps/web/app/future/[user]/[type]/page.tsx index 3a61c20e5badb9..0fce87470a134d 100644 --- a/apps/web/app/future/[user]/[type]/page.tsx +++ b/apps/web/app/future/[user]/[type]/page.tsx @@ -28,6 +28,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => { isTeamEvent: false, org: isValidOrgDomain ? currentOrgDomain : null, fromRedirectOfNonOrgLink: legacyCtx.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile?.name ?? ""; diff --git a/apps/web/app/future/org/[orgSlug]/instant-meeting/team/[slug]/[type]/page.tsx b/apps/web/app/future/org/[orgSlug]/instant-meeting/team/[slug]/[type]/page.tsx index 2786759be38759..5f27b9b94abe17 100644 --- a/apps/web/app/future/org/[orgSlug]/instant-meeting/team/[slug]/[type]/page.tsx +++ b/apps/web/app/future/org/[orgSlug]/instant-meeting/team/[slug]/[type]/page.tsx @@ -27,6 +27,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) => isTeamEvent: true, org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile.name ?? ""; diff --git a/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx b/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx index ea51f5cd9b771b..45a259e684b808 100644 --- a/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx +++ b/apps/web/app/future/org/[orgSlug]/team/[slug]/[type]/page.tsx @@ -25,6 +25,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) => isTeamEvent: true, org: isValidOrgDomain ? currentOrgDomain : null, fromRedirectOfNonOrgLink: legacyCtx.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile?.name ?? ""; diff --git a/apps/web/app/future/team/[slug]/[type]/embed/page.tsx b/apps/web/app/future/team/[slug]/[type]/embed/page.tsx index 378a528ff517dc..d41adfde432625 100644 --- a/apps/web/app/future/team/[slug]/[type]/embed/page.tsx +++ b/apps/web/app/future/team/[slug]/[type]/embed/page.tsx @@ -26,6 +26,7 @@ export const generateMetadata = async ({ params, searchParams }: _PageProps) => isTeamEvent: true, org: isValidOrgDomain ? currentOrgDomain : null, fromRedirectOfNonOrgLink: legacyCtx.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile?.name ?? ""; diff --git a/apps/web/app/future/team/[slug]/[type]/page.tsx b/apps/web/app/future/team/[slug]/[type]/page.tsx index debf7575b85c76..abca995aeb267c 100644 --- a/apps/web/app/future/team/[slug]/[type]/page.tsx +++ b/apps/web/app/future/team/[slug]/[type]/page.tsx @@ -24,6 +24,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => { isTeamEvent: true, org: isValidOrgDomain ? currentOrgDomain : null, fromRedirectOfNonOrgLink: legacyCtx.query.orgRedirection === "true", + limitHostsToThree: true, }); const profileName = event?.profile?.name ?? ""; diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx index 888e15625331af..9881f9a437f9f0 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx @@ -12,7 +12,7 @@ import { FromTime } from "../../utils/dates"; import { useEvent } from "../../utils/event"; const BookEventFormWrapper = ({ children, onCancel }: { onCancel: () => void; children: ReactNode }) => { - const { data } = useEvent(); + const { data } = useEvent({ limitHostsToThree: true }); return ; }; diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index fd04b3eebe9e8b..6809e9d38c4916 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -19,7 +19,7 @@ export type useScheduleForEventReturnType = ReturnType { +export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean; limitHostsToThree?: boolean }) => { const [username, eventSlug, isTeamEvent, org] = useBookerStore( (state) => [state.username, state.eventSlug, state.isTeamEvent, state.org], shallow @@ -32,6 +32,7 @@ export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean }) => { isTeamEvent, org: org ?? null, fromRedirectOfNonOrgLink: props?.fromRedirectOfNonOrgLink, + limitHostsToThree: props?.limitHostsToThree, }, { refetchOnWindowFocus: false, diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index f136c9e1af9a5d..e6b92be6dcd9e9 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -178,7 +178,7 @@ const EmailEmbed = ({ ], shallow ); - const event = useEvent(); + const event = useEvent({ limitHostsToThree: true }); const schedule = useScheduleForEvent({ orgSlug, eventId: eventType?.id, isTeamEvent }); const nonEmptyScheduleDays = useNonEmptyScheduleDays(schedule?.data?.slots); diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index d3fa3c5f9278f5..050a7fbeac3eee 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -50,99 +50,6 @@ const userSelect = Prisma.validator()({ defaultScheduleId: true, }); -const publicEventSelect = Prisma.validator()({ - id: true, - title: true, - description: true, - eventName: true, - slug: true, - isInstantEvent: true, - instantMeetingParameters: true, - aiPhoneCallConfig: true, - schedulingType: true, - length: true, - locations: true, - customInputs: true, - disableGuests: true, - metadata: true, - lockTimeZoneToggleOnBookingPage: true, - requiresConfirmation: true, - autoTranslateDescriptionEnabled: true, - fieldTranslations: { - select: { - translatedText: true, - targetLocale: true, - field: true, - }, - }, - requiresBookerEmailVerification: true, - recurringEvent: true, - price: true, - currency: true, - seatsPerTimeSlot: true, - seatsShowAvailabilityCount: true, - bookingFields: true, - teamId: true, - team: { - select: { - parentId: true, - metadata: true, - brandColor: true, - darkBrandColor: true, - slug: true, - name: true, - logoUrl: true, - theme: true, - parent: { - select: { - slug: true, - name: true, - bannerUrl: true, - logoUrl: true, - }, - }, - isPrivate: true, - }, - }, - successRedirectUrl: true, - forwardParamsSuccessRedirect: true, - workflows: { - include: { - workflow: { - include: { - steps: true, - }, - }, - }, - }, - hosts: { - select: { - user: { - select: userSelect, - }, - }, - }, - owner: { - select: userSelect, - }, - schedule: { - select: { - id: true, - timeZone: true, - }, - }, - instantMeetingSchedule: { - select: { - id: true, - timeZone: true, - }, - }, - - hidden: true, - assignAllTeamMembers: true, - rescheduleWithSameRoundRobinHost: true, -}); - export async function isCurrentlyAvailable({ prisma, instantMeetingScheduleId, @@ -209,6 +116,102 @@ function isAvailableInTimeSlot( return isWithinPeriod; } +const getPublicEventSelect = (limitHostsToThree?: boolean) => { + return Prisma.validator()({ + id: true, + title: true, + description: true, + eventName: true, + slug: true, + isInstantEvent: true, + instantMeetingParameters: true, + aiPhoneCallConfig: true, + schedulingType: true, + length: true, + locations: true, + customInputs: true, + disableGuests: true, + metadata: true, + lockTimeZoneToggleOnBookingPage: true, + requiresConfirmation: true, + autoTranslateDescriptionEnabled: true, + fieldTranslations: { + select: { + translatedText: true, + targetLocale: true, + field: true, + }, + }, + requiresBookerEmailVerification: true, + recurringEvent: true, + price: true, + currency: true, + seatsPerTimeSlot: true, + seatsShowAvailabilityCount: true, + bookingFields: true, + teamId: true, + team: { + select: { + parentId: true, + metadata: true, + brandColor: true, + darkBrandColor: true, + slug: true, + name: true, + logoUrl: true, + theme: true, + parent: { + select: { + slug: true, + name: true, + bannerUrl: true, + logoUrl: true, + }, + }, + isPrivate: true, + }, + }, + successRedirectUrl: true, + forwardParamsSuccessRedirect: true, + workflows: { + include: { + workflow: { + include: { + steps: true, + }, + }, + }, + }, + hosts: { + select: { + user: { + select: userSelect, + }, + }, + ...(limitHostsToThree ? { take: 3 } : {}), + }, + owner: { + select: userSelect, + }, + schedule: { + select: { + id: true, + timeZone: true, + }, + }, + instantMeetingSchedule: { + select: { + id: true, + timeZone: true, + }, + }, + + hidden: true, + assignAllTeamMembers: true, + rescheduleWithSameRoundRobinHost: true, + }); +}; + // TODO: Convert it to accept a single parameter with structured data export const getPublicEvent = async ( username: string, @@ -217,8 +220,10 @@ export const getPublicEvent = async ( org: string | null, prisma: PrismaClient, fromRedirectOfNonOrgLink: boolean, - currentUserId?: number + currentUserId?: number, + limitHostsToThree?: boolean ) => { + const publicEventSelect = getPublicEventSelect(limitHostsToThree); const usernameList = getUsernameList(username); const orgQuery = org ? getSlugOrRequestedSlug(org) : null; // In case of dynamic group event, we fetch user's data and use the default event. @@ -504,7 +509,7 @@ export const getPublicEvent = async ( }; const eventData = Prisma.validator()({ - select: publicEventSelect, + select: getPublicEventSelect(false), }); type Event = Prisma.EventTypeGetPayload; diff --git a/packages/lib/server/repository/event.ts b/packages/lib/server/repository/event.ts index e1d2fa222391d5..09d6e33b19dfeb 100644 --- a/packages/lib/server/repository/event.ts +++ b/packages/lib/server/repository/event.ts @@ -11,7 +11,8 @@ export class EventRepository { input.org, prisma, input.fromRedirectOfNonOrgLink, - userId + userId, + input.limitHostsToThree ); return event; } diff --git a/packages/platform/atoms/booker/BookerWebWrapper.tsx b/packages/platform/atoms/booker/BookerWebWrapper.tsx index 88eb7acc686bfc..4a7312b1b31dd3 100644 --- a/packages/platform/atoms/booker/BookerWebWrapper.tsx +++ b/packages/platform/atoms/booker/BookerWebWrapper.tsx @@ -31,7 +31,10 @@ export const BookerWebWrapper = (props: BookerWebWrapperAtomProps) => { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); - const event = useEvent({ fromRedirectOfNonOrgLink: props.entity.fromRedirectOfNonOrgLink }); + const event = useEvent({ + fromRedirectOfNonOrgLink: props.entity.fromRedirectOfNonOrgLink, + limitHostsToThree: true, + }); const bookerLayout = useBookerLayout(event.data); const selectedDate = searchParams?.get("date"); diff --git a/packages/trpc/server/routers/publicViewer/event.schema.ts b/packages/trpc/server/routers/publicViewer/event.schema.ts index d10a5965cccbef..fc52c3c2587ae2 100644 --- a/packages/trpc/server/routers/publicViewer/event.schema.ts +++ b/packages/trpc/server/routers/publicViewer/event.schema.ts @@ -10,6 +10,7 @@ export const ZEventInputSchema = z.object({ * Based on this decision like whether to allow unpublished organization's event to be served or not can be made. */ fromRedirectOfNonOrgLink: z.boolean().optional().default(false), + limitHostsToThree: z.boolean().optional().default(false), }); export type TEventInputSchema = z.infer;