perf: routing forms loading time (#17518)

* perf: routing forms loading time

* chore: add TODO

* chore

* chore: add type

* chore: use Promise.all

* fix: type err

* fix: fetch id

* refactor: don't fetch team

* chore: add name
This commit is contained in:
Udit Takkar
2024-11-12 17:32:42 +05:30
committed by GitHub
parent dc400d80d0
commit 4e0e3a47f5
6 changed files with 38 additions and 36 deletions
@@ -87,20 +87,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
id: formId,
...entityPrismaWhereClause({ userId: user.id }),
},
include: {
team: {
select: {
members: true,
},
},
},
});
if (!form) {
return res.status(404).json({ message: "Form not found or unauthorized" });
}
if (!canEditEntity(form, user.id)) {
if (!(await canEditEntity(form, user.id))) {
return res.status(404).json({ message: "Form not found or unauthorized" });
}
@@ -22,11 +22,6 @@ export async function isFormCreateEditAllowed({
select: {
userId: true,
teamId: true,
team: {
select: {
members: true,
},
},
},
});
@@ -37,5 +32,5 @@ export async function isFormCreateEditAllowed({
});
}
return canEditEntity(form, userId);
return await canEditEntity(form, userId);
}
@@ -367,7 +367,7 @@ export const formMutationHandler = async ({ ctx, input }: FormMutationHandlerOpt
});
}
if (!canEditEntity(sourceForm, userId)) {
if (!(await canEditEntity(sourceForm, userId))) {
throw new TRPCError({
code: "NOT_FOUND",
message: `Form to duplicate: ${duplicateFrom} not found or you are unauthorized`,
@@ -36,8 +36,9 @@ export const formsHandler = async ({ ctx, input }: FormsHandlerOptions) => {
],
include: {
team: {
include: {
members: true,
select: {
id: true,
name: true,
},
},
_count: {
@@ -54,15 +55,19 @@ export const formsHandler = async ({ ctx, input }: FormsHandlerOptions) => {
}),
});
const serializableForms = [];
for (let i = 0; i < forms.length; i++) {
const form = forms[i];
const hasWriteAccess = canEditEntity(form, user.id);
serializableForms.push({
form: await getSerializableForm({ form: forms[i] }),
readOnly: !hasWriteAccess,
});
}
const serializableForms = await Promise.all(
forms.map(async (form) => {
const [hasWriteAccess, serializedForm] = await Promise.all([
canEditEntity(form, user.id),
getSerializableForm({ form }),
]);
return {
form: serializedForm,
readOnly: !hasWriteAccess,
};
})
);
return {
filtered: serializableForms,
@@ -49,6 +49,7 @@ async function getResponseWithFormFieldsHandler({ ctx, input }: GetResponseWithF
},
team: {
select: {
id: true,
members: true,
slug: true,
parent: {
@@ -74,7 +75,7 @@ async function getResponseWithFormFieldsHandler({ ctx, input }: GetResponseWithF
// TODO: To make the check stricter, we could check if the user is admin/owner of the team or a member that is the organizer.
// But the exact criteria of showing a booking to the user could be trickier. Maybe we allow hosts as well to access the booking and thus should allow them as well to reroute
if (!canAccessEntity(form, user.id)) {
if (!(await canAccessEntity(form, user.id))) {
throw new TRPCError({
code: "FORBIDDEN",
message: translate("you_dont_have_access_to_reroute_this_booking"),
+17 -9
View File
@@ -1,4 +1,3 @@
import type { Membership } from "@calcom/prisma/client";
import { MembershipRole } from "@calcom/prisma/enums";
export const enum ENTITY_PERMISSION_LEVEL {
@@ -11,22 +10,22 @@ export const enum ENTITY_PERMISSION_LEVEL {
TEAM_WRITE,
}
export function canEditEntity(
export async function canEditEntity(
entity: Parameters<typeof getEntityPermissionLevel>[0],
userId: Parameters<typeof getEntityPermissionLevel>[1]
) {
const permissionLevel = getEntityPermissionLevel(entity, userId);
const permissionLevel = await getEntityPermissionLevel(entity, userId);
return (
permissionLevel === ENTITY_PERMISSION_LEVEL.TEAM_WRITE ||
permissionLevel === ENTITY_PERMISSION_LEVEL.USER_ONLY_WRITE
);
}
export function canAccessEntity(
export async function canAccessEntity(
entity: Parameters<typeof getEntityPermissionLevel>[0],
userId: Parameters<typeof getEntityPermissionLevel>[1]
) {
const permissionLevel = getEntityPermissionLevel(entity, userId);
const permissionLevel = await getEntityPermissionLevel(entity, userId);
return (
permissionLevel === ENTITY_PERMISSION_LEVEL.TEAM_WRITE ||
permissionLevel === ENTITY_PERMISSION_LEVEL.USER_ONLY_WRITE ||
@@ -34,15 +33,24 @@ export function canAccessEntity(
);
}
export function getEntityPermissionLevel(
export async function getEntityPermissionLevel(
entity: {
userId: number | null;
team: { members: Membership[] } | null;
teamId: number | null;
},
userId: number
) {
if (entity.team) {
const roleForTeamMember = entity.team.members.find((member) => member.userId === userId)?.role;
if (entity.teamId) {
const { prisma } = await import("@calcom/prisma");
const membership = await prisma.membership.findFirst({
where: {
teamId: entity.teamId,
userId,
accepted: true,
},
});
const roleForTeamMember = membership?.role;
if (roleForTeamMember) {
//TODO: Remove type assertion
const hasWriteAccessToTeam = (