Merge pull request #63 from calcom/fix-openapi-spec

docs: improve open api spec, fixing all issues, removes json-schema / models
This commit is contained in:
Agusti Fernandez Pardo authored and GitHub committed 2022-04-30 20:58:43 +02:00
commit 167a42156d
42 files changed
+1386 -2603

No files matched your search

+2 -4
View File
@@ -108,8 +108,6 @@ We have some shared validations which several resources require, like baseApiPar
- **[*]BodyParams** which merges both `[*]BaseBodyParams.merge([*]RequiredParams);`
- **withValid[*]** which is currently not being much used because is only useful in only post endpoints (we do post/get all in same file). This would validate the req.body of a POST call to API against our BaseBodyParams validation
### Next Validations
[Next-Validations Docs](https://next-validations.productsway.com/)
@@ -127,9 +125,9 @@ We aim to provide a fully tested API for our peace of mind, this is accomplished
| attendees | ✅ | ✅ | ✅ | ✅ | ✅ |
| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| daily-event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-type-custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-types | ✅ | ✅ | ✅ | ✅ | ✅ |
| memberships | ✅ | ✅ | ✅ | ✅ | ✅ |
| payments | ✅ | ✅ | ❌ | ❌ | ❌ |
File diff suppressed because it is too large. Load diff
+10 -8
View File
@@ -8,6 +8,8 @@ import prisma from "@calcom/prisma";
declare module "next" {
export interface NextApiRequest extends IncomingMessage {
userId: number;
body: any;
query: { [key: string]: string | string[] };
}
}
@@ -20,21 +22,21 @@ export const dateNotInPast = function (date: Date) {
};
// This verifies the apiKey and sets the user if it is valid.
export const verifyApiKey: NextMiddleware = async (req, res, next) => {
if (!req.query.apiKey) return res.status(401).json({ message: "No apiKey provided" });
export const verifyApiKey: NextMiddleware = async ({ query: { apiKey }, ...req }, res, next) => {
if (!apiKey) return res.status(401).json({ message: "No apiKey provided" });
// We remove the prefix from the user provided api_key. If no env set default to "cal_"
const strippedApiKey = `${req.query.apiKey}`.replace(process.env.API_KEY_PREFIX || "cal_", "");
const strippedApiKey = `${apiKey}`.replace(process.env.API_KEY_PREFIX || " cal_", "");
// Hash the key again before matching against the database records.
const hashedKey = hashAPIKey(strippedApiKey);
// Check if the hashed api key exists in database.
const apiKey = await prisma.apiKey.findUnique({ where: { hashedKey } });
const validApiKey = await prisma.apiKey.findUnique({ where: { hashedKey } });
// If we cannot find any api key. Throw a 401 Unauthorized.
if (!apiKey) return res.status(401).json({ error: "Your apiKey is not valid" });
if (apiKey.expiresAt && dateNotInPast(apiKey.expiresAt)) {
if (!validApiKey) return res.status(401).json({ error: "Your apiKey is not valid" });
if (validApiKey.expiresAt && dateNotInPast(validApiKey.expiresAt)) {
return res.status(401).json({ error: "This apiKey is expired" });
}
if (!apiKey.userId) return res.status(404).json({ error: "No user found for this apiKey" });
if (!validApiKey.userId) return res.status(404).json({ error: "No user found for this apiKey" });
/* We save the user id in the request for later use */
req.userId = apiKey.userId;
req.userId = validApiKey.userId;
await next();
};
+3 -7
View File
@@ -1,5 +1,3 @@
// https://www.npmjs.com/package/next-transpile-modules
// This makes our @calcom/prisma package from the monorepo to be transpiled and usable by API
const withTM = require("next-transpile-modules")([
"@calcom/app-store",
"@calcom/prisma",
@@ -7,13 +5,11 @@ const withTM = require("next-transpile-modules")([
"@calcom/ee",
]);
// use something like withPlugins([withTM], {}) if more plugins added later.
module.exports = withTM({
async headers() {
return [
{
// matching all API routes
// @note: disabling CORS matching all API routes as this will be a our Public API
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
@@ -30,12 +26,12 @@ module.exports = withTM({
},
async rewrites() {
return [
// This redirects requests recieved at / the root to the /api/ folder.
// @note: redirects requests from: "/:rest*" the root level to the "/api/:rest*" folder by default.
{
source: "/:rest*",
destination: "/api/:rest*",
},
// This redirects requests to api/v*/ to /api/ passing version as a query parameter.
// @note: redirects requests from api/v*/:rest to /api/:rest?version=* passing version as a query parameter.
{
source: "/api/v:version/:rest*",
destination: "/api/:rest*?version=:version",
+1
View File
@@ -26,6 +26,7 @@
"dependencies": {
"@calcom/prisma": "*",
"@sentry/nextjs": "^6.19.3",
"modify-response-middleware": "^1.1.0",
"next": "^12.1.4",
"next-api-middleware": "^1.0.1",
"next-swagger-doc": "^0.2.1",
+110 -104
View File
@@ -10,115 +10,56 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /attendees/{id}:
* get:
* summary: Find an attendee by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the attendee to get
* example: 3
* security:
* - ApiKeyAuth: []
* tags:
* - attendees
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Attendee was not found
* patch:
* summary: Edit an existing attendee
* consumes:
* - application/json
* requestBody:
* description: Edit an existing attendee related to one of your bookings
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - bookingId
* - name
* - email
* - timeZone
* properties:
* email:
* type: string
* example: email@example.com
* name:
* type: string
* example: John Doe
* timeZone:
* type: string
* example: Europe/London
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* example: 3
* required: true
* description: Numeric ID of the attendee to edit
* security:
* - ApiKeyAuth: []
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee edited successfuly
* model: Attendee
* 400:
* description: Bad request. Attendee body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing attendee
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the attendee to delete
* security:
* - ApiKeyAuth: []
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee removed successfuly
* model: Attendee
* 400:
* description: Bad request. Attendee id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function attendeeById(req: NextApiRequest, res: NextApiResponse<AttendeeResponse>) {
const { method, query, body, userId } = req;
export async function attendeeById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<AttendeeResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
if (!safeQuery.success) {
res.status(400).json({ error: safeQuery.error });
throw new Error("Invalid request query", safeQuery.error);
}
const userBookings = await prisma.booking.findMany({
where: { userId },
include: { attendees: true },
});
const attendees = userBookings.map((booking) => booking.attendees).flat();
const attendeeIds = attendees.map((attendee) => attendee.id);
// Here we make sure to only return attendee's of the user's own bookings.
if (!attendeeIds.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
const userBookingsAttendeeIds = await prisma.booking
// Find all user bookings, including attendees
.findMany({
where: { userId },
include: { attendees: true },
})
.then(
// Flatten and merge all the attendees in one array
(bookings) =>
bookings
.map((bookings) => bookings.attendees)
.flat()
.map((attendee) => attendee.id)
);
// @note: Here we make sure to only return attendee's of the user's own bookings.
if (!userBookingsAttendeeIds.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /attendees/{id}:
* get:
* summary: Find an attendee
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the attendee to get
* example: 3
* tags:
* - attendees
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Attendee was not found
*/
case "GET":
await prisma.attendee
.findUnique({ where: { id: safeQuery.data.id } })
@@ -131,7 +72,51 @@ export async function attendeeById(req: NextApiRequest, res: NextApiResponse<Att
})
);
break;
/**
* @swagger
* /attendees/{id}:
* patch:
* summary: Edit an existing attendee
* requestBody:
* description: Edit an existing attendee related to one of your bookings
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - bookingId
* - name
* - email
* - timeZone
* properties:
* email:
* type: string
* example: email@example.com
* name:
* type: string
* example: John Doe
* timeZone:
* type: string
* example: Europe/London
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* example: 3
* required: true
* description: Numeric ID of the attendee to edit
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee edited successfuly
* 400:
* description: Bad request. Attendee body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
const safeBody = schemaAttendeeEditBodyParams.safeParse(body);
if (!safeBody.success) {
@@ -149,7 +134,28 @@ export async function attendeeById(req: NextApiRequest, res: NextApiResponse<Att
})
);
break;
/**
* @swagger
* /attendees/{id}:
* delete:
* summary: Remove an existing attendee
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the attendee to delete
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee removed successfuly
* 400:
* description: Bad request. Attendee id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.attendee
.delete({ where: { id: safeQuery.data.id } })
+58 -65
View File
@@ -6,70 +6,10 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { AttendeeResponse, AttendeesResponse } from "@lib/types";
import { schemaAttendeeCreateBodyParams, schemaAttendeeReadPublic } from "@lib/validations/attendee";
/**
* @swagger
* /attendees:
* get:
* summary: Find all attendees
* security:
* - ApiKeyAuth: []
* tags:
* - attendees
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No attendees were found
* post:
* summary: Creates a new attendee
* security:
* - ApiKeyAuth: []
* consumes:
* - application/json
* requestBody:
* description: Create a new attendee related to one of your bookings
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - bookingId
* - name
* - email
* - timeZone
* properties:
* bookingId:
* type: number
* example: 1
* email:
* type: string
* example: email@example.com
* name:
* type: string
* example: John Doe
* timeZone:
* type: string
* example: Europe/London
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee created
* model: Attendee
* 400:
* description: Bad request. Attendee body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllAttendees(
req: NextApiRequest,
{ method, userId, body }: NextApiRequest,
res: NextApiResponse<AttendeesResponse | AttendeeResponse>
) {
const { method, userId } = req;
// Here we make sure to only return attendee's of the user's own bookings.
const userBookings = await prisma.booking.findMany({
where: {
userId,
@@ -80,6 +20,21 @@ async function createOrlistAllAttendees(
});
const attendees = userBookings.map((booking) => booking.attendees).flat();
if (method === "GET") {
/**
* @swagger
* /attendees:
* get:
* summary: Find all attendees
* tags:
* - attendees
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No attendees were found
*/
if (attendees) res.status(200).json({ attendees });
else
(error: Error) =>
@@ -88,13 +43,51 @@ async function createOrlistAllAttendees(
error,
});
} else if (method === "POST") {
const safePost = schemaAttendeeCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /attendees:
* post:
* summary: Creates a new attendee
* requestBody:
* description: Create a new attendee related to one of your bookings
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - bookingId
* - name
* - email
* - timeZone
* properties:
* bookingId:
* type: number
* example: 1
* email:
* type: string
* example: email@example.com
* name:
* type: string
* example: John Doe
* timeZone:
* type: string
* example: Europe/London
* tags:
* - attendees
* responses:
* 201:
* description: OK, attendee created
* 400:
* description: Bad request. Attendee body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safePost = schemaAttendeeCreateBodyParams.safeParse(body);
if (!safePost.success) {
console.log(safePost.error);
res.status(400).json({ error: safePost.error });
throw new Error("Invalid request body", safePost.error);
}
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
@@ -102,7 +95,7 @@ async function createOrlistAllAttendees(
if (!userWithBookings) {
throw new Error("User not found");
}
const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat();
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
// Here we make sure to only return attendee's of the user's own bookings.
if (!userBookingIds.includes(safePost.data.bookingId)) res.status(401).json({ message: "Unauthorized" });
else {
+76 -87
View File
@@ -13,97 +13,41 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /availabilities/{id}:
* get:
* summary: Find an availability by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to get
* security:
* - ApiKeyAuth: []
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Availability was not found
* patch:
* summary: Edit an existing availability
* consumes:
* - application/json
* parameters:
* - in: body
* name: availability
* description: The availability to edit
* schema:
* type: object
* $ref: '#/components/schemas/Availability'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to edit
* security:
* - ApiKeyAuth: []
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability edited successfuly
* model: Availability
* 400:
* description: Bad request. Availability body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing availability
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to delete
* security:
* - ApiKeyAuth: []
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability removed successfuly
* model: Availability
* 400:
* description: Bad request. Availability id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function availabilityById(req: NextApiRequest, res: NextApiResponse<AvailabilityResponse>) {
const { method, query, body } = req;
export async function availabilityById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<AvailabilityResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const data = await prisma.availability.findMany({ where: { userId } });
const availabiltiesIds = data.map((availability) => availability.id);
if (!availabiltiesIds.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /availabilities/{id}:
* get:
* summary: Find an availability
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to get
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Availability was not found
*/
case "GET":
await prisma.availability
.findUnique({ where: { id: safeQuery.data.id } })
@@ -113,7 +57,30 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse
res.status(404).json({ message: `Availability with id: ${safeQuery.data.id} not found`, error })
);
break;
/**
* @swagger
* /availabilities/{id}:
* patch:
* summary: Edit an existing availability
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to edit
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability edited successfuly
* 400:
* description: Bad request. Availability body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
const safeBody = schemaAvailabilityEditBodyParams.safeParse(body);
if (!safeBody.success) throw new Error("Invalid request body");
@@ -132,14 +99,36 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse
.then((data) => schemaAvailabilityReadPublic.parse(data))
.then((availability) => res.status(200).json({ availability }))
.catch((error: Error) => {
console.log(error);
res.status(404).json({
message: `Availability with id: ${safeQuery.data.id} not found`,
error,
});
});
break;
/**
* @swagger
* /availabilities/{id}:
* delete:
* summary: Remove an existing availability
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the availability to delete
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability removed successfuly
* 400:
* description: Bad request. Availability id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.availability
.delete({ where: { id: safeQuery.data.id } })
+36 -41
View File
@@ -9,49 +9,28 @@ import {
schemaAvailabilityReadPublic,
} from "@lib/validations/availability";
/**
* @swagger
* /availabilities:
* get:
* summary: Find all availabilities
* security:
* - ApiKeyAuth: []
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No availabilities were found
* post:
* summary: Creates a new availability
* security:
* - ApiKeyAuth: []
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability created
* model: Availability
* 400:
* description: Bad request. Availability body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllAvailabilities(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<AvailabilitiesResponse | AvailabilityResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /availabilities:
* get:
* summary: Find all availabilities
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No availabilities were found
*/
const data = await prisma.availability.findMany({ where: { userId } });
const availabilities = data.map((availability) => schemaAvailabilityReadPublic.parse(availability));
if (availabilities) res.status(200).json({ availabilities });
@@ -62,11 +41,27 @@ async function createOrlistAllAvailabilities(
error,
});
} else if (method === "POST") {
const safe = schemaAvailabilityCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /availabilities:
* post:
* summary: Creates a new availability
* tags:
* - availabilities
* externalDocs:
* url: https://docs.cal.com/availability
* responses:
* 201:
* description: OK, availability created
* 400:
* description: Bad request. Availability body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaAvailabilityCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.availability.create({ data: { ...safe.data, userId } });
console.log(data);
const availability = schemaAvailabilityReadPublic.parse(data);
if (availability) res.status(201).json({ availability, message: "Availability created successfully" });
+72 -83
View File
@@ -14,100 +14,46 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /booking-references/{id}:
* get:
* summary: Find a booking reference by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to get
* security:
* - ApiKeyAuth: []
* tags:
* - booking-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: BookingReference was not found
* patch:
* summary: Edit an existing booking reference
* consumes:
* - application/json
* parameters:
* - in: body
* name: bookingReference
* description: The bookingReference to edit
* schema:
* type: object
* $ref: '#/components/schemas/BookingReference'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to edit
* security:
* - ApiKeyAuth: []
* tags:
* - booking-references
* responses:
* 201:
* description: OK, bookingReference edited successfuly
* model: BookingReference
* 400:
* description: Bad request. BookingReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing booking reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to delete
* security:
* - ApiKeyAuth: []
* tags:
* - booking-references
* responses:
* 201:
* description: OK, bookingReference removed successfuly
* model: BookingReference
* 400:
* description: Bad request. BookingReference id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function bookingReferenceById(
req: NextApiRequest,
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<BookingReferenceResponse>
) {
const { method, query, body } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
});
if (!userWithBookings) throw new Error("User not found");
const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat();
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
const bookingReference = await prisma.bookingReference.findUnique({ where: { id: safeQuery.data.id } });
if (!bookingReference) throw new Error("BookingReference not found");
if (!bookingReference?.bookingId) throw new Error("BookingReference: bookingId not found");
if (userBookingIds.includes(bookingReference.bookingId)) {
switch (method) {
case "GET":
/**
* @swagger
* /booking-references/{id}:
* get:
* summary: Find a booking reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to get
* tags:
* - booking-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: BookingReference was not found
*/
await prisma.bookingReference
.findUnique({ where: { id: safeQuery.data.id } })
.then((data) => schemaBookingReferenceReadPublic.parse(data))
@@ -118,11 +64,33 @@ export async function bookingReferenceById(
error,
})
);
break;
case "PATCH":
const safeBody = schemaBookingEditBodyParams.safeParse(body);
/**
* @swagger
* /booking-references/{id}:
* patch:
* summary: Edit an existing booking reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to edit
* tags:
* - booking-references
* responses:
* 201:
* description: OK, bookingReference edited successfuly
* 400:
* description: Bad request. BookingReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safeBody = schemaBookingEditBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
}
@@ -137,7 +105,28 @@ export async function bookingReferenceById(
})
);
break;
/**
* @swagger
* /booking-references/{id}:
* delete:
* summary: Remove an existing booking reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking reference to delete
* tags:
* - booking-references
* responses:
* 201:
* description: OK, bookingReference removed successfuly
* 400:
* description: Bad request. BookingReference id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.bookingReference
.delete({
+35 -39
View File
@@ -9,50 +9,32 @@ import {
schemaBookingReferenceReadPublic,
} from "@lib/validations/booking-reference";
/**
* @swagger
* /booking-references:
* get:
* summary: Find all booking references
* security:
* - ApiKeyAuth: []
* tags:
* - booking-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No booking references were found
* post:
* summary: Creates a new booking reference
* security:
* - ApiKeyAuth: []
* tags:
* - booking-references
* responses:
* 201:
* description: OK, booking reference created
* model: BookingReference
* 400:
* description: Bad request. BookingReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllBookingReferences(
req: NextApiRequest,
{ method, userId, body }: NextApiRequest,
res: NextApiResponse<BookingReferencesResponse | BookingReferenceResponse>
) {
const { method } = req;
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
});
if (!userWithBookings) throw new Error("User not found");
const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat();
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
if (method === "GET") {
/**
* @swagger
* /booking-references:
* get:
* summary: Find all booking references
* tags:
* - booking-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No booking references were found
*/
const data = await prisma.bookingReference.findMany({ where: { id: { in: userBookingIds } } });
const booking_references = data.map((bookingReference) =>
schemaBookingReferenceReadPublic.parse(bookingReference)
@@ -65,13 +47,26 @@ async function createOrlistAllBookingReferences(
error,
});
} else if (method === "POST") {
const safe = schemaBookingCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /booking-references:
* post:
* summary: Creates a new booking reference
* tags:
* - booking-references
* responses:
* 201:
* description: OK, booking reference created
* 400:
* description: Bad request. BookingReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaBookingCreateBodyParams.safeParse(body);
if (!safe.success) {
throw new Error("Invalid request body");
}
// const booking_reference = schemaBookingReferencePublic.parse(data);
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
@@ -79,7 +74,8 @@ async function createOrlistAllBookingReferences(
if (!userWithBookings) {
throw new Error("User not found");
}
const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat();
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
if (!safe.data.bookingId) throw new Error("BookingReference: bookingId not found");
if (!userBookingIds.includes(safe.data.bookingId)) res.status(401).json({ message: "Unauthorized" });
else {
const booking_reference = await prisma.bookingReference.create({
+71 -82
View File
@@ -10,95 +10,43 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /bookings/{id}:
* get:
* summary: Find a booking by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to get
* security:
* - ApiKeyAuth: []
* tags:
* - bookings
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Booking was not found
* patch:
* summary: Edit an existing booking
* consumes:
* - application/json
* parameters:
* - in: body
* name: booking
* description: The booking to edit
* schema:
* type: object
* $ref: '#/components/schemas/Booking'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to edit
* security:
* - ApiKeyAuth: []
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking edited successfuly
* model: Booking
* 400:
* description: Bad request. Booking body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing booking
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to delete
* security:
* - ApiKeyAuth: []
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking removed successfuly
* model: Booking
* 400:
* description: Bad request. Booking id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function bookingById(req: NextApiRequest, res: NextApiResponse<BookingResponse>) {
const { method, query, body } = req;
export async function bookingById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<BookingResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
});
if (!userWithBookings) throw new Error("User not found");
const userBookingIds = userWithBookings.bookings.map((booking: any) => booking.id).flat();
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
if (!userBookingIds.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /bookings/{id}:
* get:
* summary: Find a booking
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to get
* tags:
* - bookings
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Booking was not found
*/
case "GET":
await prisma.booking
.findUnique({ where: { id: safeQuery.data.id } })
@@ -111,10 +59,30 @@ export async function bookingById(req: NextApiRequest, res: NextApiResponse<Book
})
);
break;
/**
* @swagger
* /bookings/{id}:
* patch:
* summary: Edit an existing booking
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to edit
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking edited successfuly
* 400:
* description: Bad request. Booking body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
const safeBody = schemaBookingEditBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
}
@@ -132,7 +100,28 @@ export async function bookingById(req: NextApiRequest, res: NextApiResponse<Book
})
);
break;
/**
* @swagger
* /bookings/{id}:
* delete:
* summary: Remove an existing booking
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the booking to delete
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking removed successfuly
* 400:
* description: Bad request. Booking id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.booking
.delete({ where: { id: safeQuery.data.id } })
+32 -36
View File
@@ -6,45 +6,26 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { BookingResponse, BookingsResponse } from "@lib/types";
import { schemaBookingCreateBodyParams, schemaBookingReadPublic } from "@lib/validations/booking";
/**
* @swagger
* /bookings:
* get:
* summary: Find all bookings
* security:
* - ApiKeyAuth: []
* tags:
* - bookings
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No bookings were found
* post:
* summary: Creates a new booking
* security:
* - ApiKeyAuth: []
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking created
* model: Booking
* 400:
* description: Bad request. Booking body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllBookings(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<BookingsResponse | BookingResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /bookings:
* get:
* summary: Find all bookings
* tags:
* - bookings
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No bookings were found
*/
const data = await prisma.booking.findMany({ where: { userId } });
const bookings = data.map((booking) => schemaBookingReadPublic.parse(booking));
if (bookings) res.status(200).json({ bookings });
@@ -55,7 +36,22 @@ async function createOrlistAllBookings(
error,
});
} else if (method === "POST") {
const safe = schemaBookingCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /bookings:
* post:
* summary: Creates a new booking
* tags:
* - bookings
* responses:
* 201:
* description: OK, booking created
* 400:
* description: Bad request. Booking body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaBookingCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.booking.create({ data: { ...safe.data, userId } });
@@ -15,9 +15,9 @@ import {
/**
* @swagger
* /event-type-custom-inputs/{id}:
* /custom-inputs/{id}:
* get:
* summary: Find a eventTypeCustomInput by ID
* summary: Find a eventTypeCustomInput
* parameters:
* - in: path
* name: id
@@ -25,45 +25,31 @@ import {
* type: integer
* required: true
* description: Numeric ID of the eventTypeCustomInput to get
* security:
* - ApiKeyAuth: []
* tags:
* - event-type-custom-inputs
* - custom-inputs
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* deCustomInputscription: EventType was not found
* description: EventType was not found
* patch:
* summary: Edit an existing eventTypeCustomInput
* consumes:
* - application/json
* parameters:
* - in: body
* name: eventTypeCustomInput
* description: The eventTypeCustomInput to edit
* schema:
* type: object
* $ref: '#/components/schemas/EventTypeCustomInput'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventTypeCustomInput to edit
* security:
* - ApiKeyAuth: []
* tags:
* - event-type-custom-inputs
* - custom-inputs
* responses:
* 201:
* description: OK, eventTypeCustomInput edited successfuly
* model: EventTypeCustomInput
* 400:
* desCustomInputcription: Bad request. EventType body is invalid.
* description: Bad request. EventType body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
@@ -75,25 +61,23 @@ import {
* type: integer
* required: true
* description: Numeric ID of the eventTypeCustomInput to delete
* security:
* - ApiKeyAuth: []
* tags:
* - event-type-custom-inputs
* - custom-inputs
* responses:
* 201:
* description: OK, eventTypeCustomInput removed successfuly
* model: EventTypeCustomInput
* 400:
* desCustomInputcription: Bad request. EventType id is invalid.
* description: Bad request. EventType id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function eventTypeById(req: NextApiRequest, res: NextApiResponse<EventTypeCustomInputResponse>) {
const { method, query, body } = req;
async function eventTypeById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<EventTypeCustomInputResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaEventTypeCustomInputBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const data = await prisma.eventType.findMany({ where: { userId } });
const userEventTypes = data.map((eventType) => eventType.id);
const userEventTypeCustomInputs = await prisma.eventTypeCustomInput.findMany({
@@ -9,47 +9,28 @@ import {
schemaEventTypeCustomInputPublic,
} from "@lib/validations/event-type-custom-input";
/**
* @swagger
* /event-type-custom-inputs:
* get:
* summary: Find all eventTypeCustomInputs
* security:
* - ApiKeyAuth: []
* tags:
* - event-type-custom-inputs
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No eventTypeCustomInputs were found
* post:
* summary: Creates a new eventTypeCustomInput
* security:
* - ApiKeyAuth: []
* tags:
* - event-type-custom-inputs
* responses:
* 201:
* description: OK, eventTypeCustomInput created
* model: EventTypeCustomInput
* 400:
* description: Bad request. EventTypeCustomInput body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllEventTypeCustomInputs(
req: NextApiRequest,
{ userId, method, body }: NextApiRequest,
res: NextApiResponse<EventTypeCustomInputsResponse | EventTypeCustomInputResponse>
) {
const { method } = req;
const userId = req.userId;
const data = await prisma.eventType.findMany({ where: { userId } });
const userEventTypes = data.map((eventType) => eventType.id);
const userEventTypes: number[] = data.map((eventType) => eventType.id);
if (method === "GET") {
/**
* @swagger
* /custom-inputs:
* get:
* summary: Find all eventTypeCustomInputs
* tags:
* - custom-inputs
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No eventTypeCustomInputs were found
*/
const data = await prisma.eventTypeCustomInput.findMany({ where: { eventType: userEventTypes } });
const event_type_custom_inputs = data.map((eventTypeCustomInput) =>
schemaEventTypeCustomInputPublic.parse(eventTypeCustomInput)
@@ -62,7 +43,22 @@ async function createOrlistAllEventTypeCustomInputs(
error,
});
} else if (method === "POST") {
const safe = schemaEventTypeCustomInputBodyParams.safeParse(req.body);
/**
* @swagger
* /custom-inputs:
* post:
* summary: Creates a new eventTypeCustomInput
* tags:
* - custom-inputs
* responses:
* 201:
* description: OK, eventTypeCustomInput created
* 400:
* description: Bad request. EventTypeCustomInput body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaEventTypeCustomInputBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
// 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
+103 -80
View File
@@ -13,90 +13,13 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /destination-calendars/{id}:
* get:
* summary: Find a destination calendar by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to get
* security:
* - ApiKeyAuth: []
* tags:
* - destination-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: DestinationCalendar was not found
* patch:
* summary: Edit an existing destination calendar
* consumes:
* - application/json
* parameters:
* - in: body
* name: destinationCalendar
* description: The destinationCalendar to edit
* schema:
* type: object
* $ref: '#/components/schemas/DestinationCalendar'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to edit
* security:
* - ApiKeyAuth: []
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar edited successfuly
* model: DestinationCalendar
* 400:
* description: Bad request. DestinationCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to delete
* security:
* - ApiKeyAuth: []
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar removed successfuly
* model: DestinationCalendar
* 400:
* description: Bad request. DestinationCalendar id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function destionationCalendarById(
req: NextApiRequest,
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<DestinationCalendarResponse>
) {
const { method, query, body } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaDestinationCalendarEditBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const data = await prisma.destinationCalendar.findMany({ where: { userId } });
const userDestinationCalendars = data.map((destinationCalendar) => destinationCalendar.id);
// FIXME: Should we also check ownership of bokingId and eventTypeId to avoid users cross-pollinating other users calendars.
@@ -104,6 +27,64 @@ export async function destionationCalendarById(
if (userDestinationCalendars.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /destination-calendars/{id}:
* get:
* summary: Find a destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to get
* tags:
* - destination-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: DestinationCalendar was not found
* patch:
* summary: Edit an existing destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to edit
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar edited successfuly
* 400:
* description: Bad request. DestinationCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to delete
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar removed successfuly
* 400:
* description: Bad request. DestinationCalendar id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "GET":
await prisma.destinationCalendar
.findUnique({ where: { id: safeQuery.data.id } })
@@ -116,7 +97,28 @@ export async function destionationCalendarById(
})
);
break;
/**
* @swagger
* /destination-calendars/{id}:
* patch:
* summary: Edit an existing destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to edit
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar edited successfuly
* 400:
* description: Bad request. DestinationCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
@@ -132,7 +134,28 @@ export async function destionationCalendarById(
})
);
break;
/**
* @swagger
* /destination-calendars/{id}:
* delete:
* summary: Remove an existing destination calendar
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the destination calendar to delete
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destinationCalendar removed successfuly
* 400:
* description: Bad request. DestinationCalendar id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.destinationCalendar
.delete({
+32 -36
View File
@@ -9,45 +9,26 @@ import {
schemaDestinationCalendarReadPublic,
} from "@lib/validations/destination-calendar";
/**
* @swagger
* /destination-calendars:
* get:
* summary: Find all destination calendars
* security:
* - ApiKeyAuth: []
* tags:
* - destination-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No destination calendars were found
* post:
* summary: Creates a new destination calendar
* security:
* - ApiKeyAuth: []
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destination calendar created
* model: DestinationCalendar
* 400:
* description: Bad request. DestinationCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllDestinationCalendars(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<DestinationCalendarsResponse | DestinationCalendarResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /destination-calendars:
* get:
* summary: Find all destination calendars
* tags:
* - destination-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No destination calendars were found
*/
const data = await prisma.destinationCalendar.findMany({ where: { userId } });
const destination_calendars = data.map((destinationCalendar) =>
schemaDestinationCalendarReadPublic.parse(destinationCalendar)
@@ -60,7 +41,22 @@ async function createOrlistAllDestinationCalendars(
error,
});
} else if (method === "POST") {
const safe = schemaDestinationCalendarCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /destination-calendars:
* post:
* summary: Creates a new destination calendar
* tags:
* - destination-calendars
* responses:
* 201:
* description: OK, destination calendar created
* 400:
* description: Bad request. DestinationCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaDestinationCalendarCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.destinationCalendar.create({ data: { ...safe.data, userId } });
+14 -20
View File
@@ -1,6 +1,8 @@
import jsonSchema from "@/json-schema/json-schema.json";
import pjson from "@/package.json";
import modifyRes from "modify-response-middleware";
import { use } from "next-api-middleware";
import { withSwagger } from "next-swagger-doc";
import { NextApiRequest, NextApiResponse } from "next/types";
const swaggerHandler = withSwagger({
definition: {
@@ -20,26 +22,18 @@ const swaggerHandler = withSwagger({
},
components: {
securitySchemes: { ApiKeyAuth: { type: "apiKey", in: "query", name: "apiKey" } },
security: { ApiKeyAuth: [] },
schemas: { ...jsonSchema.definitions },
},
security: [{ ApiKeyAuth: [] }],
},
apiFolder: "pages/api",
tags: [
"users",
"teams",
"memeberships",
"selected-calendars",
"schedules",
"payments",
"event-types",
"event-type-custom-inputs",
"destination-calendars",
"daily-event-references",
"booking-references",
"availabilities",
"attendees",
],
sort: true,
});
export default swaggerHandler();
export default use(
modifyRes((content: string, _req: NextApiRequest, _res: NextApiResponse) => {
if (content) {
const parsed = JSON.parse(content);
delete parsed.channels;
return Buffer.from(JSON.stringify(parsed));
}
})
)(swaggerHandler());
@@ -13,92 +13,15 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /daily-event-references/{id}:
* get:
* summary: Find a daily event reference by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to get
* security:
* - ApiKeyAuth: []
* tags:
* - daily-event-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: DailyEventReference was not found
* patch:
* summary: Edit an existing daily event reference
* consumes:
* - application/json
* parameters:
* - in: body
* name: dailyEventReference
* description: The dailyEventReference to edit
* schema:
* type: object
* $ref: '#/components/schemas/DailyEventReference'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to edit
* security:
* - ApiKeyAuth: []
* tags:
* - daily-event-references
* responses:
* 201:
* description: OK, dailyEventReference edited successfuly
* model: DailyEventReference
* 400:
* description: Bad request. DailyEventReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing daily event reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to delete
* security:
* - ApiKeyAuth: []
* tags:
* - daily-event-references
* responses:
* 201:
* description: OK, dailyEventReference removed successfuly
* model: DailyEventReference
* 400:
* description: Bad request. DailyEventReference id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function dailyEventReferenceById(
req: NextApiRequest,
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<DailyEventReferenceResponse>
) {
const { method, query, body } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaDailyEventReferenceEditBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userBookings = await prisma.booking.findMany({ where: { userId } });
const userBookingIds = userBookings.map((booking) => booking.id);
const userBookingIds: number[] = userBookings.map((booking) => booking.id);
const userBookingDailyEventReferences = await prisma.dailyEventReference.findMany({
where: { bookingId: { in: userBookingIds } },
});
@@ -109,6 +32,28 @@ export async function dailyEventReferenceById(
res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /event-references/{id}:
* get:
* summary: Find a event reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the event reference to get
* tags:
* - event-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: EventReference was not found
*/
case "GET":
await prisma.dailyEventReference
.findUnique({ where: { id: safeQuery.data.id } })
@@ -122,6 +67,28 @@ export async function dailyEventReferenceById(
);
break;
/**
* @swagger
* /event-references/{id}:
* patch:
* summary: Edit an existing event reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the event reference to edit
* tags:
* - event-references
* responses:
* 201:
* description: OK, EventReference edited successfuly
* 400:
* description: Bad request. EventReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
@@ -138,6 +105,28 @@ export async function dailyEventReferenceById(
);
break;
/**
* @swagger
* /event-references/{id}:
* delete:
* summary: Remove an existing event reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the event reference to delete
* tags:
* - event-references
* responses:
* 201:
* description: OK, EventReference removed successfuly
* 400:
* description: Bad request. EventReference id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.dailyEventReference
.delete({
@@ -9,47 +9,29 @@ import {
schemaDailyEventReferenceReadPublic,
} from "@lib/validations/daily-event-reference";
/**
* @swagger
* /daily-event-references:
* get:
* summary: Find all daily event reference
* security:
* - ApiKeyAuth: []
* tags:
* - daily-event-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No daily event references were found
* post:
* summary: Creates a new daily event reference
* security:
* - ApiKeyAuth: []
* tags:
* - daily-event-references
* responses:
* 201:
* description: OK, daily event reference created
* model: DailyEventReference
* 400:
* description: Bad request. DailyEventReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllDailyEventReferences(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<DailyEventReferencesResponse | DailyEventReferenceResponse>
) {
const { method } = req;
const userId = req.userId;
const userBookings = await prisma.booking.findMany({ where: { userId } });
const userBookingIds = userBookings.map((booking) => booking.id);
if (method === "GET") {
/**
* @swagger
* /event-references:
* get:
* summary: Find all daily event reference
* tags:
* - event-references
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No daily event references were found
*/
const data = await prisma.dailyEventReference.findMany({
where: { bookingId: { in: userBookingIds } },
});
@@ -64,7 +46,22 @@ async function createOrlistAllDailyEventReferences(
error,
});
} else if (method === "POST") {
const safe = schemaDailyEventReferenceCreateBodyParams.safeParse(req.body);
/**
* @swagger
* /event-references:
* post:
* summary: Creates a new daily event reference
* tags:
* - event-references
* responses:
* 201:
* description: OK, daily event reference created
* 400:
* description: Bad request. DailyEventReference body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaDailyEventReferenceCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.dailyEventReference.create({ data: safe.data });
+83 -87
View File
@@ -10,98 +10,43 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /event-types/{id}:
* get:
* summary: Find a eventType by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to get
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: EventType was not found
* patch:
* summary: Edit an existing eventType
* consumes:
* - application/json
* parameters:
* - in: body
* name: eventType
* description: The eventType to edit
* schema:
* type: object
* $ref: '#/components/schemas/EventType'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to edit
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, eventType edited successfuly
* model: EventType
* 400:
* description: Bad request. EventType body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing eventType
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to delete
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, eventType removed successfuly
* model: EventType
* 400:
* description: Bad request. EventType id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function eventTypeById(req: NextApiRequest, res: NextApiResponse<EventTypeResponse>) {
const { method, query, body } = req;
export async function eventTypeById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<EventTypeResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaEventTypeBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const data = await prisma.eventType.findMany({ where: { userId } });
const userEventTypes = data.map((eventType) => eventType.id);
if (!userEventTypes.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /event-types/{id}:
* get:
* summary: Find a eventType
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to get
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: EventType was not found
*/
case "GET":
await prisma.eventType
.findUnique({ where: { id: safeQuery.data.id } })
@@ -114,8 +59,34 @@ export async function eventTypeById(req: NextApiRequest, res: NextApiResponse<Ev
})
);
break;
/**
* @swagger
* /event-types/{id}:
* patch:
* summary: Edit an existing eventType
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to edit
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, eventType edited successfuly
* 400:
* description: Bad request. EventType body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
const safeBody = schemaEventTypeBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
}
@@ -130,7 +101,32 @@ export async function eventTypeById(req: NextApiRequest, res: NextApiResponse<Ev
})
);
break;
/**
* @swagger
* /event-types/{id}:
* delete:
* summary: Remove an existing eventType
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the eventType to delete
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, eventType removed successfuly
* 400:
* description: Bad request. EventType id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.eventType
.delete({ where: { id: safeQuery.data.id } })
+36 -40
View File
@@ -6,49 +6,28 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { EventTypeResponse, EventTypesResponse } from "@lib/types";
import { schemaEventTypeBodyParams, schemaEventTypePublic } from "@lib/validations/event-type";
/**
* @swagger
* /event-types:
* get:
* summary: Find all event types
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No event types were found
* post:
* summary: Creates a new event type
* security:
* - ApiKeyAuth: []
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, event type created
* model: EventType
* 400:
* description: Bad request. EventType body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllEventTypes(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<EventTypesResponse | EventTypeResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /event-types:
* get:
* summary: Find all event types
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No event types were found
*/
const data = await prisma.eventType.findMany({ where: { userId } });
const event_types = data.map((eventType) => schemaEventTypePublic.parse(eventType));
if (event_types) res.status(200).json({ event_types });
@@ -59,7 +38,24 @@ async function createOrlistAllEventTypes(
error,
});
} else if (method === "POST") {
const safe = schemaEventTypeBodyParams.safeParse(req.body);
/**
* @swagger
* /event-types:
* post:
* summary: Creates a new event type
* tags:
* - event-types
* externalDocs:
* url: https://docs.cal.com/event-types
* responses:
* 201:
* description: OK, event type created
* 400:
* description: Bad request. EventType body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaEventTypeBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.eventType.create({ data: { ...safe.data, userId } });
-5
View File
@@ -1,10 +1,5 @@
import type { NextApiRequest, NextApiResponse } from "next";
/**
* @swagger
* security:
* - ApiKeyAuth: []
*/
export default async function CalcomApi(_: NextApiRequest, res: NextApiResponse) {
res.status(201).json({ message: "Welcome to Cal.com API - docs are at https://docs.cal.com/api" });
}
+89 -97
View File
@@ -7,110 +7,45 @@ import type { MembershipResponse } from "@lib/types";
import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validations/membership";
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString";
/**
* @swagger
* /memberships/{userId}_{teamId}:
* get:
* summary: Find 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
* security:
* - ApiKeyAuth: []
* 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
* security:
* - ApiKeyAuth: []
* 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
* security:
* - ApiKeyAuth: []
* 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<MembershipResponse>) {
const { method, query, body } = req;
export async function membershipById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<MembershipResponse>
) {
const safeQuery = schemaQueryIdAsString.safeParse(query);
const safeBody = 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 [paramUserId, teamId] = safeQuery.data.id.split("_");
const userId = req.userId;
if (parseInt(paramUserId) !== userId) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /memberships/{userId}_{teamId}:
* get:
* summary: Find 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
*/
case "GET":
await prisma.membership
.findUnique({
@@ -131,7 +66,36 @@ export async function membershipById(req: NextApiRequest, res: NextApiResponse<M
);
break;
/**
* @swagger
* /memberships/{userId}_{teamId}:
* patch:
* summary: Edit 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 edited successfuly
* 400:
* description: Bad request. Membership body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
const safeBody = schemaMembershipBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
}
@@ -155,6 +119,34 @@ export async function membershipById(req: NextApiRequest, res: NextApiResponse<M
);
break;
/**
* @swagger
* /memberships/{userId}_{teamId}:
* 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
* 400:
* description: Bad request. Membership id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.membership
.delete({
+32 -35
View File
@@ -6,44 +6,26 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { MembershipResponse, MembershipsResponse } from "@lib/types";
import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validations/membership";
/**
* @swagger
* /memberships:
* get:
* summary: Find all memberships
* security:
* - ApiKeyAuth: []
* tags:
* - memberships
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No memberships were found
* post:
* summary: Creates a new membership
* security:
* - ApiKeyAuth: []
* tags:
* - memberships
* responses:
* 201:
* description: OK, membership created
* model: Membership
* 400:
* description: Bad request. Membership body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllMemberships(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<MembershipsResponse | MembershipResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /memberships:
* get:
* summary: Find all memberships
* tags:
* - memberships
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No memberships were found
*/
const data = await prisma.membership.findMany({ where: { userId } });
const memberships = data.map((membership) => schemaMembershipPublic.parse(membership));
if (memberships) res.status(200).json({ memberships });
@@ -54,7 +36,22 @@ async function createOrlistAllMemberships(
error,
});
} else if (method === "POST") {
const safe = schemaMembershipBodyParams.safeParse(req.body);
/**
* @swagger
* /memberships:
* post:
* summary: Creates a new membership
* tags:
* - memberships
* responses:
* 201:
* description: OK, membership created
* 400:
* description: Bad request. Membership body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaMembershipBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.membership.create({ data: { ...safe.data, userId } });
+5 -7
View File
@@ -14,7 +14,7 @@ import {
* @swagger
* /payments/{id}:
* get:
* summary: Find one of your own payments by ID
* summary: Find a payment
* parameters:
* - in: path
* name: id
@@ -22,8 +22,6 @@ import {
* type: integer
* required: true
* description: Numeric ID of the payment to get
* security:
* - ApiKeyAuth: []
* tags:
* - payments
* responses:
@@ -34,11 +32,11 @@ import {
* 404:
* description: Payment was not found
*/
export async function paymentById(req: NextApiRequest, res: NextApiResponse<PaymentResponse>) {
const { method, query } = req;
export async function paymentById(
{ method, query, userId }: NextApiRequest,
res: NextApiResponse<PaymentResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const userId = req.userId;
if (safeQuery.success && method === "GET") {
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
+1 -5
View File
@@ -11,8 +11,6 @@ import { schemaPaymentPublic } from "@lib/validations/payment";
* /payments:
* get:
* summary: Find all payments
* security:
* - ApiKeyAuth: []
* tags:
* - payments
* responses:
@@ -23,9 +21,7 @@ import { schemaPaymentPublic } from "@lib/validations/payment";
* 404:
* description: No payments were found
*/
async function allPayments(req: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
const userId = req.userId;
async function allPayments({ userId }: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
+70 -78
View File
@@ -10,92 +10,40 @@ import {
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
/**
* @swagger
* /schedules/{id}:
* get:
* summary: Find a schedule by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to get
* security:
* - ApiKeyAuth: []
* tags:
* - schedules
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Schedule was not found
* patch:
* summary: Edit an existing schedule
* consumes:
* - application/json
* parameters:
* - in: body
* name: schedule
* description: The schedule to edit
* schema:
* type: object
* $ref: '#/components/schemas/Schedule'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to edit
* security:
* - ApiKeyAuth: []
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule edited successfuly
* model: Schedule
* 400:
* description: Bad request. Schedule body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing schedule
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to delete
* security:
* - ApiKeyAuth: []
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule removed successfuly
* model: Schedule
* 400:
* description: Bad request. Schedule id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function scheduleById(req: NextApiRequest, res: NextApiResponse<ScheduleResponse>) {
const { method, query, body } = req;
export async function scheduleById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<ScheduleResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaScheduleBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userSchedules = await prisma.schedule.findMany({ where: { userId } });
const userScheduleIds = userSchedules.map((schedule) => schedule.id);
if (!userScheduleIds.includes(safeQuery.data.id)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /schedules/{id}:
* get:
* summary: Find a schedule
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to get
* tags:
* - schedules
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: Schedule was not found
*/
case "GET":
await prisma.schedule
.findUnique({ where: { id: safeQuery.data.id } })
@@ -109,6 +57,28 @@ export async function scheduleById(req: NextApiRequest, res: NextApiResponse<Sch
);
break;
/**
* @swagger
* /schedules/{id}:
* patch:
* summary: Edit an existing schedule
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to edit
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule edited successfuly
* 400:
* description: Bad request. Schedule body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
@@ -125,6 +95,28 @@ export async function scheduleById(req: NextApiRequest, res: NextApiResponse<Sch
);
break;
/**
* @swagger
* /schedules/{id}:
* delete:
* summary: Remove an existing schedule
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the schedule to delete
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule removed successfuly
* 400:
* description: Bad request. Schedule id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
// Look for user to check if schedule is user's default
const user = await prisma.user.findUnique({ where: { id: userId } });
+32 -36
View File
@@ -6,45 +6,26 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { ScheduleResponse, SchedulesResponse } from "@lib/types";
import { schemaScheduleBodyParams, schemaSchedulePublic } from "@lib/validations/schedule";
/**
* @swagger
* /schedules:
* get:
* summary: Find all schedules
* security:
* - ApiKeyAuth: []
* tags:
* - schedules
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No schedules were found
* post:
* summary: Creates a new schedule
* security:
* - ApiKeyAuth: []
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule created
* model: Schedule
* 400:
* description: Bad request. Schedule body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllSchedules(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<SchedulesResponse | ScheduleResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /schedules:
* get:
* summary: Find all schedules
* tags:
* - schedules
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No schedules were found
*/
const data = await prisma.schedule.findMany({ where: { userId } });
const schedules = data.map((schedule) => schemaSchedulePublic.parse(schedule));
if (schedules) res.status(200).json({ schedules });
@@ -55,7 +36,22 @@ async function createOrlistAllSchedules(
error,
});
} else if (method === "POST") {
const safe = schemaScheduleBodyParams.safeParse(req.body);
/**
* @swagger
* /schedules:
* post:
* summary: Creates a new schedule
* tags:
* - schedules
* responses:
* 201:
* description: OK, schedule created
* 400:
* description: Bad request. Schedule body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaScheduleBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const data = await prisma.schedule.create({ data: { ...safe.data, userId } });
const schedule = schemaSchedulePublic.parse(data);
+103 -115
View File
@@ -10,131 +10,52 @@ import {
} from "@lib/validations/selected-calendar";
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString";
/**
* @swagger
* /selected-calendars/{userId}_{integration}_{externalId}:
* get:
* summary: Find a selected-calendar by userID and teamID
* parameters:
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: string
* required: true
* description: externalId of the selected calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* security:
* - ApiKeyAuth: []
* tags:
* - selected-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: SelectedCalendar was not found
* patch:
* summary: Edit an existing selected calendar
* consumes:
* - application/json
* parameters:
* - in: body
* name: selected-calendar
* description: The selected-calendar to edit
* schema:
* type: object
* $ref: '#/components/schemas/SelectedCalendar'
* required: true
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: string
* required: true
* description: externalId of the selected calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* security:
* - ApiKeyAuth: []
* tags:
* - selected-calendars
* responses:
* 201:
* description: OK, selected-calendar edited successfuly
* model: SelectedCalendar
* 400:
* description: Bad request. SelectedCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing selected-calendar
* parameters:
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: integer
* required: true
* description: externalId of the selected-calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* security:
* - ApiKeyAuth: []
* tags:
* - selected-calendars
* responses:
* 201:
* description: OK, selected-calendar removed successfuly
* model: SelectedCalendar
* 400:
* description: Bad request. SelectedCalendar id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function selectedCalendarById(
req: NextApiRequest,
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<SelectedCalendarResponse>
) {
const { method, query, body } = req;
const safeQuery = schemaQueryIdAsString.safeParse(query);
const safeBody = schemaSelectedCalendarBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
// This is how we set the userId and externalId in the query for managing compoundId.
const [paramUserId, integration, externalId] = safeQuery.data.id.split("_");
const userId = req.userId;
if (userId !== parseInt(paramUserId)) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
/**
* @swagger
* /selected-calendars/{userId}_{integration}_{externalId}:
* get:
* summary: Find a selected calendar
* parameters:
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: string
* required: true
* description: externalId of the selected calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* tags:
* - selected-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: SelectedCalendar was not found
*/
case "GET":
await prisma.selectedCalendar
.findUnique({
@@ -156,6 +77,40 @@ export async function selectedCalendarById(
);
break;
/**
* @swagger
* /selected-calendars/{userId}_{integration}_{externalId}:
* patch:
* summary: Edit a selected calendar
* parameters:
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: string
* required: true
* description: externalId of the selected calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* tags:
* - selected-calendars
* responses:
* 201:
* description: OK, selected-calendar edited successfuly
* 400:
* description: Bad request. SelectedCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
@@ -180,7 +135,40 @@ export async function selectedCalendarById(
})
);
break;
/**
* @swagger
* /selected-calendars/{userId}_{integration}_{externalId}:
* delete:
* summary: Remove a selected calendar
* parameters:
* - in: path
* name: userId
* schema:
* type: integer
* required: true
* description: userId of the selected calendar to get
* - in: path
* name: externalId
* schema:
* type: integer
* required: true
* description: externalId of the selected-calendar to get
* - in: path
* name: integration
* schema:
* type: string
* required: true
* description: integration of the selected calendar to get
* tags:
* - selected-calendars
* responses:
* 201:
* description: OK, selected-calendar removed successfuly
* 400:
* description: Bad request. SelectedCalendar id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
case "DELETE":
await prisma.selectedCalendar
.delete({
+43 -36
View File
@@ -9,45 +9,26 @@ import {
schemaSelectedCalendarPublic,
} from "@lib/validations/selected-calendar";
/**
* @swagger
* /selected-calendars:
* get:
* summary: Find all selected calendars
* security:
* - ApiKeyAuth: []
* tags:
* - selected-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No selected calendars were found
* post:
* summary: Creates a new selected calendar
* security:
* - ApiKeyAuth: []
* tags:
* - selected-calendars
* 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 createOrlistAllSelectedCalendars(
req: NextApiRequest,
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<SelectedCalendarsResponse | SelectedCalendarResponse>
) {
const { method } = req;
const userId = req.userId;
if (method === "GET") {
/**
* @swagger
* /selected-calendars:
* get:
* summary: Find all selected calendars
* tags:
* - selected-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No selected calendars were found
*/
const data = await prisma.selectedCalendar.findMany({ where: { userId } });
const selected_calendars = data.map((selected_calendar) =>
schemaSelectedCalendarPublic.parse(selected_calendar)
@@ -60,7 +41,33 @@ async function createOrlistAllSelectedCalendars(
error,
});
} else if (method === "POST") {
const safe = schemaSelectedCalendarBodyParams.safeParse(req.body);
/**
* @swagger
* /selected-calendars:
* get:
* summary: Find all selected calendars
* tags:
* - selected-calendars
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No selected calendars were found
* post:
* summary: Creates a new selected calendar
* tags:
* - selected-calendars
* responses:
* 201:
* description: OK, selected calendar created
* 400:
* description: Bad request. SelectedCalendar body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaSelectedCalendarBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
// Create new selectedCalendar connecting it to current userId
const data = await prisma.selectedCalendar.create({
+5 -21
View File
@@ -14,7 +14,7 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
* @swagger
* /teams/{id}:
* get:
* summary: Find a team by ID
* summary: Find a team
* parameters:
* - in: path
* name: id
@@ -22,8 +22,6 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
* type: integer
* required: true
* description: Numeric ID of the team to get
* security:
* - ApiKeyAuth: []
* tags:
* - teams
* responses:
@@ -35,30 +33,18 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
* description: Team was not found
* patch:
* summary: Edit an existing team
* consumes:
* - application/json
* parameters:
* - in: body
* name: team
* description: The team to edit
* schema:
* type: object
* $ref: '#/components/schemas/Team'
* required: true
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the team to edit
* security:
* - ApiKeyAuth: []
* tags:
* - teams
* responses:
* 201:
* description: OK, team edited successfuly
* model: Team
* 400:
* description: Bad request. Team body is invalid.
* 401:
@@ -72,25 +58,23 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
* type: integer
* required: true
* description: Numeric ID of the team to delete
* security:
* - ApiKeyAuth: []
* tags:
* - teams
* 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 teamById(req: NextApiRequest, res: NextApiResponse<TeamResponse>) {
const { method, query, body } = req;
export async function teamById(
{ method, query, body, userId }: NextApiRequest,
res: NextApiResponse<TeamResponse>
) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaTeamBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userWithMemberships = await prisma.membership.findMany({
where: { userId: userId },
});
+35 -35
View File
@@ -7,41 +7,26 @@ import { TeamResponse, TeamsResponse } from "@lib/types";
import { schemaMembershipPublic } from "@lib/validations/membership";
import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
/**
* @swagger
* /teams:
* get:
* summary: Find all teams
* security:
* - ApiKeyAuth: []
* tags:
* - teams
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No teams were found
* post:
* summary: Creates a new team
* security:
* - ApiKeyAuth: []
* tags:
* - teams
* 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 createOrlistAllTeams(req: NextApiRequest, res: NextApiResponse<TeamsResponse | TeamResponse>) {
const { method } = req;
const userId = req.userId;
async function createOrlistAllTeams(
{ method, body, userId }: NextApiRequest,
res: NextApiResponse<TeamsResponse | TeamResponse>
) {
if (method === "GET") {
/**
* @swagger
* /teams:
* get:
* summary: Find all teams
* tags:
* - teams
* responses:
* 200:
* description: OK
* 401:
* description: Authorization information is missing or invalid.
* 404:
* description: No teams were found
*/
const userWithMemberships = await prisma.membership.findMany({
where: { userId: userId },
});
@@ -55,7 +40,22 @@ async function createOrlistAllTeams(req: NextApiRequest, res: NextApiResponse<Te
error,
});
} else if (method === "POST") {
const safe = schemaTeamBodyParams.safeParse(req.body);
/**
* @swagger
* /teams:
* post:
* summary: Creates a new team
* tags:
* - teams
* responses:
* 201:
* description: OK, team created
* 400:
* description: Bad request. Team body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaTeamBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const team = await prisma.team.create({ data: safe.data });
// We're also creating the relation membership of team ownership in this call.
+5 -18
View File
@@ -14,7 +14,8 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations
* @swagger
* /users/{id}:
* get:
* summary: Find a user by ID, returns your user if regular user.
* summary: Find a user, returns your user if regular user.
* operationId: getUserById
* parameters:
* - in: path
* name: id
@@ -22,8 +23,6 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations
* type: integer
* required: true
* description: Numeric ID of the user to get
* security:
* - ApiKeyAuth: []
* tags:
* - users
* responses:
@@ -35,34 +34,26 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations
* description: User was not found
* patch:
* summary: Edit an existing user
* consumes:
* - application/json
* operationId: editUserById
* parameters:
* - in: body
* name: name
* description: The users full name
* schema:
* type: string
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the user to edit
* security:
* - ApiKeyAuth: []
* tags:
* - users
* 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.
* delete:
* summary: Remove an existing user
* operationId: deleteUserById
* parameters:
* - in: path
* name: id
@@ -70,21 +61,17 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations
* type: integer
* required: true
* description: Numeric ID of the user to delete
* security:
* - ApiKeyAuth: []
* tags:
* - users
* 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 userById(req: NextApiRequest, res: NextApiResponse<any>) {
const { method, query, body, userId } = req;
export async function userById({ method, query, body, userId }: NextApiRequest, res: NextApiResponse<any>) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
console.log(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
+3 -5
View File
@@ -10,11 +10,10 @@ import { schemaUserReadPublic } from "@lib/validations/user";
* @swagger
* /users:
* get:
* summary: Find all users (admin only), returns your user if regular user.
* security:
* - ApiKeyAuth: []
* summary: Find all users.
* tags:
* - users
* operationId: listUsers
* responses:
* 200:
* description: OK
@@ -23,8 +22,7 @@ import { schemaUserReadPublic } from "@lib/validations/user";
* 404:
* description: No users were found
*/
async function allUsers(req: NextApiRequest, res: NextApiResponse<UsersResponse>) {
const userId = req.userId;
async function allUsers({ userId }: NextApiRequest, res: NextApiResponse<UsersResponse>) {
const data = await prisma.user.findMany({
where: {
id: userId,
+4 -6
View File
@@ -21,22 +21,20 @@ import {
* type: integer
* required: true
* description: Numeric ID of the resource to delete
* security:
* - ApiKeyAuth: []
* tags:
* - resources
* responses:
* 201:
* description: OK, resource removed successfuly
* model: Resource
* 400:
* description: Bad request. Resource id is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function deleteResource(req: NextApiRequest, res: NextApiResponse<BaseResponse>) {
const safe = schemaQueryIdParseInt.safeParse(req.query);
if (!safe.success) throw new Error("Invalid request query", safe.error);
export async function deleteResource({query}: NextApiRequest, res: NextApiResponse<BaseResponse>) {
const safe = schemaQueryIdParseInt.safeParse(query);
if (!safe.success) throw new Error("Invalid request query");
const data = await prisma.resource.delete({ where: { id: safe.data.id } });
+4 -6
View File
@@ -22,22 +22,20 @@ import {
* type: integer
* required: true
* description: Numeric ID of the resource to edit
* security:
* - ApiKeyAuth: []
* tags:
* - resources
* responses:
* 201:
* description: OK, resource edited successfuly
* model: Resource
* 400:
* description: Bad request. Resource body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
export async function editResource(req: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safeQuery = schemaQueryIdParseInt.safeParse(req.query);
const safeBody = schemaResourceBodyParams.safeParse(req.body);
export async function editResource({query, body}: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaResourceBodyParams.safeParse(body);
if (!safeQuery.success || !safeBody.success) throw new Error("Invalid request");
const resource = await prisma.resource.update({
+4 -5
View File
@@ -14,7 +14,7 @@ import {
* @swagger
* /v1/resources/{id}:
* get:
* summary: Find a resource by ID
* summary: Find a resource
* parameters:
* - in: path
* name: id
@@ -22,8 +22,7 @@ import {
* type: integer
* required: true
* description: Numeric ID of the resource to get
* security:
* - ApiKeyAuth: []
* tags:
* - resources
* responses:
@@ -34,8 +33,8 @@ import {
* 404:
* description: Resource was not found
*/
export async function resourceById(req: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safe = schemaQueryIdParseInt.safeParse(req.query);
export async function resourceById({query}: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safe = schemaQueryIdParseInt.safeParse(query);
if (!safe.success) throw new Error("Invalid request query");
const resource = await prisma.resource.findUnique({ where: { id: safe.data.id } });
+1 -2
View File
@@ -11,8 +11,7 @@ import { schemaResourcePublic } from "@lib/validations/resource";
* /v1/resources:
* get:
* summary: Find all resources
* security:
* - ApiKeyAuth: []
* tags:
* - resources
* responses:
+25 -23
View File
@@ -6,13 +6,18 @@ import { withMiddleware } from "@lib/helpers/withMiddleware";
import { PaymentResponse, PaymentsResponse } from "@lib/types";
import { schemaPaymentBodyParams, schemaPaymentPublic } from "@lib/validations/payment";
async function createOrlistAllPayments(
{method, body}: NextApiRequest,
res: NextApiResponse<PaymentsResponse | PaymentResponse>
) {
if (method === "GET") {
/**
* @swagger
* /v1/payments:
* get:
* summary: Find all payments
* security:
* - ApiKeyAuth: []
* tags:
* - payments
* responses:
@@ -22,27 +27,7 @@ import { schemaPaymentBodyParams, schemaPaymentPublic } from "@lib/validations/p
* description: Authorization information is missing or invalid.
* 404:
* description: No payments were found
* post:
* summary: Creates a new payment
* security:
* - ApiKeyAuth: []
* tags:
* - payments
* responses:
* 201:
* description: OK, payment created
* model: Payment
* 400:
* description: Bad request. Payment body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createOrlistAllPayments(
req: NextApiRequest,
res: NextApiResponse<PaymentsResponse | PaymentResponse>
) {
const { method } = req;
if (method === "GET") {
const payments = await prisma.payment.findMany();
const data = payments.map((payment) => schemaPaymentPublic.parse(payment));
if (data) res.status(200).json({ data });
@@ -53,7 +38,24 @@ async function createOrlistAllPayments(
error,
});
} else if (method === "POST") {
const safe = schemaPaymentBodyParams.safeParse(req.body);
/**
* @swagger
* /v1/payments:
* post:
* summary: Creates a new payment
* tags:
* - payments
* responses:
* 201:
* description: OK, payment created
* 400:
* description: Bad request. Payment body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
const safe = schemaPaymentBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const payment = await prisma.payment.create({ data: safe.data });
+4 -6
View File
@@ -18,22 +18,20 @@ import { schemaResourceBodyParams, schemaResourcePublic, withValidResource } fro
* application/json:
* schema:
* $ref: '#/components/schemas/Resource'
* security:
* - ApiKeyAuth: []
* tags:
* - resources
* responses:
* 201:
* description: OK, resource created
* model: Resource
* 400:
* description: Bad request. Resource body is invalid.
* 401:
* description: Authorization information is missing or invalid.
*/
async function createResource(req: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safe = schemaResourceBodyParams.safeParse(req.body);
if (!safe.success) throw new Error("Invalid request body", safe.error);
async function createResource({body}: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safe = schemaResourceBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
const resource = await prisma.resource.create({ data: safe.data });
const data = schemaResourcePublic.parse(resource);
Vendored
+2
View File
@@ -0,0 +1,2 @@
declare module "modify-response-middleware";