diff --git a/pages/api/hooks/[id].ts b/pages/api/hooks/[id].ts new file mode 100644 index 0000000000..c9fcdf346d --- /dev/null +++ b/pages/api/hooks/[id].ts @@ -0,0 +1,153 @@ +import type { NextApiRequest, NextApiResponse } from "next"; + +import prisma from "@calcom/prisma"; + +import { withMiddleware } from "@lib/helpers/withMiddleware"; +import type { WebhookResponse } from "@lib/types"; +import { schemaWebhookBodyParams, schemaWebhookPublic } from "@lib/validations/webhook"; +import { + schemaQueryIdParseInt, + withValidQueryIdTransformParseInt, +} from "@lib/validations/shared/queryIdTransformParseInt"; + +export async function WebhookById( + { method, query, body, userId }: NextApiRequest, + res: NextApiResponse +) { + const safeQuery = schemaQueryIdParseInt.safeParse(query); + if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); + const data = await prisma.webhook.findMany({ where: { userId } }); + const userWebhooks = data.map((webhook) => webhook.id); + if (!userWebhooks.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" }); + else { + switch (method) { + /** + * @swagger + * /hooks/{id}: + * get: + * summary: Find a webhook + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: Numeric ID of the webhook to get + * security: + * - ApiKeyAuth: [] + * tags: + * - hooks + * externalDocs: + * url: https://docs.cal.com/hooks + * responses: + * 200: + * description: OK + * 401: + * description: Authorization information is missing or invalid. + * 404: + * description: Webhook was not found + */ + case "GET": + await prisma.webhook + .findUnique({ where: { id: safeQuery.data.id } }) + .then((data) => schemaWebhookPublic.parse(data)) + .then((hook) => res.status(200).json({ hook })) + .catch((error: Error) => + res.status(404).json({ + message: `Webhook with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; + /** + * @swagger + * /hooks/{id}: + * patch: + * summary: Edit an existing webhook + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: Numeric ID of the webhook to edit + * security: + * - ApiKeyAuth: [] + * tags: + * - hooks + * externalDocs: + * url: https://docs.cal.com/hooks + * responses: + * 201: + * description: OK, webhook edited successfuly + * 400: + * description: Bad request. Webhook body is invalid. + * 401: + * description: Authorization information is missing or invalid. + */ + case "PATCH": + const safeBody = schemaWebhookBodyParams.safeParse(body); + if (!safeBody.success) { + throw new Error("Invalid request body"); + } + await prisma.webhook + .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) + .then((data) => schemaWebhookPublic.parse(data)) + .then((hook) => res.status(200).json({ hook })) + .catch((error: Error) => + res.status(404).json({ + message: `Webhook with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; + /** + * @swagger + * /hooks/{id}: + * delete: + * summary: Remove an existing hook + * parameters: + * - in: path + * name: id + * schema: + * type: integer + * required: true + * description: Numeric ID of the hooks to delete + * security: + * - ApiKeyAuth: [] + * tags: + * - hooks + * externalDocs: + * url: https://docs.cal.com/hooks + * responses: + * 201: + * description: OK, hook removed successfuly + * 400: + * description: Bad request. hook id is invalid. + * 401: + * description: Authorization information is missing or invalid. + */ + case "DELETE": + await prisma.webhook + .delete({ where: { id: safeQuery.data.id } }) + .then(() => + res.status(200).json({ + message: `Webhook with id: ${safeQuery.data.id} deleted`, + }) + ) + .catch((error: Error) => + res.status(404).json({ + message: `Webhook 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(WebhookById)); diff --git a/pages/api/hooks/index.ts b/pages/api/hooks/index.ts new file mode 100644 index 0000000000..9ff4f441af --- /dev/null +++ b/pages/api/hooks/index.ts @@ -0,0 +1,74 @@ +import type { NextApiRequest, NextApiResponse } from "next"; + +import prisma from "@calcom/prisma"; + +import { withMiddleware } from "@lib/helpers/withMiddleware"; +import { WebhookResponse, WebhooksResponse } from "@lib/types"; +import { schemaWebhookBodyParams, schemaWebhookPublic } from "@lib/validations/webhook"; + +async function createOrlistAllWebhooks( + { method, body, userId }: NextApiRequest, + res: NextApiResponse +) { + if (method === "GET") { + /** + * @swagger + * /hooks: + * get: + * summary: Find all webhooks + * tags: + * - hooks + * externalDocs: + * url: https://docs.cal.com/webhooks + * responses: + * 200: + * description: OK + * 401: + * description: Authorization information is missing or invalid. + * 404: + * description: No webhooks were found + */ + const data = await prisma.webhooks.findMany({ where: { userId } }); + const webhooks = data.map((webhook) => schemaWebhookPublic.parse(webhook)); + if (webhooks) res.status(200).json({ webhooks }); + else + (error: Error) => + res.status(404).json({ + message: "No Webhooks were found", + error, + }); + } else if (method === "POST") { + /** + * @swagger + * /hooks: + * post: + * summary: Creates a new webhook + * tags: + * - webhooks + * externalDocs: + * url: https://docs.cal.com/webhooks + * responses: + * 201: + * description: OK, webhook created + * 400: + * description: Bad request. webhook body is invalid. + * 401: + * description: Authorization information is missing or invalid. + */ + const safe = schemaWebhookBodyParams.safeParse(body); + if (!safe.success) throw new Error("Invalid request body"); + + const data = await prisma.webhook.create({ data: { ...safe.data, userId } }); + const webhook = schemaWebhookPublic.parse(data); + + if (data) res.status(201).json({ webhook, message: "Webhook created successfully" }); + else + (error: Error) => + res.status(400).json({ + message: "Could not create new webhook", + error, + }); + } else res.status(405).json({ message: `Method ${method} not allowed` }); +} + +export default withMiddleware("HTTP_GET_OR_POST")(createOrlistAllWebhooks);