diff --git a/README.md b/README.md index 3731387b94..480973762b 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,6 @@ tests/endpoint/resource.new.test.ts - Create new resource | event-types | ✅ | ✅ | ✅ | ✅ | ✅ | | memberships | ✅ | ✅ | ✅ | ✅ | ✅ | | payments | ✅ | ✅ | ❌ | ❌ | ❌ | -| reminder-mails | ✅ | ✅ | ✅ | ✅ | ✅ | | schedules | ✅ | ✅ | ✅ | ✅ | ✅ | | selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ | | teams | ✅ | ✅ | ✅ | ✅ | ✅ | @@ -144,9 +143,7 @@ tests/endpoint/resource.new.test.ts - Create new resource - daily-event-references - destination-calendars -- event-types-custom-input -- memberships -- reminder-mails + ## Models from database that are not exposed @@ -157,7 +154,8 @@ mostly because they're deemed too sensitive can be revisited if needed. most are - [ ] Webhooks - [ ] ResetPasswordRequest - [ ] VerificationToken - +- [ ] ReminderMail +- [ ] ## Documentation (OpenAPI) You will see that each endpoint has a comment at the top with the annotation `@swagger` with the documentation of the endpoint, **please update it if you change the code!** This is what auto-generates the OpenAPI spec by collecting the YAML in each endpoint and parsing it in /docs alongside the json-schema (auto-generated from prisma package, not added to code but manually for now, need to fix later) diff --git a/pages/api/event-type-custom-inputs/[id].ts b/pages/api/event-type-custom-inputs/[id].ts index d9dd21d112..5a00436361 100644 --- a/pages/api/event-type-custom-inputs/[id].ts +++ b/pages/api/event-type-custom-inputs/[id].ts @@ -4,6 +4,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { EventTypeCustomInputResponse } from "@lib/types"; +import { getCalcomUserId } from "@lib/utils/getCalcomUserId"; import { schemaEventTypeCustomInputBodyParams, schemaEventTypeCustomInputPublic, @@ -93,47 +94,69 @@ async function eventTypeById(req: NextApiRequest, res: NextApiResponse eventType.id); + const userEventTypeCustomInputs = await prisma.eventTypeCustomInput.findMany({ + where: { eventType: userEventTypes }, + }); + const userEventTypeCustomInputIds = userEventTypeCustomInputs.map( + (eventTypeCustomInput) => eventTypeCustomInput.id + ); + if (userEventTypeCustomInputIds.includes(safeQuery.data.id)) { + switch (method) { + case "GET": + await prisma.eventTypeCustomInput + .findUnique({ where: { id: safeQuery.data.id } }) + .then((data) => schemaEventTypeCustomInputPublic.parse(data)) + .then((event_type_custom_input) => res.status(200).json({ event_type_custom_input })) + .catch((error: Error) => + res.status(404).json({ + message: `EventType with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - switch (method) { - case "GET": - await prisma.eventTypeCustomInput - .findUnique({ where: { id: safeQuery.data.id } }) - .then((data) => schemaEventTypeCustomInputPublic.parse(data)) - .then((event_type_custom_input) => res.status(200).json({ event_type_custom_input })) - .catch((error: Error) => - res.status(404).json({ message: `EventType with id: ${safeQuery.data.id} not found`, error }) - ); - break; + case "PATCH": + if (!safeBody.success) { + throw new Error("Invalid request body"); + } + await prisma.eventTypeCustomInput + .update({ where: { id: safeQuery.data.id }, data: safeBody.data }) + .then((data) => schemaEventTypeCustomInputPublic.parse(data)) + .then((event_type_custom_input) => res.status(200).json({ event_type_custom_input })) + .catch((error: Error) => + res.status(404).json({ + message: `EventType with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - case "PATCH": - if (!safeBody.success) throw new Error("Invalid request body"); - await prisma.eventTypeCustomInput - .update({ - where: { id: safeQuery.data.id }, - data: safeBody.data, - }) - .then((data) => schemaEventTypeCustomInputPublic.parse(data)) - .then((event_type_custom_input) => res.status(200).json({ event_type_custom_input })) - .catch((error: Error) => - res.status(404).json({ message: `EventType with id: ${safeQuery.data.id} not found`, error }) - ); - break; + case "DELETE": + await prisma.eventTypeCustomInput + .delete({ + where: { id: safeQuery.data.id }, + }) + .then(() => + res.status(200).json({ + message: `CustomInputEventType with id: ${safeQuery.data.id} deleted`, + }) + ) + .catch((error: Error) => + res.status(404).json({ + message: `EventType with id: ${safeQuery.data.id} not found`, + error, + }) + ); + break; - case "DELETE": - await prisma.eventTypeCustomInput - .delete({ where: { id: safeQuery.data.id } }) - .then(() => - res.status(200).json({ message: `CustomInputEventType with id: ${safeQuery.data.id} deleted` }) - ) - .catch((error: Error) => - res.status(404).json({ message: `EventType 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(eventTypeById)); diff --git a/pages/api/event-type-custom-inputs/index.ts b/pages/api/event-type-custom-inputs/index.ts index 806d3ca91e..e6c0c852bf 100644 --- a/pages/api/event-type-custom-inputs/index.ts +++ b/pages/api/event-type-custom-inputs/index.ts @@ -45,8 +45,17 @@ async function createOrlistAllEventTypeCustomInputs( res: NextApiResponse ) { const { method } = req; + const userId = getCalcomUserId(res); + const data = await prisma.eventType.findMany({ where: { userId } }); + const userEventTypes = data.map((eventType) => eventType.id); + // const userEventTypeCustomInputs = await prisma.eventTypeCustomInput.findMany({ + // where: { eventType: userEventTypes }, + // }); + // const userEventTypeCustomInputIds = userEventTypeCustomInputs.map( + // (eventTypeCustomInput) => eventTypeCustomInput.id + // ); if (method === "GET") { - const data = await prisma.eventTypeCustomInput.findMany(); + const data = await prisma.eventTypeCustomInput.findMany({ where: { eventType: userEventTypes } }); const event_type_custom_inputs = data.map((eventTypeCustomInput) => schemaEventTypeCustomInputPublic.parse(eventTypeCustomInput) ); @@ -60,13 +69,25 @@ async function createOrlistAllEventTypeCustomInputs( } else if (method === "POST") { const safe = schemaEventTypeCustomInputBodyParams.safeParse(req.body); if (!safe.success) throw new Error("Invalid request body"); - - const data = await prisma.eventTypeCustomInput.create({ data: safe.data }); - const event_type_custom_input = schemaEventTypeCustomInputPublic.parse(data); - - if (event_type_custom_input) - res.status(201).json({ event_type_custom_input, message: "EventTypeCustomInput created successfully" }); - else + // Since we're supporting a create or connect relation on eventType, we need to treat them differently + // When using connect on event type, check if userId is the owner of the event + if (safe.data.eventType.connect && !userEventTypes.includes(safe.data.eventType.connect.id as number)) { + const data = await prisma.eventTypeCustomInput.create({ data: { ...safe.data } }); + const event_type_custom_input = schemaEventTypeCustomInputPublic.parse(data); + if (event_type_custom_input) + res + .status(201) + .json({ event_type_custom_input, message: "EventTypeCustomInput created successfully" }); + // When creating, no need + // FIXME: we might want to pass userId to the new created/linked eventType, though. + } else if (safe.data.eventType.create) { + const data = await prisma.eventTypeCustomInput.create({ data: { ...safe.data } }); + const event_type_custom_input = schemaEventTypeCustomInputPublic.parse(data); + if (event_type_custom_input) + res + .status(201) + .json({ event_type_custom_input, message: "EventTypeCustomInput created successfully" }); + } else (error: Error) => res.status(400).json({ message: "Could not create new eventTypeCustomInput",