Compare commits

...

31 Commits

Author SHA1 Message Date
Hariom Balhara 7c091b3181 Merge remote-tracking branch 'origin/main' into fix/allow-self-event-editing 2022-05-19 13:26:08 +05:30
kodiakhq[bot] 17e9a739c2
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 19:43:30 +00:00
kodiakhq[bot] 88500a2b80
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 19:33:29 +00:00
kodiakhq[bot] 7eacc34ed9
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 17:13:05 +00:00
kodiakhq[bot] 030833c28c
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 17:06:13 +00:00
kodiakhq[bot] 5acf986770
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 16:54:50 +00:00
kodiakhq[bot] 03feb12488
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 16:25:05 +00:00
kodiakhq[bot] a62bd2eb47
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 16:05:52 +00:00
kodiakhq[bot] 5dbb2799b7
Merge branch 'main' into fix/allow-self-event-editing 2022-05-17 13:23:12 +00:00
Hariom Balhara a94b968303 Fix Ts errors and deletion failure message 2022-05-17 18:52:55 +05:30
Hariom Balhara 4b7016d3d3 Fix TS errors 2022-05-17 18:29:41 +05:30
Hariom Balhara b6faa9a57e Merge remote-tracking branch 'origin/main' into fix/allow-self-event-editing 2022-05-17 18:25:26 +05:30
kodiakhq[bot] fd007efefc
Merge branch 'main' into fix/allow-self-event-editing 2022-04-04 22:36:48 +00:00
kodiakhq[bot] fd4a5f783c
Merge branch 'main' into fix/allow-self-event-editing 2022-04-04 22:25:27 +00:00
kodiakhq[bot] 6413acc4f4
Merge branch 'main' into fix/allow-self-event-editing 2022-04-04 21:54:38 +00:00
zomars d6510516db Merge branch 'main' into pr/2066 2022-04-04 14:51:06 -06:00
zomars b1ed0aeb25 Merge branch 'main' into pr/2066 2022-04-04 14:46:12 -06:00
Hariom Balhara 492aa81905 Merge branch 'fix/allow-self-event-editing' of github.com:hariombalhara/cal.com into fix/allow-self-event-editing 2022-03-16 09:46:41 +05:30
Hariom Balhara 9c565d3ec9 Revert accidental changes 2022-03-16 09:45:02 +05:30
Hariom Balhara c825275d52 Merge remote-tracking branch 'origin/main' into fix/allow-self-event-editing 2022-03-16 09:37:28 +05:30
Bailey Pumfleet 30e65c4e0e
Merge branch 'main' into fix/allow-self-event-editing 2022-03-15 15:52:05 +00:00
Hariom Balhara 8d7a7c8b1f Debug failing test -Revert 2022-03-12 09:27:17 +05:30
Hariom Balhara 33be1a89ec Merge branch 'main' into fix/allow-self-event-editing 2022-03-12 09:21:25 +05:30
Hariom Balhara 77f3c0cb50 Debug failing test 2022-03-12 09:04:09 +05:30
Hariom Balhara 04293a25ca
Merge branch 'main' into fix/allow-self-event-editing 2022-03-11 20:03:52 +05:30
Hariom Balhara 9464e4cbe5
Merge branch 'main' into fix/allow-self-event-editing 2022-03-11 13:01:59 +05:30
Hariom Balhara a229dea41c Remove unnecessary autogenerated queries 2022-03-10 09:19:59 +05:30
Hariom Balhara f10f3c05ae Merge remote-tracking branch 'origin/main' into fix/allow-self-event-editing 2022-03-10 09:18:39 +05:30
Hariom Balhara 37aa750f04 Add comments 2022-03-05 13:43:45 +05:30
Hariom Balhara 13f682961b Deduplicate editing check 2022-03-05 13:29:35 +05:30
Hariom Balhara 5115965239 Allow Team Event editing by the person who created it 2022-03-05 12:08:22 +05:30
5 changed files with 71 additions and 26 deletions

View File

@ -1,3 +1,4 @@
import { EventType, Membership, MembershipRole, User } from "@prisma/client";
import { TFunction } from "next-i18next";
type EventNameObjectType = {
@ -17,3 +18,40 @@ export function getEventName(eventNameObj: EventNameObjectType) {
attendeeName: eventNameObj.attendeeName,
});
}
export function canEventBeEdited({
user,
eventType,
}: {
user: {
id: User["id"];
};
eventType: {
users: {
id: User["id"];
}[];
userId: User["id"] | null;
team: {
members: {
userId: Membership["userId"];
role: MembershipRole;
}[];
} | null;
};
}) {
// I am the creator of the event.
if (eventType.userId === user.id) {
return true;
}
// Check if he is the owner of the team to which event belongs
if (eventType.team) {
return eventType.team.members
.filter((member) => {
return member.role === MembershipRole.OWNER || member.role === MembershipRole.ADMIN;
})
.map((member) => member.userId)
.includes(user.id);
}
return eventType.users.find((user) => user.id === user.id);
}

View File

@ -63,7 +63,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
};
await sendPasswordResetEmail(passwordEmail);
/** So we can test the password reset flow on CI */
if (process.env.NEXT_PUBLIC_IS_E2E) {
return res.status(201).json({ message: "Reset Requested", resetLink });

View File

@ -59,13 +59,13 @@ interface EventTypeListHeadingProps {
type EventTypeGroup = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"][number];
type EventType = EventTypeGroup["eventTypes"][number];
interface EventTypeListProps {
group: EventTypeGroup;
groupIndex: number;
readOnly: boolean;
group: EventTypeGroup;
types: EventType[];
profile: { slug: string | null };
}
const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGroup; readOnly: boolean }) => {
const Item = ({ type, group }: { type: EventType; group: EventTypeGroup }) => {
const { t } = useLocale();
return (
@ -90,7 +90,7 @@ const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGrou
{t("hidden")}
</span>
)}
{readOnly && (
{type.readOnly && (
<span className="rtl:mr-2inline items-center rounded-sm bg-gray-100 px-1.5 py-0.5 text-xs font-medium text-gray-800 ltr:ml-2">
{t("readonly")}
</span>
@ -104,7 +104,7 @@ const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGrou
const MemoizedItem = React.memo(Item);
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
export const EventTypeList = ({ group, groupIndex, types, profile }: EventTypeListProps): JSX.Element => {
const { t } = useLocale();
const router = useRouter();
@ -184,10 +184,17 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
showToast(t("event_type_deleted_successfully"), "success");
},
onError: (err) => {
let message: string;
if (err instanceof HttpError) {
const message = `${err.statusCode}: ${err.message}`;
showToast(message, "error");
message = `${err.statusCode}: ${err.message}`;
}
if (err.data?.code === "UNAUTHORIZED") {
message = `${err.data.code}: You are not able to delete this event`;
} else {
message = "Some Error Occurred";
}
showToast(message, "error");
},
});
@ -232,7 +239,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
</button>
</>
)}
<MemoizedItem type={type} group={group} readOnly={readOnly} />
<MemoizedItem type={type} group={group} />
<div className="mt-4 hidden flex-shrink-0 sm:mt-0 sm:ml-5 sm:flex">
<div className="flex justify-between space-x-2 rtl:space-x-reverse">
{type.users?.length > 1 && (
@ -590,10 +597,10 @@ const EventTypesPage = () => {
/>
)}
<EventTypeList
profile={group.profile}
types={group.eventTypes}
group={group}
groupIndex={index}
readOnly={group.metadata.readOnly}
/>
</Fragment>
))}

View File

@ -10,6 +10,7 @@ import { bookingMinimalSelect } from "@calcom/prisma";
import { RecurringEvent } from "@calcom/types/Calendar";
import { checkRegularUsername } from "@lib/core/checkRegularUsername";
import { canEventBeEdited } from "@lib/event";
import jackson from "@lib/jackson";
import {
isSAMLLoginEnabled,
@ -135,6 +136,7 @@ const loggedInViewerRouter = createProtectedRouter()
price: true,
currency: true,
position: true,
userId: true,
successRedirectUrl: true,
hashedLink: true,
users: {
@ -144,6 +146,11 @@ const loggedInViewerRouter = createProtectedRouter()
name: true,
},
},
team: {
select: {
members: true,
},
},
});
const user = await prisma.user.findUnique({
@ -206,7 +213,6 @@ const loggedInViewerRouter = createProtectedRouter()
},
},
});
if (!user) {
throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
}
@ -235,9 +241,8 @@ const loggedInViewerRouter = createProtectedRouter()
};
metadata: {
membershipCount: number;
readOnly: boolean;
};
eventTypes: (typeof user.eventTypes[number] & { $disabled?: boolean })[];
eventTypes: (typeof user.eventTypes[number] & { $disabled?: boolean; readOnly?: boolean })[];
};
let eventTypeGroups: EventTypeGroup[] = [];
@ -260,12 +265,10 @@ const loggedInViewerRouter = createProtectedRouter()
eventTypes: _.orderBy(mergedEventTypes, ["position", "id"], ["desc", "asc"]),
metadata: {
membershipCount: 1,
readOnly: false,
},
});
eventTypeGroups = ([] as EventTypeGroup[]).concat(
eventTypeGroups,
eventTypeGroups = eventTypeGroups.concat(
user.teams.map((membership) => ({
teamId: membership.team.id,
profile: {
@ -275,9 +278,11 @@ const loggedInViewerRouter = createProtectedRouter()
},
metadata: {
membershipCount: membership.team.members.length,
readOnly: membership.role === MembershipRole.MEMBER,
},
eventTypes: membership.team.eventTypes,
eventTypes: membership.team.eventTypes.map((eventType) => ({
...eventType,
readOnly: !canEventBeEdited({ user, eventType }),
})),
}))
);

View File

@ -7,6 +7,8 @@ import { _DestinationCalendarModel, _EventTypeCustomInputModel, _EventTypeModel
import { stringOrNumber } from "@calcom/prisma/zod-utils";
import { createEventTypeInput } from "@calcom/prisma/zod/custom/eventtype";
import { canEventBeEdited } from "@lib/event";
import { createProtectedRouter } from "@server/createRouter";
import { viewerRouter } from "@server/routers/viewer";
import { TRPCError } from "@trpc/server";
@ -115,7 +117,7 @@ export const eventTypesRouter = createProtectedRouter()
const data: Prisma.EventTypeCreateInput = {
...rest,
userId: teamId ? undefined : userId,
userId: userId,
users: {
connect: {
id: userId,
@ -187,13 +189,7 @@ export const eventTypesRouter = createProtectedRouter()
}
const isAuthorized = (function () {
if (event.team) {
return event.team.members
.filter((member) => member.role === MembershipRole.OWNER || member.role === MembershipRole.ADMIN)
.map((member) => member.userId)
.includes(ctx.user.id);
}
return event.userId === ctx.user.id || event.users.find((user) => user.id === ctx.user.id);
return canEventBeEdited({ user: ctx.user, eventType: event });
})();
if (!isAuthorized) {