From ae9063804d2f1fdcd006dcde615556fccc3dd34b Mon Sep 17 00:00:00 2001 From: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:55:42 +0530 Subject: [PATCH] fix: Users details leak for team booking when the team is private (#17403) * fix: host details leaking * type error * update * update * Update getPublicEvent.ts * Update getPublicEvent.ts --- .../features/eventtypes/lib/getPublicEvent.ts | 28 +++++++++++++++++-- packages/lib/server/repository/event.ts | 5 ++-- .../server/middlewares/sessionMiddleware.ts | 2 +- .../routers/publicViewer/event.handler.ts | 5 ++-- .../routers/publicViewer/procedures/event.ts | 4 ++- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index 4de2cba600..24f682fa49 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -74,6 +74,7 @@ const publicEventSelect = Prisma.validator()({ seatsPerTimeSlot: true, seatsShowAvailabilityCount: true, bookingFields: true, + teamId: true, team: { select: { parentId: true, @@ -92,6 +93,7 @@ const publicEventSelect = Prisma.validator()({ logoUrl: true, }, }, + isPrivate: true, }, }, successRedirectUrl: true, @@ -206,7 +208,8 @@ export const getPublicEvent = async ( isTeamEvent: boolean | undefined, org: string | null, prisma: PrismaClient, - fromRedirectOfNonOrgLink: boolean + fromRedirectOfNonOrgLink: boolean, + currentUserId?: number ) => { const usernameList = getUsernameList(username); const orgQuery = org ? getSlugOrRequestedSlug(org) : null; @@ -377,7 +380,7 @@ export const getPublicEvent = async ( hosts: hosts, }; - const users = + let users = (await getUsersFromEvent(eventWithUserProfiles, prisma)) || (await getOwnerFromUsersArray(prisma, event.id)); @@ -423,6 +426,27 @@ export const getPublicEvent = async ( length: eventWithUserProfiles.length, }); } + const isTeamAdminOrOwner = await prisma.membership.findFirst({ + where: { + userId: currentUserId ?? -1, + teamId: event.teamId ?? -1, + accepted: true, + role: { in: ["ADMIN", "OWNER"] }, + }, + }); + + const isOrgAdminOrOwner = await prisma.membership.findFirst({ + where: { + userId: currentUserId ?? -1, + teamId: event.team?.parentId ?? -1, + accepted: true, + role: { in: ["ADMIN", "OWNER"] }, + }, + }); + + if (event.team?.isPrivate && !isTeamAdminOrOwner && !isOrgAdminOrOwner) { + users = []; + } return { ...eventWithUserProfiles, diff --git a/packages/lib/server/repository/event.ts b/packages/lib/server/repository/event.ts index a7f78bfaed..e1d2fa2223 100644 --- a/packages/lib/server/repository/event.ts +++ b/packages/lib/server/repository/event.ts @@ -3,14 +3,15 @@ import prisma from "@calcom/prisma"; import type { TEventInputSchema } from "@calcom/trpc/server/routers/publicViewer/event.schema"; export class EventRepository { - static async getPublicEvent(input: TEventInputSchema) { + static async getPublicEvent(input: TEventInputSchema, userId?: number) { const event = await getPublicEvent( input.username, input.eventSlug, input.isTeamEvent, input.org, prisma, - input.fromRedirectOfNonOrgLink + input.fromRedirectOfNonOrgLink, + userId ); return event; } diff --git a/packages/trpc/server/middlewares/sessionMiddleware.ts b/packages/trpc/server/middlewares/sessionMiddleware.ts index 745734f446..443f16b9a8 100644 --- a/packages/trpc/server/middlewares/sessionMiddleware.ts +++ b/packages/trpc/server/middlewares/sessionMiddleware.ts @@ -147,7 +147,7 @@ const getSession = async (ctx: TRPCContextInner) => { return req ? await getServerSession({ req, res }) : null; }; -const getUserSession = async (ctx: TRPCContextInner) => { +export const getUserSession = async (ctx: TRPCContextInner) => { /** * It is possible that the session and user have already been added to the context by a previous middleware * or when creating the context diff --git a/packages/trpc/server/routers/publicViewer/event.handler.ts b/packages/trpc/server/routers/publicViewer/event.handler.ts index 1744762288..1902468fec 100644 --- a/packages/trpc/server/routers/publicViewer/event.handler.ts +++ b/packages/trpc/server/routers/publicViewer/event.handler.ts @@ -4,10 +4,11 @@ import type { TEventInputSchema } from "./event.schema"; interface EventHandlerOptions { input: TEventInputSchema; + userId?: number; } -export const eventHandler = async ({ input }: EventHandlerOptions) => { - return await EventRepository.getPublicEvent(input); +export const eventHandler = async ({ input, userId }: EventHandlerOptions) => { + return await EventRepository.getPublicEvent(input, userId); }; export default eventHandler; diff --git a/packages/trpc/server/routers/publicViewer/procedures/event.ts b/packages/trpc/server/routers/publicViewer/procedures/event.ts index 734e7d11b3..6f96bc6856 100644 --- a/packages/trpc/server/routers/publicViewer/procedures/event.ts +++ b/packages/trpc/server/routers/publicViewer/procedures/event.ts @@ -1,3 +1,4 @@ +import { getUserSession } from "../../../middlewares/sessionMiddleware"; import publicProcedure from "../../../procedures/publicProcedure"; import { importHandler } from "../../../trpc"; import { ZEventInputSchema } from "../event.schema"; @@ -6,6 +7,7 @@ const NAMESPACE = "publicViewer"; const namespaced = (s: string) => `${NAMESPACE}.${s}`; export const event = publicProcedure.input(ZEventInputSchema).query(async (opts) => { + const { user } = await getUserSession(opts.ctx); const handler = await importHandler(namespaced("event"), () => import("../event.handler")); - return handler(opts); + return handler({ input: opts.input, userId: user?.id }); });