diff --git a/apps/web/lib/getTemporaryOrgRedirect.ts b/apps/web/lib/getTemporaryOrgRedirect.ts index aa9b6cf824..f2d443f17a 100644 --- a/apps/web/lib/getTemporaryOrgRedirect.ts +++ b/apps/web/lib/getTemporaryOrgRedirect.ts @@ -3,7 +3,6 @@ import { stringify } from "querystring"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import type { PrismaClient } from "@calcom/prisma"; import type { RedirectType } from "@calcom/prisma/client"; const log = logger.getSubLogger({ prefix: ["lib", "getTemporaryOrgRedirect"] }); @@ -12,15 +11,13 @@ export const getTemporaryOrgRedirect = async ({ redirectType, eventTypeSlug, currentQuery, - prismaClient, }: { slugs: string[] | string; redirectType: RedirectType; eventTypeSlug: string | null; currentQuery: ParsedUrlQuery; - prismaClient?: PrismaClient; }) => { - const prisma = prismaClient ?? (await import("@calcom/prisma")).default; + const prisma = (await import("@calcom/prisma")).default; slugs = slugs instanceof Array ? slugs : [slugs]; log.debug( `Looking for redirect for`, diff --git a/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx b/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx index 835007460f..5a7a37ace9 100644 --- a/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx +++ b/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx @@ -2,11 +2,9 @@ import type { GetServerSidePropsContext } from "next"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; +import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booking"; -import { - orgDomainConfig, - whereClauseForOrgWithSlugOrRequestedSlug, -} from "@calcom/features/ee/organizations/lib/orgDomains"; +import { getSlugOrRequestedSlug, orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import { getOrganizationSEOSettings } from "@calcom/features/ee/organizations/lib/orgSettings"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; @@ -32,7 +30,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const { req, params, query } = context; const session = await getServerSession({ req }); const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(params); - const { rescheduleUid, isInstantMeeting: queryIsInstantMeeting } = query; + const { rescheduleUid, isInstantMeeting: queryIsInstantMeeting, email } = query; const allowRescheduleForCancelledBooking = query.allowRescheduleForCancelledBooking === "true"; const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req, params?.orgSlug); const isOrgContext = currentOrgDomain && isValidOrgDomain; @@ -43,7 +41,6 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => redirectType: RedirectType.Team, eventTypeSlug: meetingSlug, currentQuery: context.query, - prismaClient: prisma, }); if (redirect) { @@ -51,49 +48,43 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => } } - const [orgId, booking] = await Promise.all([ - isOrgContext ? getOrgId(currentOrgDomain) : Promise.resolve(null), - rescheduleUid ? getBookingForReschedule(`${rescheduleUid}`, session?.user?.id) : Promise.resolve(null), - ]); + const team = await getTeamWithEventsData(teamSlug, meetingSlug, isValidOrgDomain, currentOrgDomain); - const team = await getTeamData(teamSlug, orgId); - - if (!team) { + if (!team || !team.eventTypes?.[0]) { return { notFound: true } as const; } - const eventData = await getEventTypeData(meetingSlug, team.id); - - if (!eventData) { - return { notFound: true } as const; - } + const eventData = team.eventTypes[0]; if (rescheduleUid && eventData.disableRescheduling) { return { redirect: { destination: `/booking/${rescheduleUid}`, permanent: false } }; } - if ( - booking?.status === BookingStatus.CANCELLED && - !allowRescheduleForCancelledBooking && - !eventData.allowReschedulingCancelledBookings - ) { - return { - redirect: { - permanent: false, - destination: `/team/${teamSlug}/${meetingSlug}`, - }, - }; - } - const eventTypeId = eventData.id; + const eventHostsUserData = await getUsersData( + team.isPrivate, + eventTypeId, + eventData.hosts.map((h) => h.user) + ); const orgSlug = isValidOrgDomain ? currentOrgDomain : null; const name = team.parent?.name ?? team.name ?? null; - const eventHostsUserData = getEventHosts( - team.isPrivate, - eventData.hosts.map((h) => h.user), - eventData.users ?? [] - ); + let booking: GetBookingType | null = null; + if (rescheduleUid) { + booking = await getBookingForReschedule(`${rescheduleUid}`, session?.user?.id); + if ( + booking?.status === BookingStatus.CANCELLED && + !allowRescheduleForCancelledBooking && + !eventData.allowReschedulingCancelledBookings + ) { + return { + redirect: { + permanent: false, + destination: `/team/${teamSlug}/${meetingSlug}`, + }, + }; + } + } const fromRedirectOfNonOrgLink = context.query.orgRedirection === "true"; const isUnpublished = team.parent ? !team.parent.slug : !team.slug; @@ -104,9 +95,11 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => // Handle string[] type from query params let teamMemberEmail = Array.isArray(crmContactOwnerEmail) ? crmContactOwnerEmail[0] : crmContactOwnerEmail; + let crmOwnerRecordType = Array.isArray(crmContactOwnerRecordType) ? crmContactOwnerRecordType[0] : crmContactOwnerRecordType; + let crmAppSlug = Array.isArray(crmAppSlugParam) ? crmAppSlugParam[0] : crmAppSlugParam; if (!teamMemberEmail || !crmOwnerRecordType || !crmAppSlug) { @@ -129,6 +122,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const organizationSettings = getOrganizationSEOSettings(team); const allowSEOIndexing = organizationSettings?.allowSEOIndexing ?? false; + const featureRepo = new FeaturesRepository(); const teamHasApiV2Route = await featureRepo.checkIfTeamHasFeature(team.id, "use-api-v2-for-team-slots"); const useApiV2 = teamHasApiV2Route && hasApiV2RouteInEnv(); @@ -178,149 +172,116 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => }; }; -const getOrgId = async (orgSlug: string): Promise => { - const org = await prisma.team.findFirst({ - where: whereClauseForOrgWithSlugOrRequestedSlug(orgSlug), - select: { id: true }, - }); - - return org?.id ?? null; -}; - -const getTeamData = async (teamSlug: string, orgId: number | null) => { - const teamSelectFields = { - id: true, - isPrivate: true, - hideBranding: true, - logoUrl: true, - name: true, - slug: true, - isOrganization: true, - parent: { - select: { - slug: true, - name: true, - bannerUrl: true, - logoUrl: true, - hideBranding: true, - organizationSettings: { - select: { - allowSEOIndexing: true, - }, - }, - }, - }, - organizationSettings: { - select: { - allowSEOIndexing: true, - }, - }, - }; - - if (orgId !== null) { - const publishedTeam = await prisma.team.findUnique({ - where: { - slug_parentId: { - slug: teamSlug, - parentId: orgId, - }, - isOrganization: false, - }, - select: teamSelectFields, - }); - if (publishedTeam) return publishedTeam; - } - +const getTeamWithEventsData = async ( + teamSlug: string, + meetingSlug: string, + isValidOrgDomain: boolean, + currentOrgDomain: string | null +) => { return await prisma.team.findFirst({ where: { - parentId: orgId ?? null, - isOrganization: false, - OR: [ - { slug: teamSlug }, - { - metadata: { - path: ["requestedSlug"], - equals: teamSlug, - }, - }, - ], + ...getSlugOrRequestedSlug(teamSlug), + parent: isValidOrgDomain && currentOrgDomain ? getSlugOrRequestedSlug(currentOrgDomain) : null, }, - select: teamSelectFields, orderBy: { slug: { sort: "asc", nulls: "last" }, }, - }); -}; - -const getEventTypeData = async (meetingSlug: string, teamId: number) => { - return await prisma.eventType.findUnique({ - where: { - // Use the EventType_teamId_slug_key unique index - teamId_slug: { - teamId: teamId, - slug: meetingSlug, - }, - }, select: { id: true, - title: true, - isInstantEvent: true, - schedulingType: true, - metadata: true, - length: true, - hidden: true, - disableCancelling: true, - disableRescheduling: true, - allowReschedulingCancelledBookings: true, - interfaceLanguage: true, - hosts: { - take: 3, + isPrivate: true, + hideBranding: true, + parent: { select: { - user: { + slug: true, + name: true, + bannerUrl: true, + logoUrl: true, + hideBranding: true, + organizationSettings: { select: { - name: true, - username: true, + allowSEOIndexing: true, }, }, }, }, - // Include users for when hosts is empty - users: { - take: 1, + logoUrl: true, + name: true, + slug: true, + eventTypes: { + where: { + slug: meetingSlug, + }, select: { - username: true, - name: true, + id: true, + title: true, + isInstantEvent: true, + schedulingType: true, + metadata: true, + length: true, + hidden: true, + disableCancelling: true, + disableRescheduling: true, + allowReschedulingCancelledBookings: true, + interfaceLanguage: true, + hosts: { + take: 3, + select: { + user: { + select: { + name: true, + username: true, + email: true, + }, + }, + }, + }, + }, + }, + isOrganization: true, + organizationSettings: { + select: { + allowSEOIndexing: true, }, }, }, }); }; -const getEventHosts = ( +const getUsersData = async ( isPrivateTeam: boolean, - hosts: Pick[], + eventTypeId: number, users: Pick[] ) => { - if (isPrivateTeam) { - return []; - } - - if (hosts.length > 0) { - return hosts + if (!isPrivateTeam && users.length > 0) { + return users .filter((user) => user.username) .map((user) => ({ username: user.username ?? "", name: user.name ?? "", })); } - - if (users.length > 0) { - return [ - { - username: users[0].username ?? "", - name: users[0].name ?? "", + if (!isPrivateTeam && users.length === 0) { + const { users: data } = await prisma.eventType.findUniqueOrThrow({ + where: { id: eventTypeId }, + select: { + users: { + take: 1, + select: { + username: true, + name: true, + }, + }, }, - ]; + }); + + return data.length > 0 + ? [ + { + username: data[0].username ?? "", + name: data[0].name ?? "", + }, + ] + : []; } return []; diff --git a/packages/features/bookings/lib/get-booking.ts b/packages/features/bookings/lib/get-booking.ts index 92f754e662..ba44e23d07 100644 --- a/packages/features/bookings/lib/get-booking.ts +++ b/packages/features/bookings/lib/get-booking.ts @@ -156,7 +156,7 @@ export const getBookingForReschedule = async (uid: string, userId?: number) => { let attendeeEmail: string | null = null; let bookingSeatData: { description?: string; responses: Prisma.JsonValue } | null = null; if (!theBooking) { - const bookingSeat = await prisma.bookingSeat.findUnique({ + const bookingSeat = await prisma.bookingSeat.findFirst({ where: { referenceUid: uid, },