Merge pull request #13 from calcom/feat/swagger-docs
commit
064c39b7f6
|
@ -8,7 +8,8 @@ export const captureErrors: NextMiddleware = async (_req, res, next) => {
|
|||
await next();
|
||||
} catch (err) {
|
||||
Sentry.captureException(err);
|
||||
res.status(500);
|
||||
res.json({ error: err });
|
||||
console.log(err);
|
||||
res.status(400).json({ message: "Something went wrong", error: err });
|
||||
// res.json({ error: err });
|
||||
}
|
||||
};
|
||||
|
|
|
@ -11,13 +11,14 @@ const dateInPast = function (firstDate: Date, secondDate: Date) {
|
|||
const today = new Date();
|
||||
|
||||
export const verifyApiKey: NextMiddleware = async (req, res, next) => {
|
||||
if (!req.query.apiKey) res.status(401).json({ message: "No API key provided" });
|
||||
const apiKey = await prisma.apiKey.findUnique({ where: { id: req.query.apiKey as string } });
|
||||
if (!apiKey) {
|
||||
res.status(400).json({ error: "Your api key is not valid" });
|
||||
res.status(401).json({ error: "Your api key is not valid" });
|
||||
throw new Error("No api key found");
|
||||
}
|
||||
if (apiKey.expiresAt && apiKey.userId && dateInPast(apiKey.expiresAt, today)) {
|
||||
res.setHeader("Calcom-User-ID", apiKey.userId);
|
||||
await next();
|
||||
} else res.status(400).json({ error: "Your api key is not valid" });
|
||||
} else res.status(401).json({ error: "Your api key is not valid" });
|
||||
};
|
||||
|
|
18
lib/types.ts
18
lib/types.ts
|
@ -1,4 +1,4 @@
|
|||
import { User, ApiKey } from "@calcom/prisma/client";
|
||||
import { User, ApiKey, Team, SelectedCalendar } from "@calcom/prisma/client";
|
||||
|
||||
// Base response, used for all responses
|
||||
export type BaseResponse = {
|
||||
|
@ -20,3 +20,19 @@ export type ApiKeyResponse = BaseResponse & {
|
|||
export type ApiKeysResponse = BaseResponse & {
|
||||
data?: Partial<ApiKey>[];
|
||||
};
|
||||
|
||||
// API Key
|
||||
export type TeamResponse = BaseResponse & {
|
||||
data?: Partial<Team>;
|
||||
};
|
||||
export type TeamsResponse = BaseResponse & {
|
||||
data?: Partial<Team>[];
|
||||
};
|
||||
|
||||
// API Key
|
||||
export type SelectedCalendarResponse = BaseResponse & {
|
||||
data?: Partial<SelectedCalendar>;
|
||||
};
|
||||
export type SelectedCalendarsResponse = BaseResponse & {
|
||||
data?: Partial<SelectedCalendar>[];
|
||||
};
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaSelectedCalendar = z.object({}).strict();
|
||||
const withValidSelectedCalendar = withValidation({
|
||||
schema: schemaSelectedCalendar,
|
||||
import { _SelectedCalendarModel as SelectedCalendar } from "@calcom/prisma/zod";
|
||||
|
||||
export const schemaSelectedCalendarBodyParams = SelectedCalendar.omit({});
|
||||
|
||||
export const schemaSelectedCalendarPublic = SelectedCalendar.omit({ userId: true });
|
||||
|
||||
export const withValidSelectedCalendar = withValidation({
|
||||
schema: schemaSelectedCalendarBodyParams,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaSelectedCalendar, withValidSelectedCalendar };
|
||||
|
|
|
@ -6,7 +6,7 @@ export const baseApiParams = z
|
|||
.object({
|
||||
// since we added apiKey as query param this is required by next-validations helper
|
||||
// for query params to work properly and not fail.
|
||||
apiKey: z.string().cuid(),
|
||||
apiKey: z.string().cuid().optional(),
|
||||
// version required for supporting /v1/ redirect to query in api as *?version=1
|
||||
version: z.string().optional(),
|
||||
})
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaTeam = z
|
||||
.object({
|
||||
slug: z.string().min(3),
|
||||
name: z.string().min(3),
|
||||
hideBranding: z.boolean().default(false),
|
||||
bio: z.string().min(3).optional(),
|
||||
logo: z.string().optional(),
|
||||
})
|
||||
.strict();
|
||||
const withValidTeam = withValidation({
|
||||
schema: schemaTeam,
|
||||
import { _TeamModel as Team } from "@calcom/prisma/zod";
|
||||
|
||||
export const schemaTeamBodyParams = Team.omit({ id: true });
|
||||
|
||||
export const schemaTeamPublic = Team.omit({});
|
||||
|
||||
export const withValidTeam = withValidation({
|
||||
schema: schemaTeamBodyParams,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaTeam, withValidTeam };
|
||||
|
|
|
@ -28,12 +28,14 @@
|
|||
"babel-jest": "^27.5.1",
|
||||
"husky": "^7.0.4",
|
||||
"jest": "^27.5.1",
|
||||
"node-mocks-http": "^1.11.0"
|
||||
"node-mocks-http": "^1.11.0",
|
||||
"prettier": "^2.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/nextjs": "^6.19.2",
|
||||
"next": "^12.1.0",
|
||||
"next-api-middleware": "^1.0.1",
|
||||
"next-swagger-doc": "^0.2.1",
|
||||
"next-transpile-modules": "^9.0.0",
|
||||
"next-validations": "^0.1.11",
|
||||
"typescript": "^4.6.3",
|
||||
|
|
|
@ -1,17 +1,22 @@
|
|||
// import { NextApiResponse } from "next";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
// Not much useful yet as prisma.client can't be used in the middlewares (client is not available)
|
||||
// For now we just throw early if no apiKey is passed,
|
||||
// but we could also check if the apiKey is valid if we had prisma here.
|
||||
|
||||
export default async function requireApiKeyAsQueryParams({ nextUrl }: NextRequest) {
|
||||
export default async function requireApiKeyAsQueryParams({ nextUrl }: NextRequest, res: NextResponse) {
|
||||
const response = NextResponse.next();
|
||||
const apiKey = nextUrl.searchParams.get("apiKey");
|
||||
|
||||
if (apiKey) return response;
|
||||
// if no apiKey is passed, we throw early
|
||||
// if no apiKey is passed, we throw early a 401 unauthorized
|
||||
else
|
||||
throw new Error(
|
||||
"You need to pass an apiKey as query param: https://api.cal.com/resource?apiKey=<your-api-key>"
|
||||
new NextResponse(
|
||||
JSON.stringify({
|
||||
message:
|
||||
"You need to pass an apiKey as query param: https://api.cal.com/resource?apiKey=<your-api-key>",
|
||||
}),
|
||||
{ status: 401, statusText: "Unauthorized" }
|
||||
);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { withSwagger } from "next-swagger-doc";
|
||||
|
||||
const swaggerHandler = withSwagger({
|
||||
definition: {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Cal.com Public API",
|
||||
version: "1.0.0",
|
||||
},
|
||||
},
|
||||
apiFolder: "pages/api",
|
||||
});
|
||||
export default swaggerHandler();
|
|
@ -2,28 +2,41 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
|||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { BaseResponse } from "@lib/types";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
/**
|
||||
* @swagger
|
||||
* /api/selectedCalendars/:id/delete:
|
||||
* delete:
|
||||
* description: Remove an existing selectedCalendar
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, selectedCalendar removed successfuly
|
||||
* model: SelectedCalendar
|
||||
* 400:
|
||||
* description: Bad request. SelectedCalendar id is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteSelectedCalendar(req: NextApiRequest, res: NextApiResponse<BaseResponse>) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query", safe.error);
|
||||
|
||||
export async function deleteSelectedCalendar(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "DELETE" && safe.success && safe.data) {
|
||||
const selectedCalendar = await prisma.selectedCalendar.delete({ where: { id: safe.data.id } });
|
||||
// We only remove the selectedCalendar type from the database if there's an existing resource.
|
||||
if (selectedCalendar)
|
||||
res.status(200).json({ message: `selectedCalendar with id: ${safe.data.id} deleted successfully` });
|
||||
// This catches the error thrown by prisma.selectedCalendar.delete() if the resource is not found.
|
||||
else res.status(400).json({ message: `Resource with id:${safe.data.id} was not found` });
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only DELETE Method allowed" });
|
||||
const data = await prisma.selectedCalendar.delete({ where: { id: safe.data.id } });
|
||||
|
||||
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 withValidQueryIdTransformParseInt(deleteSelectedCalendar);
|
||||
export default withMiddleware("HTTP_DELETE")(withValidQueryIdTransformParseInt(deleteSelectedCalendar));
|
||||
|
|
|
@ -1,38 +1,56 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { SelectedCalendar } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaSelectedCalendar, withValidSelectedCalendar } from "@lib/validations/selected-calendar";
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { SelectedCalendarResponse } from "@lib/types";
|
||||
import {
|
||||
schemaSelectedCalendarBodyParams,
|
||||
schemaSelectedCalendarPublic,
|
||||
withValidSelectedCalendar,
|
||||
} from "@lib/validations/selected-calendar";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: SelectedCalendar;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
/**
|
||||
* @swagger
|
||||
* /api/selectedCalendars/:id/edit:
|
||||
* patch:
|
||||
* description: Edits an existing selectedCalendar
|
||||
* 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<SelectedCalendarResponse>
|
||||
) {
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
const safeBody = await schemaSelectedCalendarBodyParams.safeParse(req.body);
|
||||
|
||||
export async function editSelectedCalendar(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaSelectedCalendar.safeParse(body);
|
||||
if (!safeQuery.success || !safeBody.success) throw new Error("Invalid request");
|
||||
const selectedCalendar = await prisma.selectedCalendar.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
});
|
||||
const data = schemaSelectedCalendarPublic.parse(selectedCalendar);
|
||||
|
||||
if (method === "PATCH" && safeQuery.success && safeBody.success) {
|
||||
const data = await prisma.selectedCalendar.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
});
|
||||
if (data) res.status(200).json({ data });
|
||||
else
|
||||
res
|
||||
.status(404)
|
||||
.json({ message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, error });
|
||||
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only PATCH Method allowed for updating selectedCalendars" });
|
||||
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 withValidQueryIdTransformParseInt(withValidSelectedCalendar(editSelectedCalendar));
|
||||
export default withMiddleware("HTTP_PATCH")(
|
||||
withValidQueryIdTransformParseInt(withValidSelectedCalendar(editSelectedCalendar))
|
||||
);
|
||||
|
|
|
@ -1,29 +1,45 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { SelectedCalendar } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { SelectedCalendarResponse } from "@lib/types";
|
||||
import { schemaSelectedCalendarPublic } from "@lib/validations/selected-calendar";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: SelectedCalendar;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
/**
|
||||
* @swagger
|
||||
* /api/selectedCalendars/:id:
|
||||
* get:
|
||||
* description: find selectedCalendar by ID
|
||||
* 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<SelectedCalendarResponse>
|
||||
) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query");
|
||||
|
||||
export async function selectedCalendar(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "GET" && safe.success) {
|
||||
const data = await prisma.selectedCalendar.findUnique({ where: { id: safe.data.id } });
|
||||
const selectedCalendar = await prisma.selectedCalendar.findUnique({ where: { id: safe.data.id } });
|
||||
const data = schemaSelectedCalendarPublic.parse(selectedCalendar);
|
||||
|
||||
if (data) res.status(200).json({ data });
|
||||
else res.status(404).json({ message: "Event type not found" });
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only GET Method allowed" });
|
||||
if (selectedCalendar) res.status(200).json({ data });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(404).json({
|
||||
message: "SelectedCalendar was not found",
|
||||
error,
|
||||
});
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(selectedCalendar);
|
||||
export default withMiddleware("HTTP_GET")(withValidQueryIdTransformParseInt(selectedCalendarById));
|
||||
|
|
|
@ -1,15 +1,37 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { SelectedCalendar } from "@calcom/prisma/client";
|
||||
|
||||
type ResponseData = {
|
||||
data?: SelectedCalendar[];
|
||||
error?: unknown;
|
||||
};
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { SelectedCalendarsResponse } from "@lib/types";
|
||||
import { schemaSelectedCalendarPublic } from "@lib/validations/selected-calendar";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/selectedCalendars:
|
||||
* get:
|
||||
* description: Returns all selected calendars
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: No selectedCalendars were found
|
||||
*/
|
||||
async function allSelectedCalendars(_: NextApiRequest, res: NextApiResponse<SelectedCalendarsResponse>) {
|
||||
const selectedCalendars = await prisma.selectedCalendar.findMany();
|
||||
const data = selectedCalendars.map((selectedCalendar) =>
|
||||
schemaSelectedCalendarPublic.parse(selectedCalendar)
|
||||
);
|
||||
|
||||
export default async function selectedCalendar(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const data = await prisma.selectedCalendar.findMany();
|
||||
if (data) res.status(200).json({ data });
|
||||
else res.status(400).json({ error: "No data found" });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(404).json({
|
||||
message: "No SelectedCalendars were found",
|
||||
error,
|
||||
});
|
||||
}
|
||||
|
||||
export default withMiddleware("HTTP_GET")(allSelectedCalendars);
|
||||
|
|
|
@ -1,28 +1,43 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { SelectedCalendar } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaSelectedCalendar, withValidSelectedCalendar } from "@lib/validations/selected-calendar";
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { SelectedCalendarResponse } from "@lib/types";
|
||||
import {
|
||||
schemaSelectedCalendarBodyParams,
|
||||
schemaSelectedCalendarPublic,
|
||||
withValidSelectedCalendar,
|
||||
} from "@lib/validations/selected-calendar";
|
||||
|
||||
type ResponseData = {
|
||||
data?: SelectedCalendar;
|
||||
message?: string;
|
||||
error?: string;
|
||||
};
|
||||
/**
|
||||
* @swagger
|
||||
* /api/selectedCalendars/new:
|
||||
* post:
|
||||
* description: Creates a new selected calendar
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, selected calendar created
|
||||
* model: SelectedCalendar
|
||||
* 400:
|
||||
* description: Bad request. SelectedCalendar body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function createSelectedCalendar(req: NextApiRequest, res: NextApiResponse<SelectedCalendarResponse>) {
|
||||
const safe = schemaSelectedCalendarBodyParams.safeParse(req.body);
|
||||
if (!safe.success) throw new Error("Invalid request body", safe.error);
|
||||
|
||||
async function createSelectedCalendar(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { body, method } = req;
|
||||
const safe = schemaSelectedCalendar.safeParse(body);
|
||||
if (method === "POST" && safe.success) {
|
||||
await prisma.selectedCalendar
|
||||
.create({ data: safe.data })
|
||||
.then((data) => res.status(201).json({ data }))
|
||||
.catch((error) =>
|
||||
res.status(400).json({ message: "Could not create selectedCalendar type", error: error })
|
||||
);
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ error: "Only POST Method allowed" });
|
||||
const selectedCalendar = await prisma.selectedCalendar.create({ data: safe.data });
|
||||
const data = schemaSelectedCalendarPublic.parse(selectedCalendar);
|
||||
|
||||
if (data) res.status(201).json({ data, message: "SelectedCalendar created successfully" });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
message: "Could not create new selectedCalendar",
|
||||
error,
|
||||
});
|
||||
}
|
||||
|
||||
export default withValidSelectedCalendar(createSelectedCalendar);
|
||||
export default withMiddleware("HTTP_POST")(withValidSelectedCalendar(createSelectedCalendar));
|
||||
|
|
|
@ -3,19 +3,29 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
|||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { BaseResponse } from "@lib/types";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
message: string;
|
||||
error?: object;
|
||||
};
|
||||
|
||||
export async function deleteTeam(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
/**
|
||||
* @swagger
|
||||
* /api/teams/:id/delete:
|
||||
* delete:
|
||||
* description: Remove an existing team
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, team removed successfuly
|
||||
* model: Team
|
||||
* 400:
|
||||
* description: Bad request. Team id is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteTeam(req: NextApiRequest, res: NextApiResponse<BaseResponse>) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query");
|
||||
if (!safe.success) throw new Error("Invalid request query", safe.error);
|
||||
|
||||
const data = await prisma.team.delete({ where: { id: safe.data.id } });
|
||||
|
||||
|
@ -28,4 +38,4 @@ export async function deleteTeam(req: NextApiRequest, res: NextApiResponse<Respo
|
|||
});
|
||||
}
|
||||
|
||||
export default withMiddleware("HTTP_DELETE", "addRequestId")(withValidQueryIdTransformParseInt(deleteTeam));
|
||||
export default withMiddleware("HTTP_DELETE")(withValidQueryIdTransformParseInt(deleteTeam));
|
||||
|
|
|
@ -1,30 +1,39 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { TeamResponse } from "@lib/types";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaTeam, withValidTeam } from "@lib/validations/team";
|
||||
import { schemaTeamBodyParams, schemaTeamPublic, withValidTeam } from "@lib/validations/team";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team;
|
||||
message?: string;
|
||||
error?: object;
|
||||
};
|
||||
|
||||
export async function editTeam(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
/**
|
||||
* @swagger
|
||||
* /api/teams/:id/edit:
|
||||
* patch:
|
||||
* description: Edits an existing team
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, team edited successfuly
|
||||
* model: Team
|
||||
* 400:
|
||||
* description: Bad request. Team body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function editTeam(req: NextApiRequest, res: NextApiResponse<TeamResponse>) {
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
const safeBody = await schemaTeam.safeParse(req.body);
|
||||
const safeBody = await schemaTeamBodyParams.safeParse(req.body);
|
||||
|
||||
if (!safeQuery.success || !safeBody.success) throw new Error("Invalid request");
|
||||
const data = await prisma.team.update({
|
||||
const team = await prisma.team.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
});
|
||||
const data = schemaTeamPublic.parse(team);
|
||||
|
||||
if (data) res.status(200).json({ data });
|
||||
else
|
||||
|
@ -35,7 +44,4 @@ export async function editTeam(req: NextApiRequest, res: NextApiResponse<Respons
|
|||
});
|
||||
}
|
||||
|
||||
export default withMiddleware(
|
||||
"HTTP_PATCH",
|
||||
"addRequestId"
|
||||
)(withValidQueryIdTransformParseInt(withValidTeam(editTeam)));
|
||||
export default withMiddleware("HTTP_PATCH")(withValidQueryIdTransformParseInt(withValidTeam(editTeam)));
|
||||
|
|
|
@ -1,27 +1,36 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { TeamResponse } from "@lib/types";
|
||||
import {
|
||||
schemaQueryIdParseInt,
|
||||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaTeamPublic } from "@lib/validations/team";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team;
|
||||
message?: string;
|
||||
error?: object;
|
||||
};
|
||||
|
||||
export async function teamById(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
/**
|
||||
* @swagger
|
||||
* /api/teams/:id:
|
||||
* get:
|
||||
* description: find team by ID
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: Team was not found
|
||||
*/
|
||||
export async function teamById(req: NextApiRequest, res: NextApiResponse<TeamResponse>) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query");
|
||||
|
||||
const data = await prisma.team.findUnique({ where: { id: safe.data.id } });
|
||||
const team = await prisma.team.findUnique({ where: { id: safe.data.id } });
|
||||
const data = schemaTeamPublic.parse(team);
|
||||
|
||||
if (data) res.status(200).json({ data });
|
||||
if (team) res.status(200).json({ data });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(404).json({
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { TeamsResponse } from "@lib/types";
|
||||
import { schemaTeamPublic } from "@lib/validations/team";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team[];
|
||||
message?: string;
|
||||
error?: object;
|
||||
};
|
||||
|
||||
async function allTeams(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const data = await prisma.team.findMany();
|
||||
/**
|
||||
* @swagger
|
||||
* /api/teams:
|
||||
* get:
|
||||
* description: Returns all teams
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: No teams were found
|
||||
*/
|
||||
async function allTeams(_: NextApiRequest, res: NextApiResponse<TeamsResponse>) {
|
||||
const teams = await prisma.team.findMany();
|
||||
const data = teams.map((team) => schemaTeamPublic.parse(team));
|
||||
|
||||
if (data) res.status(200).json({ data });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
res.status(404).json({
|
||||
message: "No Teams were found",
|
||||
error,
|
||||
});
|
||||
|
|
|
@ -1,31 +1,39 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { schemaTeam, withValidTeam } from "@lib/validations/team";
|
||||
import type { TeamResponse } from "@lib/types";
|
||||
import { schemaTeamBodyParams, schemaTeamPublic, withValidTeam } from "@lib/validations/team";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team;
|
||||
error?: object;
|
||||
};
|
||||
/**
|
||||
* @swagger
|
||||
* /api/teams/new:
|
||||
* post:
|
||||
* description: Creates a new team
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, team created
|
||||
* model: Team
|
||||
* 400:
|
||||
* description: Bad request. Team body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function createTeam(req: NextApiRequest, res: NextApiResponse<TeamResponse>) {
|
||||
const safe = schemaTeamBodyParams.safeParse(req.body);
|
||||
if (!safe.success) throw new Error("Invalid request body", safe.error);
|
||||
|
||||
async function createTeam(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const safe = schemaTeam.safeParse(req.body);
|
||||
if (!safe.success) throw new Error("Invalid request body");
|
||||
const team = await prisma.team.create({ data: safe.data });
|
||||
const data = schemaTeamPublic.parse(team);
|
||||
|
||||
const data = await prisma.team.create({ data: safe.data });
|
||||
|
||||
if (data) res.status(201).json({ data });
|
||||
if (data) res.status(201).json({ data, message: "Team created successfully" });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
error: {
|
||||
message: "Could not create new team",
|
||||
error,
|
||||
},
|
||||
message: "Could not create new team",
|
||||
error,
|
||||
});
|
||||
}
|
||||
|
||||
export default withMiddleware("addRequestId", "HTTP_POST")(withValidTeam(createTeam));
|
||||
export default withMiddleware("HTTP_POST")(withValidTeam(createTeam));
|
||||
|
|
|
@ -9,6 +9,20 @@ import {
|
|||
withValidQueryIdTransformParseInt,
|
||||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/users/:id/delete:
|
||||
* delete:
|
||||
* description: Remove an existing user
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, user removed successfuly
|
||||
* model: User
|
||||
* 400:
|
||||
* description: Bad request. User id is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteUser(req: NextApiRequest, res: NextApiResponse<BaseResponse>) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query", safe.error);
|
||||
|
|
|
@ -10,6 +10,20 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaUserBodyParams, schemaUserPublic, withValidUser } from "@lib/validations/user";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/users/:id/edit:
|
||||
* patch:
|
||||
* description: Edits an existing user
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, user edited successfuly
|
||||
* model: User
|
||||
* 400:
|
||||
* description: Bad request. User body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function editUser(req: NextApiRequest, res: NextApiResponse<UserResponse>) {
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
const safeBody = await schemaUserBodyParams.safeParse(req.body);
|
||||
|
|
|
@ -10,6 +10,19 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaUserPublic } from "@lib/validations/user";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/users/:id:
|
||||
* get:
|
||||
* description: find user by ID
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: User was not found
|
||||
*/
|
||||
export async function userById(req: NextApiRequest, res: NextApiResponse<UserResponse>) {
|
||||
const safe = await schemaQueryIdParseInt.safeParse(req.query);
|
||||
if (!safe.success) throw new Error("Invalid request query");
|
||||
|
|
|
@ -6,6 +6,19 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
|
|||
import { UsersResponse } from "@lib/types";
|
||||
import { schemaUserPublic } from "@lib/validations/user";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/users:
|
||||
* get:
|
||||
* description: Returns all users
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 404:
|
||||
* description: No users were found
|
||||
*/
|
||||
async function allUsers(_: NextApiRequest, res: NextApiResponse<UsersResponse>) {
|
||||
const users = await prisma.user.findMany();
|
||||
const data = users.map((user) => schemaUserPublic.parse(user));
|
||||
|
@ -13,7 +26,7 @@ async function allUsers(_: NextApiRequest, res: NextApiResponse<UsersResponse>)
|
|||
if (data) res.status(200).json({ data });
|
||||
else
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
res.status(404).json({
|
||||
message: "No Users were found",
|
||||
error,
|
||||
});
|
||||
|
|
|
@ -6,6 +6,20 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
|
|||
import type { UserResponse } from "@lib/types";
|
||||
import { schemaUserBodyParams, schemaUserPublic, withValidUser } from "@lib/validations/user";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/users/new:
|
||||
* post:
|
||||
* description: Creates a new user
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, user created
|
||||
* model: User
|
||||
* 400:
|
||||
* description: Bad request. User body is invalid.
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function createUser(req: NextApiRequest, res: NextApiResponse<UserResponse>) {
|
||||
const safe = schemaUserBodyParams.safeParse(req.body);
|
||||
if (!safe.success) throw new Error("Invalid request body", safe.error);
|
||||
|
|
Loading…
Reference in New Issue