fix: booking reference moved to pick-first create/edit separate validations

This commit is contained in:
Agusti Fernandez Pardo committed 2022-04-26 22:48:15 +02:00
1 parent 6997606a4c
commit 14e2964a6d
8 files changed
+85 -56

No files matched your search

+22 -20
View File
@@ -1,7 +1,7 @@
# Cal.com Public API (Enterprise Only)
This is the public REST api for cal.com.
It exposes CRUD Endpoints of all our most important resources.
This is the public REST api for cal.com.
It exposes CRUD Endpoints of all our most important resources.
And it makes it easy for anyone to integrate with Cal.com at the application programming level.
## Stack
@@ -63,9 +63,10 @@ API Keys optionally may have expiry dates, if they are expired they won't work.
In the future we might add support for header Bearer Auth if we need to or if our customers require it.
## Middlewares
We don't use the new NextJS 12 Beta Middlewares, mainly because they run on the edge, and are not able to call prisma from api endpoints. We use instead a very nifty library called next-api-middleware that let's us use a similar approach building our own middlewares and applying them as we see fit.
* withMiddleware() requires some default middlewares (verifyApiKey, etc...)
- withMiddleware() requires some default middlewares (verifyApiKey, etc...)
## Next.config.js
@@ -121,21 +122,21 @@ We aim to provide a fully tested API for our peace of mind, this is accomplished
## Endpoints matrix
| resource | get [id] | get all | create | edit | delete |
|--------------------------|----------|----------|---------|-------|--------|
| attendees | ✅ | ✅ | ✅ | ✅ | ✅ |
| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| daily-event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-type-custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-types | ✅ | ✅ | ✅ | ✅ | ✅ |
| memberships | ✅ | ✅ | ✅ | ✅ | ✅ |
| payments | ✅ | ✅ | ❌ | ❌ | ❌ |
| schedules | ✅ | ✅ | ✅ | ✅ | ✅ |
| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| teams | ✅ | ✅ | ✅ | ✅ | ✅ |
| users | ✅ | 👤[1] | ✅ | ✅ | ✅ |
| resource | get [id] | get all | create | edit | delete |
| ------------------------ | -------- | ------- | ------ | ---- | ------ |
| attendees | ✅ | ✅ | ✅ | ✅ | ✅ |
| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| daily-event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-type-custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-types | ✅ | ✅ | ✅ | ✅ | ✅ |
| memberships | ✅ | ✅ | ✅ | ✅ | ✅ |
| payments | ✅ | ✅ | ❌ | ❌ | ❌ |
| schedules | ✅ | ✅ | ✅ | ✅ | ✅ |
| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| teams | ✅ | ✅ | ✅ | ✅ | ✅ |
| users | ✅ | 👤[1] | ✅ | ✅ | ✅ |
## Models from database that are not exposed
@@ -170,5 +171,6 @@ DATABASE_URL=DATABASE_URL="postgresql://postgres:@localhost:5450/calendso"
## Optional
API_KEY_PREFIX=cal_# This can be changed per envirorment so cal_test_ for staging for example.
> If you're self-hosting under our commercial license, you can use any prefix you want for api keys. either leave the default cal_ (not providing any envirorment variable) or modify it
API*KEY_PREFIX=cal*# This can be changed per envirorment so cal*test* for staging for example.
> If you're self-hosting under our commercial license, you can use any prefix you want for api keys. either leave the default cal\_ (not providing any envirorment variable) or modify it
+2 -6
View File
@@ -22,12 +22,8 @@ const schemaAttendeeEditParams = z.object({
name: z.string(),
timeZone: z.string(),
});
export const schemaAttendeeEditBodyParams = schemaAttendeeBaseBodyParams.merge(
schemaAttendeeEditParams
);
export const schemaAttendeeCreateBodyParams = schemaAttendeeBaseBodyParams.merge(
schemaAttendeeCreateParams
);
export const schemaAttendeeEditBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeEditParams);
export const schemaAttendeeCreateBodyParams = schemaAttendeeBaseBodyParams.merge(schemaAttendeeCreateParams);
export const schemaAttendeeReadPublic = Attendee.pick({
bookingId: true,
+1 -1
View File
@@ -11,7 +11,7 @@ export const schemaAvailabilityBaseBodyParams = Availability.pick({
days: true,
}).partial();
export const schemaAvailabilityPublic = Availability.pick({
export const schemaAvailabilityReadPublic = Availability.pick({
startTime: true,
endTime: true,
date: true,
+36 -12
View File
@@ -3,21 +3,45 @@ import { z } from "zod";
import { _BookingReferenceModel as BookingReference } from "@calcom/prisma/zod";
export const schemaBookingReferenceBaseBodyParams = BookingReference.omit({ id: true }).partial();
export const schemaBookingReferenceBaseBodyParams = BookingReference.pick({
type: true,
bookingId: true,
uid: true,
meetingId: true,
meetingPassword: true,
meetingUrl: true,
deleted: true,
}).partial();
export const schemaBookingReferencePublic = BookingReference.omit({});
export const schemaBookingReferenceReadPublic = BookingReference.pick({
type: true,
bookingId: true,
uid: true,
meetingId: true,
meetingPassword: true,
meetingUrl: true,
deleted: true,
});
const schemaBookingReferenceRequiredParams = z.object({
const schemaBookingReferenceEditParams = z.object({
type: z.string(),
uid: z.string(),
meetingId: z.string(),
meetingPassword: z.string(),
meetingUrl: z.string(),
deleted: z.boolean(),
});
export const schemaBookingReferenceBodyParams = schemaBookingReferenceBaseBodyParams.merge(
schemaBookingReferenceRequiredParams
const schemaBookingReferenceCreateParams = z.object({
type: z.string(),
uid: z.string(),
meetingId: z.string(),
meetingPassword: z.string(),
meetingUrl: z.string(),
deleted: z.boolean(),
});
export const schemaBookingCreateBodyParams = schemaBookingReferenceBaseBodyParams.merge(
schemaBookingReferenceCreateParams
);
export const schemaBookingEditBodyParams = schemaBookingReferenceBaseBodyParams.merge(
schemaBookingReferenceEditParams
);
export const withValidBookingReference = withValidation({
schema: schemaBookingReferenceBodyParams,
type: "Zod",
mode: "body",
});
+4 -1
View File
@@ -4,7 +4,10 @@ import prisma from "@calcom/prisma";
import { withMiddleware } from "@lib/helpers/withMiddleware";
import type { AvailabilityResponse } from "@lib/types";
import { schemaAvailabilityEditBodyParams, schemaAvailabilityReadPublic } from "@lib/validations/availability";
import {
schemaAvailabilityEditBodyParams,
schemaAvailabilityReadPublic,
} from "@lib/validations/availability";
import {
schemaQueryIdParseInt,
withValidQueryIdTransformParseInt,
+4 -1
View File
@@ -4,7 +4,10 @@ import prisma from "@calcom/prisma";
import { withMiddleware } from "@lib/helpers/withMiddleware";
import { AvailabilityResponse, AvailabilitiesResponse } from "@lib/types";
import { schemaAvailabilityCreateBodyParams, schemaAvailabilityReadPublic } from "@lib/validations/availability";
import {
schemaAvailabilityCreateBodyParams,
schemaAvailabilityReadPublic,
} from "@lib/validations/availability";
/**
* @swagger
+12 -11
View File
@@ -6,8 +6,8 @@ import prisma from "@calcom/prisma";
import { withMiddleware } from "@lib/helpers/withMiddleware";
import type { BookingReferenceResponse } from "@lib/types";
import {
schemaBookingReferenceBodyParams,
schemaBookingReferencePublic,
schemaBookingEditBodyParams,
schemaBookingReferenceReadPublic,
} from "@lib/validations/booking-reference";
import {
schemaQueryIdParseInt,
@@ -18,14 +18,14 @@ import {
* @swagger
* /booking-references/{id}:
* get:
* summary: Get a daily event reference by ID
* summary: Get a booking reference by ID
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to get
* description: Numeric ID of the booking reference to get
* security:
* - ApiKeyAuth: []
* tags:
@@ -38,7 +38,7 @@ import {
* 404:
* description: BookingReference was not found
* patch:
* summary: Edit an existing daily event reference
* summary: Edit an existing booking reference
* consumes:
* - application/json
* parameters:
@@ -54,7 +54,7 @@ import {
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to edit
* description: Numeric ID of the booking reference to edit
* security:
* - ApiKeyAuth: []
* tags:
@@ -68,14 +68,14 @@ import {
* 401:
* description: Authorization information is missing or invalid.
* delete:
* summary: Remove an existing daily event reference
* summary: Remove an existing booking reference
* parameters:
* - in: path
* name: id
* schema:
* type: integer
* required: true
* description: Numeric ID of the daily event reference to delete
* description: Numeric ID of the booking reference to delete
* security:
* - ApiKeyAuth: []
* tags:
@@ -95,7 +95,6 @@ export async function bookingReferenceById(
) {
const { method, query, body } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaBookingReferenceBodyParams.safeParse(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
const userWithBookings = await prisma.user.findUnique({
@@ -111,7 +110,7 @@ export async function bookingReferenceById(
case "GET":
await prisma.bookingReference
.findUnique({ where: { id: safeQuery.data.id } })
.then((data) => schemaBookingReferencePublic.parse(data))
.then((data) => schemaBookingReferenceReadPublic.parse(data))
.then((booking_reference) => res.status(200).json({ booking_reference }))
.catch((error: Error) =>
res.status(404).json({
@@ -122,12 +121,14 @@ export async function bookingReferenceById(
break;
case "PATCH":
const safeBody = schemaBookingEditBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
}
await prisma.bookingReference
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })
.then((data) => schemaBookingReferencePublic.parse(data))
.then((data) => schemaBookingReferenceReadPublic.parse(data))
.then((booking_reference) => res.status(200).json({ booking_reference }))
.catch((error: Error) =>
res.status(404).json({
+4 -4
View File
@@ -5,8 +5,8 @@ import prisma from "@calcom/prisma";
import { withMiddleware } from "@lib/helpers/withMiddleware";
import { BookingReferenceResponse, BookingReferencesResponse } from "@lib/types";
import {
schemaBookingReferenceBodyParams,
schemaBookingReferencePublic,
schemaBookingCreateBodyParams,
schemaBookingReferenceReadPublic,
} from "@lib/validations/booking-reference";
/**
@@ -55,7 +55,7 @@ async function createOrlistAllBookingReferences(
if (method === "GET") {
const data = await prisma.bookingReference.findMany({ where: { id: { in: userBookingIds } } });
const booking_references = data.map((bookingReference) =>
schemaBookingReferencePublic.parse(bookingReference)
schemaBookingReferenceReadPublic.parse(bookingReference)
);
if (booking_references) res.status(200).json({ booking_references });
else
@@ -65,7 +65,7 @@ async function createOrlistAllBookingReferences(
error,
});
} else if (method === "POST") {
const safe = schemaBookingReferenceBodyParams.safeParse(req.body);
const safe = schemaBookingCreateBodyParams.safeParse(req.body);
if (!safe.success) {
throw new Error("Invalid request body");
}