diff --git a/apps/web/pages/teams/index.tsx b/apps/web/pages/teams/index.tsx index 7785e8b873..acd2bdc653 100644 --- a/apps/web/pages/teams/index.tsx +++ b/apps/web/pages/teams/index.tsx @@ -18,7 +18,7 @@ function Teams() { size="fab" StartIcon={Icon.FiPlus} type="button" - href={`${WEBAPP_URL}/settings/teams/new?returnTo=/teams`}> + href={`${WEBAPP_URL}/settings/teams/new?returnTo=${WEBAPP_URL}/teams`}> {t("new")} }> diff --git a/packages/features/ee/teams/components/CreateANewTeamForm.tsx b/packages/features/ee/teams/components/CreateANewTeamForm.tsx index f77c2e3572..8ddbb26fbd 100644 --- a/packages/features/ee/teams/components/CreateANewTeamForm.tsx +++ b/packages/features/ee/teams/components/CreateANewTeamForm.tsx @@ -2,6 +2,7 @@ import { useRouter } from "next/router"; import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; +import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import slugify from "@calcom/lib/slugify"; import { trpc } from "@calcom/trpc/react"; @@ -19,7 +20,9 @@ export const CreateANewTeamForm = () => { const returnToParsed = querySchema.safeParse(router.query); - const returnToParam = returnToParsed.success ? returnToParsed.data.returnTo : "/settings/teams"; + const returnToParam = + (returnToParsed.success ? getSafeRedirectUrl(returnToParsed.data.returnTo) : "/settings/teams") || + "/settings/teams"; const newTeamFormMethods = useForm(); diff --git a/packages/lib/getSafeRedirectUrl.ts b/packages/lib/getSafeRedirectUrl.ts index 1ddf4acced..2c9688eb84 100644 --- a/packages/lib/getSafeRedirectUrl.ts +++ b/packages/lib/getSafeRedirectUrl.ts @@ -5,6 +5,8 @@ export const getSafeRedirectUrl = (url = "") => { if (!url) { return null; } + + //It is important that this fn is given absolute URL because urls that don't start with HTTP can still deceive browser into redirecting to another domain if (url.search(/^https?:\/\//) === -1) { throw new Error("Pass an absolute URL"); } diff --git a/packages/trpc/server/routers/viewer.tsx b/packages/trpc/server/routers/viewer.tsx index fa1d0f5303..f1309c81f0 100644 --- a/packages/trpc/server/routers/viewer.tsx +++ b/packages/trpc/server/routers/viewer.tsx @@ -397,8 +397,23 @@ const loggedInViewerRouter = router({ let where; - if (eventTypeId) where = { eventTypeId }; - else where = { userId: user.id }; + if (eventTypeId) { + if ( + !(await prisma.eventType.findFirst({ + where: { + id: eventTypeId, + userId: user.id, + }, + })) + ) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: `You don't have access to event type ${eventTypeId}`, + }); + } + + where = { eventTypeId }; + } else where = { userId: user.id }; await ctx.prisma.destinationCalendar.upsert({ where, @@ -726,42 +741,7 @@ const loggedInViewerRouter = router({ }) ); }), - eventTypePosition: authedProcedure - .input( - z.object({ - eventType: z.number(), - action: z.string(), - }) - ) - .mutation(async ({ input, ctx }) => { - // This mutation is for the user to be able to order their event types by incrementing or decrementing the position number - const { prisma } = ctx; - if (input.eventType && input.action == "increment") { - await prisma.eventType.update({ - where: { - id: input.eventType, - }, - data: { - position: { - increment: 1, - }, - }, - }); - } - - if (input.eventType && input.action == "decrement") { - await prisma.eventType.update({ - where: { - id: input.eventType, - }, - data: { - position: { - decrement: 1, - }, - }, - }); - } - }), + //Comment for PR: eventTypePosition is not used anywhere submitFeedback: authedProcedure .input( z.object({ diff --git a/packages/trpc/server/routers/viewer/availability.tsx b/packages/trpc/server/routers/viewer/availability.tsx index 9a9b7bcff2..a69254342d 100644 --- a/packages/trpc/server/routers/viewer/availability.tsx +++ b/packages/trpc/server/routers/viewer/availability.tsx @@ -173,7 +173,6 @@ export const availabilityRouter = router({ .input( z.object({ name: z.string(), - copyScheduleId: z.number().optional(), schedule: z .array( z.array( @@ -189,6 +188,22 @@ export const availabilityRouter = router({ ) .mutation(async ({ input, ctx }) => { const { user, prisma } = ctx; + if (input.eventTypeId) { + const eventType = await prisma.eventType.findUnique({ + where: { + id: input.eventTypeId, + }, + select: { + userId: true, + }, + }); + if (!eventType || eventType.userId !== user.id) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to create a schedule for this event type", + }); + } + } const data: Prisma.ScheduleCreateInput = { name: input.name, user: { diff --git a/packages/trpc/server/routers/viewer/bookings.tsx b/packages/trpc/server/routers/viewer/bookings.tsx index fcb44990c5..38af479dba 100644 --- a/packages/trpc/server/routers/viewer/bookings.tsx +++ b/packages/trpc/server/routers/viewer/bookings.tsx @@ -818,6 +818,22 @@ export const bookingsRouter = router({ }; const recurringEvent = parseRecurringEvent(booking.eventType?.recurringEvent); + if (recurringEventId) { + if ( + !(await prisma.booking.findFirst({ + where: { + recurringEventId, + id: booking.id, + }, + })) + ) { + // FIXME: It might be best to retrieve recurringEventId from the booking itself. + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "Recurring event id doesn't belong to the booking", + }); + } + } if (recurringEventId && recurringEvent) { const groupedRecurringBookings = await prisma.booking.groupBy({ where: {