Allow non-admin team members also to reroute (#17234)
This commit is contained in:
@@ -696,13 +696,13 @@ const RerouteDialogContentAndFooter = ({
|
||||
}: Pick<RerouteDialogProps, "isOpenDialog" | "setIsOpenDialog"> & {
|
||||
booking: TeamEventTypeBookingToReroute;
|
||||
}) => {
|
||||
const { data: responseWithForm, isPending: isRoutingFormLoading } =
|
||||
const { data: responseWithForm, isPending: isRoutingFormLoading, error: formResponseFetchError } =
|
||||
trpc.viewer.appRoutingForms.getResponseWithFormFields.useQuery({
|
||||
formResponseId: booking.routedFromRoutingFormReponse.id,
|
||||
});
|
||||
|
||||
const { t } = useLocale();
|
||||
// useUpdateIsReroutingQueryParam({ isOpenDialog });
|
||||
|
||||
if (isRoutingFormLoading)
|
||||
return (
|
||||
<>
|
||||
@@ -718,7 +718,11 @@ const RerouteDialogContentAndFooter = ({
|
||||
</>
|
||||
);
|
||||
|
||||
if (!responseWithForm) return <div>{t("something_went_wrong")}</div>;
|
||||
if (formResponseFetchError) {
|
||||
return <div className="mb-8">{formResponseFetchError.message}</div>;
|
||||
}
|
||||
|
||||
if (!responseWithForm) return <div className="mb-8">{t("something_went_wrong")}</div>;
|
||||
|
||||
return (
|
||||
<RerouteDialogContentAndFooterWithFormResponse
|
||||
|
||||
@@ -2685,5 +2685,7 @@
|
||||
"reschedule_with_different_timeslot": "Reschedule with different timeslot",
|
||||
"we_dont_have_id_for_the_new_event": "We don't have ID for the new event. Please go to the Routing Form and save it again.",
|
||||
"rerouted_booking_successfully_redirecting_to_booking_page": "Rerouted booking successfully. Redirecting to booking page",
|
||||
"you_dont_have_access_to_reroute_this_booking": "You don't have access to reroute this booking",
|
||||
"form_response_not_found": "Form response not found",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { z } from "zod";
|
||||
|
||||
import { canAccessEntity } from "@calcom/lib/entityPermissionUtils";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
|
||||
|
||||
@@ -9,7 +11,6 @@ import { enrichFormWithMigrationData } from "../enrichFormWithMigrationData";
|
||||
import { getSerializableForm } from "../lib/getSerializableForm";
|
||||
import type { FormResponse } from "../types/types";
|
||||
import type { ZFormByResponseIdInputSchema } from "./_router";
|
||||
import { canEditEntity } from "@calcom/lib/entityPermissionUtils";
|
||||
|
||||
type GetResponseWithFormFieldsOptions = {
|
||||
ctx: {
|
||||
@@ -21,8 +22,8 @@ type GetResponseWithFormFieldsOptions = {
|
||||
async function getResponseWithFormFieldsHandler({ ctx, input }: GetResponseWithFormFieldsOptions) {
|
||||
const { user } = ctx;
|
||||
const { formResponseId } = input;
|
||||
const translate = await getTranslation(user.locale ?? "en", "common");
|
||||
|
||||
|
||||
const formResponse = await prisma.app_RoutingForms_FormResponse.findUnique({
|
||||
where: {
|
||||
id: formResponseId,
|
||||
@@ -63,18 +64,20 @@ async function getResponseWithFormFieldsHandler({ ctx, input }: GetResponseWithF
|
||||
});
|
||||
|
||||
if (!formResponse) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Form response not found",
|
||||
});
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: translate("form_response_not_found"),
|
||||
});
|
||||
}
|
||||
|
||||
const form = formResponse.form;
|
||||
|
||||
if (!canEditEntity(form, user.id)) {
|
||||
// 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)) {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "You don't have access to this form",
|
||||
message: translate("you_dont_have_access_to_reroute_this_booking"),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@ import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
export const enum ENTITY_PERMISSION_LEVEL {
|
||||
NONE,
|
||||
// It is owned by user and user has write access to it
|
||||
USER_ONLY_WRITE,
|
||||
// All members of the team has access to it and user has read access to it
|
||||
TEAM_READ_ONLY,
|
||||
// All members of the team has access to it and user has write access to it
|
||||
TEAM_WRITE,
|
||||
}
|
||||
|
||||
@@ -19,6 +22,18 @@ export function canEditEntity(
|
||||
);
|
||||
}
|
||||
|
||||
export function canAccessEntity(
|
||||
entity: Parameters<typeof getEntityPermissionLevel>[0],
|
||||
userId: Parameters<typeof getEntityPermissionLevel>[1]
|
||||
) {
|
||||
const permissionLevel = getEntityPermissionLevel(entity, userId);
|
||||
return (
|
||||
permissionLevel === ENTITY_PERMISSION_LEVEL.TEAM_WRITE ||
|
||||
permissionLevel === ENTITY_PERMISSION_LEVEL.USER_ONLY_WRITE ||
|
||||
permissionLevel === ENTITY_PERMISSION_LEVEL.TEAM_READ_ONLY
|
||||
);
|
||||
}
|
||||
|
||||
export function getEntityPermissionLevel(
|
||||
entity: {
|
||||
userId: number | null;
|
||||
|
||||
Reference in New Issue
Block a user