From cabe4ae9c60f05145d1b24a5fa6a72a26a30163c Mon Sep 17 00:00:00 2001 From: Agusti Fernandez Pardo Date: Thu, 21 Apr 2022 00:48:54 +0200 Subject: [PATCH] feat: schedules hardend --- README.md | 19 ++++---- pages/api/schedules/[id].ts | 91 +++++++++++++++++++++--------------- pages/api/schedules/index.ts | 8 ++-- 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index c3faa6a283..3731387b94 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,9 @@ This is the public REST api for cal.com. It exposes CRUD Endpoints of all our mo - NextJS - TypeScript - Prisma -- No tRPC (for now) We hook directly into prisma client, but probably should look into adding a new @calcom/trpc package that adds pagination and such stuff and can be shared between webapp and API. +- No tRPC ** + +** (for now) We hook directly into prisma client, but probably should look into adding a new @calcom/trpc package that adds pagination and such stuff and can be shared between webapp and API. ## How to run it @@ -138,24 +140,23 @@ tests/endpoint/resource.new.test.ts - Create new resource | teams | ✅ | ✅ | ✅ | ✅ | ✅ | | users | ✅ | 👤[1] | ✅ | ✅ | ✅ | -## Models missing userId relation. +## Models missing userId relation - daily-event-references - destination-calendars - event-types-custom-input - memberships - reminder-mails -- schedules ## Models from database that are not exposed -mostly because they're deemed too sensitive can be revisited if needed. +mostly because they're deemed too sensitive can be revisited if needed. most are expected to be used via cal's webapp. -- [] Api Keys -- [] Credentials -- [] Webhooks -- [] ResetPasswordRequest -- [] VerificationToken +- [ ] Api Keys +- [ ] Credentials +- [ ] Webhooks +- [ ] ResetPasswordRequest +- [ ] VerificationToken ## Documentation (OpenAPI) diff --git a/pages/api/schedules/[id].ts b/pages/api/schedules/[id].ts index eb87d13949..1b46e62269 100644 --- a/pages/api/schedules/[id].ts +++ b/pages/api/schedules/[id].ts @@ -4,6 +4,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { ScheduleResponse } from "@lib/types"; +import { getCalcomUserId } from "@lib/utils/getCalcomUserId"; import { schemaScheduleBodyParams, schemaSchedulePublic } from "@lib/validations/schedule"; import { schemaQueryIdParseInt, @@ -90,47 +91,61 @@ export async function scheduleById(req: NextApiRequest, res: NextApiResponse schedule.id); + if (userScheduleIds.includes(safeQuery.data.id)) { + switch (method) { + case "GET": + await prisma.schedule + .findUnique({ where: { id: safeQuery.data.id } }) + .then((data) => schemaSchedulePublic.parse(data)) + .then((schedule) => res.status(200).json({ schedule })) + .catch((error: Error) => + res.status(404).json({ + message: `Schedule with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - switch (method) { - case "GET": - await prisma.schedule - .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaSchedulePublic.parse(data)) - .then((schedule) => res.status(200).json({ schedule })) - .catch((error: Error) => - res.status(404).json({ message: `Schedule with id: ${safeQuery.data.id} not found`, error }) - ); - break; + case "PATCH": + if (!safeBody.success) { + throw new Error("Invalid request body"); + } + await prisma.schedule + .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) + .then((data) => schemaSchedulePublic.parse(data)) + .then((schedule) => res.status(200).json({ schedule })) + .catch((error: Error) => + res.status(404).json({ + message: `Schedule with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - case "PATCH": - if (!safeBody.success) throw new Error("Invalid request body"); - await prisma.schedule - .update({ - where: { id: safeQuery.data.id }, - data: safeBody.data, - }) - .then((data) => schemaSchedulePublic.parse(data)) - .then((schedule) => res.status(200).json({ schedule })) - .catch((error: Error) => - res.status(404).json({ message: `Schedule with id: ${safeQuery.data.id} not found`, error }) - ); - break; + case "DELETE": + await prisma.schedule + .delete({ where: { id: safeQuery.data.id } }) + .then(() => + res.status(200).json({ + message: `Schedule with id: ${safeQuery.data.id} deleted successfully`, + }) + ) + .catch((error: Error) => + res.status(404).json({ + message: `Schedule with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - case "DELETE": - await prisma.schedule - .delete({ where: { id: safeQuery.data.id } }) - .then(() => - res.status(200).json({ message: `Schedule with id: ${safeQuery.data.id} deleted successfully` }) - ) - .catch((error: Error) => - res.status(404).json({ message: `Schedule with id: ${safeQuery.data.id} not found`, error }) - ); - break; - - default: - res.status(405).json({ message: "Method not allowed" }); - break; - } + default: + res.status(405).json({ message: "Method not allowed" }); + break; + } + } else res.status(401).json({ message: "Unauthorized" }); } export default withMiddleware("HTTP_GET_DELETE_PATCH")(withValidQueryIdTransformParseInt(scheduleById)); diff --git a/pages/api/schedules/index.ts b/pages/api/schedules/index.ts index 3f5761e30d..cb4eeaeb9d 100644 --- a/pages/api/schedules/index.ts +++ b/pages/api/schedules/index.ts @@ -4,6 +4,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import { ScheduleResponse, SchedulesResponse } from "@lib/types"; +import { getCalcomUserId } from "@lib/utils/getCalcomUserId"; import { schemaScheduleBodyParams, schemaSchedulePublic, withValidSchedule } from "@lib/validations/schedule"; /** @@ -42,8 +43,10 @@ async function createOrlistAllSchedules( res: NextApiResponse ) { const { method } = req; + const userId = getCalcomUserId(res); + if (method === "GET") { - const data = await prisma.schedule.findMany(); + const data = await prisma.schedule.findMany({ where: { userId } }); const schedules = data.map((schedule) => schemaSchedulePublic.parse(schedule)); if (schedules) res.status(200).json({ schedules }); else @@ -55,8 +58,7 @@ async function createOrlistAllSchedules( } else if (method === "POST") { const safe = schemaScheduleBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); - - const data = await prisma.schedule.create({ data: safe.data }); + const data = await prisma.schedule.create({ data: { ...safe.data, userId } }); const schedule = schemaSchedulePublic.parse(data); if (schedule) res.status(201).json({ schedule, message: "Schedule created successfully" });