Skip to content

Commit

Permalink
Merge branch 'main' into refactor_allow_managed_event_tests_parallel_…
Browse files Browse the repository at this point in the history
…runs
  • Loading branch information
zomars committed Sep 4, 2024
2 parents 3dc385b + 36e79bf commit 0f6d3ab
Show file tree
Hide file tree
Showing 17 changed files with 680 additions and 224 deletions.
65 changes: 42 additions & 23 deletions apps/api/v1/pages/api/bookings/[id]/_auth-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,59 @@ async function authMiddleware(req: NextApiRequest) {
}
}

const userWithBookingsAndTeamIds = await prisma.user.findUnique({
const user = await prisma.user.findUnique({
where: { id: userId },
include: {
select: {
email: true,
bookings: true,
teams: {
select: {
teamId: true,
},
},
},
});

if (!userWithBookingsAndTeamIds) throw new HttpError({ statusCode: 404, message: "User not found" });
if (!user) throw new HttpError({ statusCode: 404, message: "User not found" });

const filteredBookings = user?.bookings?.filter((booking) => booking.id === id);
const userIsHost = !!filteredBookings?.length;

const bookingsAsAttendee = prisma.booking.findMany({
where: {
id,
attendees: { some: { email: user.email } },
},
});

const userBookingIds = userWithBookingsAndTeamIds.bookings.map((booking) => booking.id);
const bookingsAsEventTypeOwner = prisma.booking.findMany({
where: {
id,
eventType: {
owner: { id: userId },
},
},
});

if (!userBookingIds.includes(id)) {
const teamBookings = await prisma.booking.findUnique({
where: {
id: id,
eventType: {
team: {
id: {
in: userWithBookingsAndTeamIds.teams.map((team) => team.teamId),
},
const bookingsAsTeamOwnerOrAdmin = prisma.booking.findMany({
where: {
id,
eventType: {
team: {
members: {
some: { userId, role: { in: ["ADMIN", "OWNER"] }, accepted: true },
},
},
},
});
},
});

if (!teamBookings) {
throw new HttpError({ statusCode: 403, message: "You are not authorized" });
}
}
const [resultOne, resultTwo, resultThree] = await Promise.all([
bookingsAsAttendee,
bookingsAsEventTypeOwner,
bookingsAsTeamOwnerOrAdmin,
]);

const teamBookingsAsOwnerOrAdmin = [...resultOne, ...resultTwo, ...resultThree];
const userHasTeamBookings = !!teamBookingsAsOwnerOrAdmin.length;

if (!userIsHost && !userHasTeamBookings)
throw new HttpError({ statusCode: 403, message: "You are not authorized" });
}

export default authMiddleware;
16 changes: 14 additions & 2 deletions apps/api/v1/pages/api/event-types/[id]/_delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import prisma from "@calcom/prisma";

import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";

import checkParentEventOwnership from "../_utils/checkParentEventOwnership";
import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission";

/**
* @swagger
* /event-types/{id}:
Expand Down Expand Up @@ -49,9 +52,18 @@ async function checkPermissions(req: NextApiRequest) {
const { userId, isSystemWideAdmin } = req;
const { id } = schemaQueryIdParseInt.parse(req.query);
if (isSystemWideAdmin) return;
/** Only event type owners can delete it */
const eventType = await prisma.eventType.findFirst({ where: { id, userId } });

const eventType = await prisma.eventType.findFirst({ where: { id } });

if (!eventType) throw new HttpError({ statusCode: 403, message: "Forbidden" });

/** Only event type owners or team owners for team events can delete it */
if (eventType.teamId) return await checkTeamEventEditPermission(req, { teamId: eventType.teamId });

if (eventType.parentId) return await checkParentEventOwnership(req);

if (eventType.userId && eventType.userId !== userId)
throw new HttpError({ statusCode: 403, message: "Forbidden" });
}

export default defaultResponder(deleteHandler);
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@ export default async function checkParentEventOwnership(req: NextApiRequest) {
/** These are already parsed upstream, we can assume they're good here. */
const parentId = Number(body.parentId);
const parentEventType = await prisma.eventType.findUnique({
where: {
id: parentId,
},
select: {
teamId: true,
},
where: { id: parentId },
select: { teamId: true },
});

if (!parentEventType) {
Expand All @@ -44,7 +40,8 @@ export default async function checkParentEventOwnership(req: NextApiRequest) {
where: {
teamId: parentEventType.teamId,
userId: userId,
OR: [{ role: "OWNER" }, { role: "ADMIN" }],
role: { in: ["ADMIN", "OWNER"] },
accepted: true,
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,17 @@ export default async function checkTeamEventEditPermission(
req: NextApiRequest,
body: Pick<z.infer<typeof schemaEventTypeCreateBodyParams>, "teamId" | "userId">
) {
const { isSystemWideAdmin } = req;
let userId = req.userId;
if (isSystemWideAdmin && body.userId) {
userId = body.userId;
}
if (body.teamId) {
const membership = await prisma.membership.findFirst({
where: {
userId,
userId: req.userId,
teamId: body.teamId,
accepted: true,
role: { in: ["ADMIN", "OWNER"] },
},
});

if (!membership?.role || !["ADMIN", "OWNER"].includes(membership.role)) {
if (!membership) {
throw new HttpError({
statusCode: 403,
message: "No permission to operate on event-type for this team",
Expand Down
2 changes: 1 addition & 1 deletion apps/api/v1/pages/api/teams/[teamId]/_auth-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export async function canUserAccessTeamWithRole(
/** If not ADMIN then we check if the actual user belongs to team and matches the required role */
if (!isSystemWideAdmin) args.where = { ...args.where, members: { some: { userId, role } } };
const team = await prisma.team.findFirst(args);
if (!team) throw new HttpError({ statusCode: 401, message: `Unauthorized: ${role.toString()} required` });
if (!team) throw new HttpError({ statusCode: 401, message: `Unauthorized: OWNER or ADMIN role required` });
return team;
}

Expand Down
Loading

0 comments on commit 0f6d3ab

Please sign in to comment.