Added 'hosts' to POST call, PATCH needs a db migration on web (#239)

Complete, but bit of a WIP due to _patch
This commit is contained in:
Alex van Andel authored and GitHub committed 2023-03-15 16:43:00 -07:00
1 parent 2b9af8457c
commit cb54ab670e
4 files changed
+93 -15

No files matched your search

+9 -3
View File
@@ -1,6 +1,6 @@
import { z } from "zod";
import { _EventTypeModel as EventType } from "@calcom/prisma/zod";
import { _EventTypeModel as EventType, _HostModel } from "@calcom/prisma/zod";
import { customInputSchema } from "@calcom/prisma/zod-utils";
import { Frequency } from "~/lib/types";
@@ -18,6 +18,11 @@ const recurringEventInputSchema = z.object({
tzid: timeZone.optional(),
});
const hostSchema = _HostModel.pick({
isFixed: true,
userId: true,
});
export const schemaEventTypeBaseBodyParams = EventType.pick({
title: true,
description: true,
@@ -25,11 +30,11 @@ export const schemaEventTypeBaseBodyParams = EventType.pick({
length: true,
hidden: true,
position: true,
teamId: true,
eventName: true,
timeZone: true,
periodType: true,
periodStartDate: true,
schedulingType: true,
periodEndDate: true,
periodDays: true,
periodCountCalendarDays: true,
@@ -39,13 +44,14 @@ export const schemaEventTypeBaseBodyParams = EventType.pick({
minimumBookingNotice: true,
beforeEventBuffer: true,
afterEventBuffer: true,
schedulingType: true,
teamId: true,
price: true,
currency: true,
slotInterval: true,
successRedirectUrl: true,
locations: true,
})
.merge(z.object({ hosts: z.array(hostSchema).optional().default([]) }))
.partial()
.strict();
+32 -4
View File
@@ -1,3 +1,5 @@
import type { Prisma } from "@prisma/client";
import { SchedulingType } from "@prisma/client";
import type { NextApiRequest } from "next";
import type { z } from "zod";
@@ -7,6 +9,7 @@ import { defaultResponder } from "@calcom/lib/server";
import type { schemaEventTypeBaseBodyParams } from "~/lib/validations/event-type";
import { schemaEventTypeEditBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
import ensureOnlyMembersAsHosts from "~/pages/api/event-types/_utils/ensureOnlyMembersAsHosts";
import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission";
@@ -49,6 +52,16 @@ import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission
* slug:
* type: string
* description: Unique slug for the event type
* hosts:
* type: array
* items:
* type: object
* properties:
* userId:
* type: number
* isFixed:
* type: boolean
* description: Host MUST be available for any slot to be bookable.
* hidden:
* type: boolean
* description: If the event type should be hidden from your public booking page
@@ -156,10 +169,25 @@ import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission
export async function patchHandler(req: NextApiRequest) {
const { prisma, query, body } = req;
const { id } = schemaQueryIdParseInt.parse(query);
const data = schemaEventTypeEditBodyParams.parse(body);
await checkPermissions(req, body);
const event_type = await prisma.eventType.update({ where: { id }, data });
return { event_type: schemaEventTypeReadPublic.parse(event_type) };
const { hosts = [], ...parsedBody } = schemaEventTypeEditBodyParams.parse(body);
const data: Prisma.EventTypeUpdateArgs["data"] = {
...parsedBody,
};
if (hosts) {
await ensureOnlyMembersAsHosts(req, parsedBody);
data.hosts = {
deleteMany: {},
create: hosts.map((host) => ({
...host,
isFixed: data.schedulingType === SchedulingType.COLLECTIVE || host.isFixed,
})),
};
}
await checkPermissions(req, parsedBody);
const eventType = await prisma.eventType.update({ where: { id }, data });
return { event_type: schemaEventTypeReadPublic.parse(eventType) };
}
async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schemaEventTypeBaseBodyParams>) {
+31 -8
View File
@@ -7,6 +7,7 @@ import { defaultResponder } from "@calcom/lib/server";
import { schemaEventTypeCreateBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
import checkTeamEventEditPermission from "./_utils/checkTeamEventEditPermission";
import ensureOnlyMembersAsHosts from "./_utils/ensureOnlyMembersAsHosts";
/**
* @swagger
@@ -46,6 +47,17 @@ import checkTeamEventEditPermission from "./_utils/checkTeamEventEditPermission"
* slug:
* type: string
* description: Unique slug for the event type
* example: my-event
* hosts:
* type: array
* items:
* type: object
* properties:
* userId:
* type: number
* isFixed:
* type: boolean
* description: Host MUST be available for any slot to be bookable.
* hidden:
* type: boolean
* description: If the event type should be hidden from your public booking page
@@ -176,22 +188,33 @@ import checkTeamEventEditPermission from "./_utils/checkTeamEventEditPermission"
* description: Authorization information is missing or invalid.
*/
async function postHandler(req: NextApiRequest) {
const { userId, isAdmin, prisma } = req;
const body = schemaEventTypeCreateBodyParams.parse(req.body);
let args: Prisma.EventTypeCreateArgs = {
data: { ...body, userId, users: { connect: { id: userId } } },
const { userId, isAdmin, prisma, body } = req;
const { hosts = [], ...parsedBody } = schemaEventTypeCreateBodyParams.parse(body || {});
let data: Prisma.EventTypeCreateArgs["data"] = {
...parsedBody,
userId,
users: { connect: { id: userId } },
};
await checkPermissions(req);
if (isAdmin && body.userId) args = { data: { ...body, users: { connect: { id: body.userId } } } };
if (isAdmin && parsedBody.userId) {
data = { ...parsedBody, users: { connect: { id: parsedBody.userId } } };
}
await checkTeamEventEditPermission(req, body);
await checkTeamEventEditPermission(req, parsedBody);
await ensureOnlyMembersAsHosts(req, parsedBody);
const data = await prisma.eventType.create(args);
if (hosts) {
data.hosts = { createMany: { data: hosts } };
}
const eventType = await prisma.eventType.create({ data });
return {
event_type: schemaEventTypeReadPublic.parse(data),
event_type: schemaEventTypeReadPublic.parse(eventType),
message: "Event type created successfully",
};
}
@@ -0,0 +1,21 @@
import type { NextApiRequest } from "next";
import type { z } from "zod";
import type { schemaEventTypeCreateBodyParams } from "~/lib/validations/event-type";
export default async function ensureOnlyMembersAsHosts(
req: NextApiRequest,
body: Pick<z.infer<typeof schemaEventTypeCreateBodyParams>, "hosts" | "teamId">
) {
if (body.teamId && body.hosts && body.hosts.length > 0) {
const teamMemberCount = await req.prisma.membership.count({
where: {
teamId: body.teamId,
userId: { in: body.hosts.map((host) => host.userId) },
},
});
if (teamMemberCount !== body.hosts.length) {
throw new Error("You can only add members of the team to a team event type.");
}
}
}