chore: Refactors Destination calendar API endpoint with a bunch of fixes (#11789)
Co-authored-by: Omar López <zomars@me.com>pull/11847/head
parent
208d040f6f
commit
a87d82fd47
|
@ -0,0 +1,14 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||
|
||||
export function extractUserIdsFromQuery({ isAdmin, query }: NextApiRequest) {
|
||||
/** Guard: Only admins can query other users */
|
||||
if (!isAdmin) {
|
||||
throw new HttpError({ statusCode: 401, message: "ADMIN required" });
|
||||
}
|
||||
const { userId: userIdOrUserIds } = schemaQuerySingleOrMultipleUserIds.parse(query);
|
||||
return Array.isArray(userIdOrUserIds) ? userIdOrUserIds : [userIdOrUserIds];
|
||||
}
|
|
@ -14,9 +14,9 @@ const schemaDestinationCalendarCreateParams = z
|
|||
.object({
|
||||
integration: z.string(),
|
||||
externalId: z.string(),
|
||||
eventTypeId: z.number(),
|
||||
bookingId: z.number(),
|
||||
userId: z.number(),
|
||||
eventTypeId: z.number().optional(),
|
||||
bookingId: z.number().optional(),
|
||||
userId: z.number().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import type { DestinationCalendarResponse } from "~/lib/types";
|
||||
import {
|
||||
schemaDestinationCalendarEditBodyParams,
|
||||
schemaDestinationCalendarReadPublic,
|
||||
} from "~/lib/validations/destination-calendar";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function destionationCalendarById(
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DestinationCalendarResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = schemaDestinationCalendarEditBodyParams.safeParse(body);
|
||||
if (!safeQuery.success) {
|
||||
res.status(400).json({ message: "Your query was invalid" });
|
||||
return;
|
||||
}
|
||||
const data = await prisma.destinationCalendar.findMany({ where: { userId } });
|
||||
const userDestinationCalendars = data.map((destinationCalendar) => destinationCalendar.id);
|
||||
// FIXME: Should we also check ownership of bokingId and eventTypeId to avoid users cross-pollinating other users calendars.
|
||||
// On a related note, moving from sequential integer IDs to UUIDs would be a good idea. and maybe help avoid having this problem.
|
||||
if (userDestinationCalendars.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
|
||||
else {
|
||||
switch (method) {
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* get:
|
||||
* summary: Find a destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to get
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: DestinationCalendar was not found
|
||||
* patch:
|
||||
* summary: Edit an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to edit
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* requestBody:
|
||||
* description: Create a new booking related to one of your event-types
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* integration:
|
||||
* type: string
|
||||
* description: 'The integration'
|
||||
* externalId:
|
||||
* type: string
|
||||
* description: 'The external ID of the integration'
|
||||
* eventTypeId:
|
||||
* type: integer
|
||||
* description: 'The ID of the eventType it is associated with'
|
||||
* bookingId:
|
||||
* type: integer
|
||||
* description: 'The booking ID it is associated with'
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destinationCalendar edited successfuly
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* delete:
|
||||
* summary: Remove an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to delete
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destinationCalendar removed successfuly
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar id is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
case "GET":
|
||||
await prisma.destinationCalendar
|
||||
.findUnique({ where: { id: safeQuery.data.id } })
|
||||
.then((data) => schemaDestinationCalendarReadPublic.parse(data))
|
||||
.then((destination_calendar) => res.status(200).json({ destination_calendar }))
|
||||
.catch((error: Error) =>
|
||||
res.status(404).json({
|
||||
message: `DestinationCalendar with id: ${safeQuery.data.id} not found`,
|
||||
error,
|
||||
})
|
||||
);
|
||||
break;
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* patch:
|
||||
* summary: Edit an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to edit
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destinationCalendar edited successfuly
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
case "PATCH":
|
||||
if (!safeBody.success) {
|
||||
{
|
||||
res.status(400).json({ message: "Invalid request body" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
await prisma.destinationCalendar
|
||||
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })
|
||||
.then((data) => schemaDestinationCalendarReadPublic.parse(data))
|
||||
.then((destination_calendar) => res.status(200).json({ destination_calendar }))
|
||||
.catch((error: Error) =>
|
||||
res.status(404).json({
|
||||
message: `DestinationCalendar with id: ${safeQuery.data.id} not found`,
|
||||
error,
|
||||
})
|
||||
);
|
||||
break;
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* delete:
|
||||
* summary: Remove an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to delete
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destinationCalendar removed successfuly
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar id is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
case "DELETE":
|
||||
await prisma.destinationCalendar
|
||||
.delete({
|
||||
where: { id: safeQuery.data.id },
|
||||
})
|
||||
.then(() =>
|
||||
res.status(200).json({
|
||||
message: `DestinationCalendar with id: ${safeQuery.data.id} deleted`,
|
||||
})
|
||||
)
|
||||
.catch((error: Error) =>
|
||||
res.status(404).json({
|
||||
message: `DestinationCalendar with id: ${safeQuery.data.id} not found`,
|
||||
error,
|
||||
})
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
res.status(405).json({ message: "Method not allowed" });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default withMiddleware("HTTP_GET_DELETE_PATCH")(
|
||||
withValidQueryIdTransformParseInt(destionationCalendarById)
|
||||
);
|
|
@ -0,0 +1,32 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
if (isAdmin) return;
|
||||
const userEventTypes = await prisma.eventType.findMany({
|
||||
where: { userId },
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
const userEventTypeIds = userEventTypes.map((eventType) => eventType.id);
|
||||
|
||||
const destinationCalendar = await prisma.destinationCalendar.findFirst({
|
||||
where: {
|
||||
AND: [
|
||||
{ id },
|
||||
{
|
||||
OR: [{ userId }, { eventTypeId: { in: userEventTypeIds } }],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
if (!destinationCalendar)
|
||||
throw new HttpError({ statusCode: 404, message: "Destination calendar not found" });
|
||||
}
|
||||
|
||||
export default authMiddleware;
|
|
@ -0,0 +1,42 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* delete:
|
||||
* summary: Remove an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to delete
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK, destinationCalendar removed successfully
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: Destination calendar not found
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.destinationCalendar.delete({ where: { id } });
|
||||
return { message: `OK, Destination Calendar removed successfully` };
|
||||
}
|
||||
|
||||
export default defaultResponder(deleteHandler);
|
|
@ -0,0 +1,47 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaDestinationCalendarReadPublic } from "~/lib/validations/destination-calendar";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* get:
|
||||
* summary: Find a destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to get
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: Destination calendar not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
|
||||
const destinationCalendar = await prisma.destinationCalendar.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
return { destinationCalendar: schemaDestinationCalendarReadPublic.parse({ ...destinationCalendar }) };
|
||||
}
|
||||
|
||||
export default defaultResponder(getHandler);
|
|
@ -0,0 +1,71 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import {
|
||||
schemaDestinationCalendarEditBodyParams,
|
||||
schemaDestinationCalendarReadPublic,
|
||||
} from "~/lib/validations/destination-calendar";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars/{id}:
|
||||
* patch:
|
||||
* summary: Edit an existing destination calendar
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* schema:
|
||||
* type: integer
|
||||
* required: true
|
||||
* description: ID of the destination calendar to edit
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* requestBody:
|
||||
* description: Create a new booking related to one of your event-types
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* integration:
|
||||
* type: string
|
||||
* description: 'The integration'
|
||||
* externalId:
|
||||
* type: string
|
||||
* description: 'The external ID of the integration'
|
||||
* eventTypeId:
|
||||
* type: integer
|
||||
* description: 'The ID of the eventType it is associated with'
|
||||
* bookingId:
|
||||
* type: integer
|
||||
* description: 'The booking ID it is associated with'
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: Destination calendar not found
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const parsedBody = schemaDestinationCalendarEditBodyParams.parse(body);
|
||||
|
||||
const destinationCalendar = await prisma.destinationCalendar.update({
|
||||
where: { id },
|
||||
data: parsedBody,
|
||||
});
|
||||
return { destinationCalendar: schemaDestinationCalendarReadPublic.parse(destinationCalendar) };
|
||||
}
|
||||
|
||||
export default defaultResponder(patchHandler);
|
|
@ -0,0 +1,18 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { defaultHandler, defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
|
||||
import authMiddleware from "./_auth-middleware";
|
||||
|
||||
export default withMiddleware()(
|
||||
defaultResponder(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
await authMiddleware(req);
|
||||
return defaultHandler({
|
||||
GET: import("./_get"),
|
||||
PATCH: import("./_patch"),
|
||||
DELETE: import("./_delete"),
|
||||
})(req, res);
|
||||
})
|
||||
);
|
|
@ -0,0 +1,58 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { extractUserIdsFromQuery } from "~/lib/utils/extractUserIdsFromQuery";
|
||||
import { schemaDestinationCalendarReadPublic } from "~/lib/validations/destination-calendar";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars:
|
||||
* get:
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* summary: Find all destination calendars
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: No destination calendars were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, prisma } = req;
|
||||
const userIds = req.query.userId ? extractUserIdsFromQuery(req) : [userId];
|
||||
|
||||
const userEventTypes = await prisma.eventType.findMany({
|
||||
where: { userId: { in: userIds } },
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
const userEventTypeIds = userEventTypes.map((eventType) => eventType.id);
|
||||
|
||||
const allDestinationCalendars = await prisma.destinationCalendar.findMany({
|
||||
where: {
|
||||
OR: [{ userId: { in: userIds } }, { eventTypeId: { in: userEventTypeIds } }],
|
||||
},
|
||||
});
|
||||
|
||||
if (allDestinationCalendars.length === 0)
|
||||
new HttpError({ statusCode: 404, message: "No destination calendars were found" });
|
||||
|
||||
return {
|
||||
destinationCalendars: allDestinationCalendars.map((destinationCalendar) =>
|
||||
schemaDestinationCalendarReadPublic.parse(destinationCalendar)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export default defaultResponder(getHandler);
|
|
@ -0,0 +1,99 @@
|
|||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import {
|
||||
schemaDestinationCalendarReadPublic,
|
||||
schemaDestinationCalendarCreateBodyParams,
|
||||
} from "~/lib/validations/destination-calendar";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars:
|
||||
* post:
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* summary: Creates a new destination calendar
|
||||
* requestBody:
|
||||
* description: Create a new destination calendar for your events
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - integration
|
||||
* - externalId
|
||||
* properties:
|
||||
* integration:
|
||||
* type: string
|
||||
* description: 'The integration'
|
||||
* externalId:
|
||||
* type: string
|
||||
* description: 'The external ID of the integration'
|
||||
* eventTypeId:
|
||||
* type: integer
|
||||
* description: 'The ID of the eventType it is associated with'
|
||||
* bookingId:
|
||||
* type: integer
|
||||
* description: 'The booking ID it is associated with'
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destination calendar created
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma, body } = req;
|
||||
|
||||
const parsedBody = schemaDestinationCalendarCreateBodyParams.parse(body);
|
||||
|
||||
await checkPermissions(req, userId);
|
||||
|
||||
if (!parsedBody.eventTypeId) {
|
||||
parsedBody.userId = userId;
|
||||
}
|
||||
|
||||
if (isAdmin) {
|
||||
parsedBody.userId = parsedBody.userId || userId;
|
||||
}
|
||||
|
||||
const destination_calendar = await prisma.destinationCalendar.create({ data: { ...parsedBody } });
|
||||
|
||||
return {
|
||||
destinationCalendar: schemaDestinationCalendarReadPublic.parse(destination_calendar),
|
||||
message: "Destination calendar created successfully",
|
||||
};
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest, userId: number) {
|
||||
const { isAdmin } = req;
|
||||
const body = schemaDestinationCalendarCreateBodyParams.parse(req.body);
|
||||
|
||||
/* Non-admin users can only create destination calendars for themselves */
|
||||
if (!isAdmin && body.userId)
|
||||
throw new HttpError({
|
||||
statusCode: 401,
|
||||
message: "ADMIN required for `userId`",
|
||||
});
|
||||
/* Admin users are required to pass in a userId */
|
||||
if (isAdmin && !body.userId) throw new HttpError({ statusCode: 400, message: "`userId` required" });
|
||||
/* User should only be able to create for their own destination calendars*/
|
||||
if (!isAdmin && body.eventTypeId) {
|
||||
const ownsEventType = await req.prisma.eventType.findFirst({ where: { id: body.eventTypeId, userId } });
|
||||
if (!ownsEventType) throw new HttpError({ statusCode: 401, message: "Unauthorized" });
|
||||
}
|
||||
// TODO:: Add support for team event types with validation
|
||||
}
|
||||
|
||||
export default defaultResponder(postHandler);
|
|
@ -1,114 +1,10 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { defaultHandler } from "@calcom/lib/server";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import type { DestinationCalendarResponse, DestinationCalendarsResponse } from "~/lib/types";
|
||||
import {
|
||||
schemaDestinationCalendarCreateBodyParams,
|
||||
schemaDestinationCalendarReadPublic,
|
||||
} from "~/lib/validations/destination-calendar";
|
||||
|
||||
async function createOrlistAllDestinationCalendars(
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DestinationCalendarsResponse | DestinationCalendarResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars:
|
||||
* get:
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* summary: Find all destination calendars
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: No destination calendars were found
|
||||
*/
|
||||
const data = await prisma.destinationCalendar.findMany({ where: { userId } });
|
||||
const destination_calendars = data.map((destinationCalendar) =>
|
||||
schemaDestinationCalendarReadPublic.parse(destinationCalendar)
|
||||
);
|
||||
if (data) res.status(200).json({ destination_calendars });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(404).json({
|
||||
message: "No DestinationCalendars were found",
|
||||
error,
|
||||
});
|
||||
} else if (method === "POST") {
|
||||
/**
|
||||
* @swagger
|
||||
* /destination-calendars:
|
||||
* post:
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* summary: Creates a new destination calendar
|
||||
* requestBody:
|
||||
* description: Create a new destination calendar for your events
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - integration
|
||||
* - externalId
|
||||
* properties:
|
||||
* integration:
|
||||
* type: string
|
||||
* description: 'The integration'
|
||||
* externalId:
|
||||
* type: string
|
||||
* description: 'The external ID of the integration'
|
||||
* eventTypeId:
|
||||
* type: integer
|
||||
* description: 'The ID of the eventType it is associated with'
|
||||
* bookingId:
|
||||
* type: integer
|
||||
* description: 'The booking ID it is associated with'
|
||||
* tags:
|
||||
* - destination-calendars
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, destination calendar created
|
||||
* 400:
|
||||
* description: Bad request. DestinationCalendar body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
const safe = schemaDestinationCalendarCreateBodyParams.safeParse(body);
|
||||
if (!safe.success) {
|
||||
res.status(400).json({ message: "Invalid request body" });
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await prisma.destinationCalendar.create({ data: { ...safe.data, userId } });
|
||||
const destination_calendar = schemaDestinationCalendarReadPublic.parse(data);
|
||||
|
||||
if (destination_calendar)
|
||||
res.status(201).json({ destination_calendar, message: "DestinationCalendar created successfully" });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
message: "Could not create new destinationCalendar",
|
||||
error,
|
||||
});
|
||||
} else res.status(405).json({ message: `Method ${method} not allowed` });
|
||||
}
|
||||
|
||||
export default withMiddleware("HTTP_GET_OR_POST")(createOrlistAllDestinationCalendars);
|
||||
export default withMiddleware()(
|
||||
defaultHandler({
|
||||
GET: import("./_get"),
|
||||
POST: import("./_post"),
|
||||
})
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue