diff --git a/packages/trpc/server/createContext.ts b/packages/trpc/server/createContext.ts index 042fc4c738..b1f7a68b21 100644 --- a/packages/trpc/server/createContext.ts +++ b/packages/trpc/server/createContext.ts @@ -4,6 +4,7 @@ import type { Session } from "next-auth"; import type { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { getLocale } from "@calcom/features/auth/lib/getLocale"; +import getIP from "@calcom/lib/getIP"; import prisma, { readonlyPrisma } from "@calcom/prisma"; import type { SelectedCalendar, User as PrismaUser } from "@calcom/prisma/client"; @@ -12,6 +13,7 @@ import type { CreateNextContextOptions } from "@trpc/server/adapters/next"; type CreateContextOptions = CreateNextContextOptions | GetServerSidePropsContext; export type CreateInnerContextOptions = { + sourceIp?: string; session?: Session | null; locale: string; user?: @@ -64,8 +66,12 @@ export async function createContextInner(opts: CreateInnerContextOptions) { */ export const createContext = async ({ req, res }: CreateContextOptions, sessionGetter?: GetSessionFn) => { const locale = await getLocale(req); + + // This type may not be accurate if this request is coming from SSG init but they both should satisfy the requirements of getIP. + // TODO: @sean - figure out a way to make getIP be happy with trpc req. params + const sourceIp = getIP(req as NextApiRequest); const session = !!sessionGetter ? await sessionGetter({ req, res }) : null; - const contextInner = await createContextInner({ locale, session }); + const contextInner = await createContextInner({ locale, session, sourceIp }); return { ...contextInner, req, diff --git a/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts b/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts index 31927231ef..b3171438bd 100644 --- a/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts @@ -1,4 +1,5 @@ import { updateQuantitySubscriptionFromStripe } from "@calcom/features/ee/teams/lib/payments"; +import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants"; import { isTeamAdmin, isTeamOwner } from "@calcom/lib/server/queries/teams"; import { closeComDeleteTeamMembership } from "@calcom/lib/sync/SyncServiceManager"; @@ -14,11 +15,16 @@ type RemoveMemberOptions = { ctx: { user: NonNullable; prisma: PrismaClient; + sourceIp?: string; }; input: TRemoveMemberInputSchema; }; export const removeMemberHandler = async ({ ctx, input }: RemoveMemberOptions) => { + await checkRateLimitAndThrowError({ + identifier: `removeMember.${ctx.sourceIp}`, + }); + const isAdmin = await isTeamAdmin(ctx.user.id, input.teamId); const isOrgAdmin = ctx.user.organizationId ? await isTeamAdmin(ctx.user.id, ctx.user.organizationId)