diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..0e71ec1eae --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require("@calcom/config/eslint-preset"); diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 0378cf43af..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,17 +0,0 @@ -// FIXME: import eslint-config-calcom-base from '@calcom/config/eslint -{ - "root": true, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended", - "plugin:@next/next/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { "project": ["./tsconfig.json"] }, - "plugins": ["@typescript-eslint", "prettier"], - "rules": { - "prettier/prettier": "error" - }, - "ignorePatterns": ["src/**/*.test.ts", "src/frontend/generated/*"] -} diff --git a/pages/api/memberships/[id].ts b/pages/api/memberships/[id].ts new file mode 100644 index 0000000000..d78d0f1c88 --- /dev/null +++ b/pages/api/memberships/[id].ts @@ -0,0 +1,147 @@ +import type { NextApiRequest, NextApiResponse } from "next"; + +import prisma from "@calcom/prisma"; + +import { withMiddleware } from "@lib/helpers/withMiddleware"; +import type { MembershipResponse } from "@lib/types"; +import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validations/membership"; +import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; + +/** + * @swagger + * /api/memberships/{userId}_{teamId}: + * get: + * summary: Get a membership by userID and teamID + * parameters: + * - in: path + * name: userId + * schema: + * type: integer + * required: true + * description: Numeric userId of the membership to get + * - in: path + * name: teamId + * schema: + * type: integer + * required: true + * description: Numeric teamId of the membership to get + * tags: + * - memberships + * responses: + * 200: + * description: OK + * 401: + * description: Authorization information is missing or invalid. + * 404: + * description: Membership was not found + * patch: + * summary: Edit an existing membership + * consumes: + * - application/json + * parameters: + * - in: body + * name: membership + * description: The membership to edit + * schema: + * type: object + * $ref: '#/components/schemas/Membership' + * required: true + * - in: path + * name: userId + * schema: + * type: integer + * required: true + * description: Numeric userId of the membership to get + * - in: path + * name: teamId + * schema: + * type: integer + * required: true + * description: Numeric teamId of the membership to get + * tags: + * - memberships + * responses: + * 201: + * description: OK, membership edited successfuly + * model: Membership + * 400: + * description: Bad request. Membership body is invalid. + * 401: + * description: Authorization information is missing or invalid. + * delete: + * summary: Remove an existing membership + * parameters: + * - in: path + * name: userId + * schema: + * type: integer + * required: true + * description: Numeric userId of the membership to get + * - in: path + * name: teamId + * schema: + * type: integer + * required: true + * description: Numeric teamId of the membership to get + * tags: + * - memberships + * responses: + * 201: + * description: OK, membership removed successfuly + * model: Membership + * 400: + * description: Bad request. Membership id is invalid. + * 401: + * description: Authorization information is missing or invalid. + */ +export async function membershipById(req: NextApiRequest, res: NextApiResponse) { + const { method, query, body } = req; + const safeQuery = await schemaQueryIdAsString.safeParse(query); + const safeBody = await schemaMembershipBodyParams.safeParse(body); + if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); + // This is how we set the userId and teamId in the query for managing compoundId. + const [userId, teamId] = safeQuery.data.id.split("_"); + + switch (method) { + case "GET": + await prisma.membership + .findUnique({ where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } } }) + .then((membership) => schemaMembershipPublic.parse(membership)) + .then((data) => res.status(200).json({ data })) + .catch((error: Error) => + res.status(404).json({ message: `Membership with id: ${safeQuery.data.id} not found`, error }) + ); + break; + + case "PATCH": + if (!safeBody.success) throw new Error("Invalid request body"); + await prisma.membership + .update({ + where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } }, + data: safeBody.data, + }) + .then((membership) => schemaMembershipPublic.parse(membership)) + .then((data) => res.status(200).json({ data })) + .catch((error: Error) => + res.status(404).json({ message: `Membership with id: ${safeQuery.data.id} not found`, error }) + ); + break; + + case "DELETE": + await prisma.membership + .delete({ where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } } }) + .then(() => + res.status(200).json({ message: `Membership with id: ${safeQuery.data.id} deleted successfully` }) + ) + .catch((error: Error) => + res.status(404).json({ message: `Membership 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")(withValidQueryIdString(membershipById)); diff --git a/pages/api/memberships/[id]/delete.ts b/pages/api/memberships/[id]/delete.ts deleted file mode 100644 index 8eb4e8ae4a..0000000000 --- a/pages/api/memberships/[id]/delete.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { BaseResponse } from "@lib/types"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/memberships/{userId}_{teamId}/delete: - * delete: - * summary: Remove an existing membership - * parameters: - * - in: path - * name: userId - * schema: - * type: integer - * required: true - * description: Numeric ID of the user to get the membership of - * - in: path - * name: teamId - * schema: - * type: integer - * required: true - * description: Numeric ID of the team to get the membership of - * tags: - * - memberships - * responses: - * 201: - * description: OK, membership removed successfuly - * model: Membership - * 400: - * description: Bad request. Membership id is invalid. - * 401: - * description: Authorization information is missing or invalid. - */ -export async function deleteMembership(req: NextApiRequest, res: NextApiResponse) { - const safe = await schemaQueryIdAsString.safeParse(req.query); - if (!safe.success) throw new Error("Invalid request query", safe.error); - const [userId, teamId] = safe.data.id.split("_"); - const data = await prisma.membership.delete({ - where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } }, - }); - - if (data) res.status(200).json({ message: `Membership with id: ${safe.data.id} deleted successfully` }); - else - (error: Error) => - res.status(400).json({ - message: `Membership with id: ${safe.data.id} was not able to be processed`, - error, - }); -} - -export default withMiddleware("HTTP_DELETE")(withValidQueryIdString(deleteMembership)); diff --git a/pages/api/memberships/[id]/edit.ts b/pages/api/memberships/[id]/edit.ts deleted file mode 100644 index 66c6ccec24..0000000000 --- a/pages/api/memberships/[id]/edit.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { MembershipResponse } from "@lib/types"; -import { - schemaMembershipBodyParams, - schemaMembershipPublic, - withValidMembership, -} from "@lib/validations/membership"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/memberships/{id}/edit: - * patch: - * summary: Edits an existing membership - * tags: - * - memberships - * responses: - * 201: - * description: OK, membership edited successfuly - * model: Membership - * 400: - * description: Bad request. Membership body is invalid. - * 401: - * description: Authorization information is missing or invalid. - */ -export async function editMembership(req: NextApiRequest, res: NextApiResponse) { - const safeQuery = await schemaQueryIdAsString.safeParse(req.query); - const safeBody = await schemaMembershipBodyParams.safeParse(req.body); - if (!safeQuery.success || !safeBody.success) throw new Error("Invalid request"); - const [userId, teamId] = safeQuery.data.id.split("_"); - - const membership = await prisma.membership.update({ - where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } }, - data: safeBody.data, - }); - const data = schemaMembershipPublic.parse(membership); - - if (data) res.status(200).json({ data }); - else - (error: Error) => - res.status(404).json({ - message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, - error, - }); -} - -export default withMiddleware("HTTP_PATCH")(withValidQueryIdString(withValidMembership(editMembership))); diff --git a/pages/api/memberships/[id]/index.ts b/pages/api/memberships/[id]/index.ts deleted file mode 100644 index a1505f185e..0000000000 --- a/pages/api/memberships/[id]/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { MembershipResponse } from "@lib/types"; -import { schemaMembershipPublic } from "@lib/validations/membership"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/memberships/{userId}_{teamId}: - * get: - * summary: find membership by userID and teamID - * parameters: - * - in: path - * name: userId - * schema: - * type: integer - * required: true - * description: Numeric userId of the membership to get - * - in: path - * name: teamId - * schema: - * type: integer - * required: true - * description: Numeric teamId of the membership to get - * tags: - * - memberships - * responses: - * 200: - * description: OK - * 401: - * description: Authorization information is missing or invalid. - * 404: - * description: Membership was not found - */ -export async function membershipById(req: NextApiRequest, res: NextApiResponse) { - const safe = await schemaQueryIdAsString.safeParse(req.query); - if (!safe.success) throw new Error("Invalid request query"); - const [userId, teamId] = safe.data.id.split("_"); - - const membership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } }, - }); - const data = schemaMembershipPublic.parse(membership); - - if (membership) res.status(200).json({ data }); - else - (error: Error) => - res.status(404).json({ - message: "Membership was not found", - error, - }); -} - -export default withMiddleware("HTTP_GET")(withValidQueryIdString(membershipById)); diff --git a/pages/api/payments/[id].ts b/pages/api/payments/[id].ts index a9ee3c78fe..14b106ca43 100644 --- a/pages/api/payments/[id].ts +++ b/pages/api/payments/[id].ts @@ -5,10 +5,7 @@ import prisma from "@calcom/prisma"; import { withMiddleware } from "@lib/helpers/withMiddleware"; import type { PaymentResponse } from "@lib/types"; import { schemaPaymentBodyParams, schemaPaymentPublic } from "@lib/validations/payment"; -import { - schemaQueryIdParseInt, - withValidQueryIdTransformParseInt, -} from "@lib/validations/shared/queryIdTransformParseInt"; +import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; /** * @swagger @@ -81,14 +78,17 @@ import { */ export async function paymentById(req: NextApiRequest, res: NextApiResponse) { const { method, query, body } = req; - const safeQuery = await schemaQueryIdParseInt.safeParse(query); + const safeQuery = await schemaQueryIdAsString.safeParse(query); const safeBody = await schemaPaymentBodyParams.safeParse(body); if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); + const [userId, teamId] = safeQuery.data.id.split("_"); switch (method) { case "GET": await prisma.payment - .findUnique({ where: { id: safeQuery.data.id } }) + .findUnique({ + where: { userId_teamId: { userId: parseInt(userId), teamId: parseInt(teamId) } }, + }) .then((payment) => schemaPaymentPublic.parse(payment)) .then((data) => res.status(200).json({ data })) .catch((error: Error) => @@ -127,4 +127,4 @@ export async function paymentById(req: NextApiRequest, res: NextApiResponse +) { + const { method, query, body } = req; + const safeQuery = await schemaQueryIdAsString.safeParse(query); + const safeBody = await schemaSelectedCalendarBodyParams.safeParse(body); + if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error); + // This is how we set the userId and teamId in the query for managing compoundId. + const [userId, integration, externalId] = safeQuery.data.id.split("_"); + + switch (method) { + case "GET": + await prisma.selectedCalendar + .findUnique({ + where: { + userId_integration_externalId: { + userId: parseInt(userId), + integration: integration, + externalId: externalId, + }, + }, + }) + .then((selectedCalendar) => schemaSelectedCalendarPublic.parse(selectedCalendar)) + .then((data) => res.status(200).json({ data })) + .catch((error: Error) => + res.status(404).json({ message: `SelectedCalendar with id: ${safeQuery.data.id} not found`, error }) + ); + break; + + case "PATCH": + if (!safeBody.success) throw new Error("Invalid request body"); + await prisma.selectedCalendar + .update({ + where: { + userId_integration_externalId: { + userId: parseInt(userId), + integration: integration, + externalId: externalId, + }, + }, + data: safeBody.data, + }) + .then((selectedCalendar) => schemaSelectedCalendarPublic.parse(selectedCalendar)) + .then((data) => res.status(200).json({ data })) + .catch((error: Error) => + res.status(404).json({ message: `SelectedCalendar with id: ${safeQuery.data.id} not found`, error }) + ); + break; + + case "DELETE": + await prisma.selectedCalendar + .delete({ + where: { + userId_integration_externalId: { + userId: parseInt(userId), + integration: integration, + externalId: externalId, + }, + }, + }) + .then(() => + res + .status(200) + .json({ message: `SelectedCalendar with id: ${safeQuery.data.id} deleted successfully` }) + ) + .catch((error: Error) => + res.status(404).json({ message: `SelectedCalendar 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")(withValidQueryIdString(selectedCalendarById)); diff --git a/pages/api/selected-calendars/[id]/delete.ts b/pages/api/selected-calendars/[id]/delete.ts deleted file mode 100644 index ec1abebed4..0000000000 --- a/pages/api/selected-calendars/[id]/delete.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { BaseResponse } from "@lib/types"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/selected-calendars/{userId}_{teamId}/delete: - * delete: - * summary: Remove an existing record of a selected calendar - * parameters: - * - in: path - * - name: userId - * schema: - * type: integer - * required: true - * description: Numeric ID of the user to get the selected calendar of - * - name: teamId - * schema: - * type: integer - * required: true - * description: Numeric ID of the team to get the selected calendar of - * tags: - * - selected-calendars - * responses: - * 201: - * description: OK, selected calendar removed successfuly - * 400: - * description: Bad request. selected calendar id is invalid. - * 401: - * description: Authorization information is missing or invalid. - */ -export async function deleteSelectedCalendar(req: NextApiRequest, res: NextApiResponse) { - const safe = await schemaQueryIdAsString.safeParse(req.query); - if (!safe.success) throw new Error("Invalid request query", safe.error); - const [userId, integration, externalId] = safe.data.id.split("_"); - const data = await prisma.selectedCalendar.delete({ - where: { - userId_integration_externalId: { - userId: parseInt(userId), - integration: integration, - externalId: externalId, - }, - }, - }); - - if (data) - res.status(200).json({ message: `SelectedCalendar with id: ${safe.data.id} deleted successfully` }); - else - (error: Error) => - res.status(400).json({ - message: `SelectedCalendar with id: ${safe.data.id} was not able to be processed`, - error, - }); -} - -export default withMiddleware("HTTP_DELETE")(withValidQueryIdString(deleteSelectedCalendar)); diff --git a/pages/api/selected-calendars/[id]/edit.ts b/pages/api/selected-calendars/[id]/edit.ts deleted file mode 100644 index c5737eb4e6..0000000000 --- a/pages/api/selected-calendars/[id]/edit.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { SelectedCalendarResponse } from "@lib/types"; -import { - schemaSelectedCalendarBodyParams, - schemaSelectedCalendarPublic, - withValidSelectedCalendar, -} from "@lib/validations/selected-calendar"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/selected-calendars/{id}/edit: - * patch: - * summary: Edits an existing selectedCalendar - * tags: - * - selected-calendars - * responses: - * 201: - * description: OK, selectedCalendar edited successfuly - * model: SelectedCalendar - * 400: - * description: Bad request. SelectedCalendar body is invalid. - * 401: - * description: Authorization information is missing or invalid. - */ -export async function editSelectedCalendar( - req: NextApiRequest, - res: NextApiResponse -) { - const safeQuery = await schemaQueryIdAsString.safeParse(req.query); - const safeBody = await schemaSelectedCalendarBodyParams.safeParse(req.body); - if (!safeQuery.success || !safeBody.success) throw new Error("Invalid request"); - const [userId, integration, externalId] = safeQuery.data.id.split("_"); - - const selectedCalendar = await prisma.selectedCalendar.update({ - where: { - userId_integration_externalId: { - userId: parseInt(userId), - integration: integration, - externalId: externalId, - }, - }, - data: safeBody.data, - }); - const data = schemaSelectedCalendarPublic.parse(selectedCalendar); - - if (data) res.status(200).json({ data }); - else - (error: Error) => - res.status(404).json({ - message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, - error, - }); -} - -export default withMiddleware("HTTP_PATCH")( - withValidQueryIdString(withValidSelectedCalendar(editSelectedCalendar)) -); diff --git a/pages/api/selected-calendars/[id]/index.ts b/pages/api/selected-calendars/[id]/index.ts deleted file mode 100644 index bec8bcc600..0000000000 --- a/pages/api/selected-calendars/[id]/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; - -import prisma from "@calcom/prisma"; - -import { withMiddleware } from "@lib/helpers/withMiddleware"; -import type { SelectedCalendarResponse } from "@lib/types"; -import { schemaSelectedCalendarPublic } from "@lib/validations/selected-calendar"; -import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString"; - -/** - * @swagger - * /api/selected-calendars/{userId}_{teamId}: - * get: - * summary: find selectedCalendar by userID and teamID - * parameters: - * - in: path - * name: userId - * schema: - * type: integer - * required: true - * description: Numeric userId of the selectedCalendar to get - * - in: path - * name: teamId - * schema: - * type: integer - * required: true - * description: Numeric teamId of the selectedCalendar to get - * tags: - * - selected-calendars - * responses: - * 200: - * description: OK - * 401: - * description: Authorization information is missing or invalid. - * 404: - * description: SelectedCalendar was not found - */ -export async function selectedCalendarById( - req: NextApiRequest, - res: NextApiResponse -) { - const safe = await schemaQueryIdAsString.safeParse(req.query); - if (!safe.success) throw new Error("Invalid request query"); - const [userId, integration, externalId] = safe.data.id.split("_"); - - const selectedCalendar = await prisma.selectedCalendar.findUnique({ - where: { - userId_integration_externalId: { - userId: parseInt(userId), - integration: integration, - externalId: externalId, - }, - }, - }); - const data = schemaSelectedCalendarPublic.parse(selectedCalendar); - - if (selectedCalendar) res.status(200).json({ data }); - else - (error: Error) => - res.status(404).json({ - message: "SelectedCalendar was not found", - error, - }); -} - -export default withMiddleware("HTTP_GET")(withValidQueryIdString(selectedCalendarById));