fix: org admin/owner can access routng form (#25412)

This commit is contained in:
Anik Dhabal Babu
2025-12-01 09:46:50 +00:00
committed by GitHub
parent 0776657faf
commit 38890dad30
2 changed files with 84 additions and 55 deletions
@@ -1,9 +1,6 @@
import { enrichFormWithMigrationData } from "@calcom/app-store/routing-forms/enrichFormWithMigrationData";
import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm";
import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository";
import { Resource } from "@calcom/features/pbac/domain/types/permission-registry";
import { getResourcePermissions } from "@calcom/features/pbac/lib/resource-permissions";
import { MembershipRole } from "@calcom/prisma/enums";
import { getRoutingFormPermissions } from "@calcom/features/pbac/lib/resource-permissions";
import type { AppGetServerSidePropsContext, AppPrisma, AppUser } from "@calcom/types/AppGetServerSideProps";
export const getServerSidePropsForSingleFormView = async function getServerSidePropsForSingleFormView(
@@ -78,7 +75,7 @@ export const getServerSidePropsForSingleFormView = async function getServerSideP
};
}
const { user: u, ...formWithoutUser } = form;
const { user: _u, ...formWithoutUser } = form;
const formWithoutProfileInfo = {
...formWithoutUser,
@@ -98,55 +95,17 @@ export const getServerSidePropsForSingleFormView = async function getServerSideP
user: await userRepo.enrichUserWithItsProfile({ user: form.user }),
};
// Get PBAC permissions for team-scoped routing forms
let permissions = {
canCreate: false,
canRead: false,
canEdit: false,
canDelete: false,
};
const permissions = await getRoutingFormPermissions({
userId: user.id,
formUserId: form.userId,
formTeamId: form.teamId,
formTeamParentId: form.team?.parentId ?? null,
});
if (!form.teamId) {
// For personal forms (teamId = null),
// check if the form belongs to the current user
if (form.userId !== user.id) {
return {
notFound: true,
};
}
permissions = {
canCreate: true,
canRead: true,
canEdit: true,
canDelete: true,
if (!permissions) {
return {
notFound: true,
};
} else {
// team-scoped routing form
// Get user's role in the team
const membership = await MembershipRepository.findUniqueByUserIdAndTeamId({
userId: user.id,
teamId: form.teamId,
});
if (!membership) {
return {
notFound: true,
};
}
permissions = await getResourcePermissions({
userId: user.id,
teamId: form.teamId,
resource: Resource.RoutingForm,
userRole: membership.role,
fallbackRoles: {
read: { roles: [MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER] },
create: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
update: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
delete: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
},
});
}
return {
@@ -1,10 +1,11 @@
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository";
import { prisma } from "@calcom/prisma";
import type { MembershipRole } from "@calcom/prisma/enums";
import { MembershipRole } from "@calcom/prisma/enums";
import { PermissionMapper } from "../domain/mappers/PermissionMapper";
import type { Resource, CustomAction } from "../domain/types/permission-registry";
import { CrudAction } from "../domain/types/permission-registry";
import type { CustomAction } from "../domain/types/permission-registry";
import { CrudAction, Resource } from "../domain/types/permission-registry";
import { PermissionCheckService } from "../services/permission-check.service";
interface RoleMapping {
@@ -140,3 +141,72 @@ export const getSpecificPermissions = async ({
return permissions;
};
export async function getRoutingFormPermissions({
userId,
formUserId,
formTeamId,
formTeamParentId,
}: {
userId: number;
formUserId: number;
formTeamId: number | null;
formTeamParentId: number | null;
}): Promise<ResourcePermissions | null> {
if (!formTeamId) {
if (formUserId !== userId) {
return null;
}
return {
canCreate: true,
canRead: true,
canEdit: true,
canDelete: true,
};
}
const membership = await MembershipRepository.findUniqueByUserIdAndTeamId({
userId,
teamId: formTeamId,
});
let isParentOrgAdmin = false;
if (!membership && formTeamParentId) {
const parentOrgMembership = await MembershipRepository.getAdminOrOwnerMembership(
userId,
formTeamParentId
);
isParentOrgAdmin = !!parentOrgMembership;
}
if (!membership && !isParentOrgAdmin) {
return null;
}
if (!membership && isParentOrgAdmin) {
return {
canCreate: true,
canRead: true,
canEdit: true,
canDelete: true,
};
}
if (membership) {
return await getResourcePermissions({
userId,
teamId: formTeamId,
resource: Resource.RoutingForm,
userRole: membership.role,
fallbackRoles: {
read: { roles: [MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER] },
create: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
update: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
delete: { roles: [MembershipRole.ADMIN, MembershipRole.OWNER] },
},
});
}
return null;
}