From 7a4795bdbfbf502240b9aa985fba569dd391d75e Mon Sep 17 00:00:00 2001 From: alannnc Date: Tue, 9 Aug 2022 11:23:12 -0600 Subject: [PATCH] Fix request-reschedule for team events (#3721) --- apps/web/pages/api/book/event.ts | 6 ++- apps/web/pages/api/book/request-reschedule.ts | 42 ++++++++++++++----- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/apps/web/pages/api/book/event.ts b/apps/web/pages/api/book/event.ts index 43fb4bba2f..8141c89f92 100644 --- a/apps/web/pages/api/book/event.ts +++ b/apps/web/pages/api/book/event.ts @@ -271,9 +271,13 @@ async function handler(req: NextApiRequest) { users.push(eventTypeUser); } const [organizerUser] = users; + /** + * @TODO: add a validation to check if organizerUser is found, otherwise it will throw error on user not found + * Probably an alert email to team owner should be sent + */ const organizer = await prisma.user.findUnique({ where: { - id: organizerUser.id, + id: organizerUser?.id, }, select: { locale: true, diff --git a/apps/web/pages/api/book/request-reschedule.ts b/apps/web/pages/api/book/request-reschedule.ts index 3d06b26aac..c1c05f9ef1 100644 --- a/apps/web/pages/api/book/request-reschedule.ts +++ b/apps/web/pages/api/book/request-reschedule.ts @@ -54,6 +54,7 @@ const findUserDataByUserId = async (userId: number) => { locale: true, credentials: true, destinationCalendar: true, + teams: true, }, }); }; @@ -67,10 +68,10 @@ const handler = async ( bookingId, rescheduleReason: cancellationReason, }: { bookingId: string; rescheduleReason: string; cancellationReason: string } = req.body; - let userOwner: Awaited>; + let user: Awaited>; try { if (session?.user?.id) { - userOwner = await findUserDataByUserId(session?.user.id); + user = await findUserDataByUserId(session?.user.id); } else { return res.status(501).end(); } @@ -79,15 +80,16 @@ const handler = async ( select: { id: true, uid: true, + userId: true, title: true, description: true, startTime: true, endTime: true, eventTypeId: true, + eventType: true, location: true, attendees: true, references: true, - userId: true, customInputs: true, dynamicEventSlugRef: true, dynamicGroupSlugRef: true, @@ -104,9 +106,25 @@ const handler = async ( }, }); - if (bookingToReschedule.userId !== userOwner.id) throw new Error("UNAUTHORIZED"); + if (!bookingToReschedule.userId) { + throw new Error("Booking to reschedule doesn't have an owner."); + } + if (!bookingToReschedule.eventType) { + throw new Error("EventType not found for current booking."); + } - if (bookingToReschedule && userOwner) { + const bookingBelongsToTeam = !!bookingToReschedule.eventType?.teamId; + if (bookingBelongsToTeam && bookingToReschedule.eventType?.teamId) { + const userTeamIds = user.teams.map((item) => item.teamId); + if (userTeamIds.indexOf(bookingToReschedule?.eventType?.teamId) === -1) { + throw new Error("User isn't a member on the team"); + } + } + if (!bookingBelongsToTeam && bookingToReschedule.userId !== user.id) { + throw new Error("User isn't owner of the current booking"); + } + + if (bookingToReschedule && user) { let event: Partial = {}; if (bookingToReschedule.eventTypeId) { event = await prisma.eventType.findFirst({ @@ -152,8 +170,8 @@ const handler = async ( }); }; - const userOwnerTranslation = await getTranslation(userOwner.locale ?? "en", "common"); - const [userOwnerAsPeopleType] = usersToPeopleType([userOwner], userOwnerTranslation); + const userTranslation = await getTranslation(user.locale ?? "en", "common"); + const [userAsPeopleType] = usersToPeopleType([user], userTranslation); const builder = new CalendarEventBuilder(); builder.init({ @@ -166,7 +184,7 @@ const handler = async ( bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[], tAttendees ), - organizer: userOwnerAsPeopleType, + organizer: userAsPeopleType, }); const director = new CalendarEventDirector(); @@ -182,7 +200,7 @@ const handler = async ( // Handling calendar and videos cancellation // This can set previous time as available, until virtual calendar is done const credentialsMap = new Map(); - userOwner.credentials.forEach((credential) => { + user.credentials.forEach((credential) => { credentialsMap.set(credential.type, credential); }); const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter( @@ -216,7 +234,7 @@ const handler = async ( customInputs: isPrismaObjOrUndefined(bookingToReschedule.customInputs), startTime: bookingToReschedule?.startTime ? dayjs(bookingToReschedule.startTime).format() : "", endTime: bookingToReschedule?.endTime ? dayjs(bookingToReschedule.endTime).format() : "", - organizer: userOwnerAsPeopleType, + organizer: userAsPeopleType, attendees: usersToPeopleType( // username field doesn't exists on attendee but could be in the future bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[], @@ -251,7 +269,9 @@ const handler = async ( return res.status(200).json(bookingToReschedule); } catch (error) { - throw new Error("Error.request.reschedule"); + if (error instanceof Error) { + throw new Error("Error.request.reschedule " + error?.message); + } } };