fix users, availabilites, attendees

This commit is contained in:
Agusti Fernandez Pardo
2022-04-24 02:10:32 +02:00
parent 096fd40044
commit dad70d5a12
7 changed files with 93 additions and 43 deletions
+4 -3
View File
@@ -3,13 +3,14 @@ import { z } from "zod";
import { _AvailabilityModel as Availability } from "@calcom/prisma/zod";
export const schemaAvailabilityBaseBodyParams = Availability.omit({ id: true }).partial();
export const schemaAvailabilityBaseBodyParams = Availability.pick({ userId: true, eventTypeId: true, days: true }).partial();
export const schemaAvailabilityPublic = Availability.omit({});
const schemaAvailabilityRequiredParams = z.object({
startTime: z.string(),
endTime: z.string(),
startTime: z.date().or(z.string()).optional(),
endTime: z.date().or(z.string()).optional(),
days: z.any().optional(),
});
export const schemaAvailabilityBodyParams = schemaAvailabilityBaseBodyParams.merge(
+61 -23
View File
@@ -3,34 +3,72 @@ import { z } from "zod";
import { _UserModel as User } from "@calcom/prisma/zod";
export const schemaUserBaseBodyParams = User.omit({
id: true,
createdAt: true,
password: true,
twoFactorEnabled: true,
twoFactorSecret: true,
// @note: These are the ONLY values allowed as weekStart. So user don't introduce bad data.
enum weekdays {
MONDAY = "Monday",
TUESDAY = "Tuesday",
WEDNESDAY = "Wednesday",
THURSDAY = "Thursday",
FRIDAY = "Friday",
SATURDAY = "Saturday",
SUNDAY = "Sunday",
}
// @note: These are the values that are editable via PATCH method on the user Model
export const schemaUserBaseBodyParams = User.pick({
name: true,
bio: true,
avatar: true,
timeZone: true,
weekStart: true,
endTime: true,
bufferTime: true,
theme: true,
defaultScheduleId: true,
locale: true,
timeFormat: true,
brandColor: true,
darkBrandColor: true,
allowDynamicBooking: true,
away: true,
}).partial();
// @note: partial() is used to allow for the user to edit only the fields they want to edit making all optional,
// if want to make any required do it in the schemaRequiredParams
// Here we can both require or not (adding optional or nullish) and also rewrite validations for any value
// for example making weekStart only accept weekdays as input
const schemaUserRequiredParams = z.object({
email: z.string().email(),
weekStart: z.nativeEnum(weekdays).optional(),
});
export const schemaUserBodyParams = schemaUserBaseBodyParams.merge(schemaUserRequiredParams);
// @note: These are the values that are editable via PATCH method on the user Model
export const schemaUserEditBodyParams = schemaUserBaseBodyParams.merge(schemaUserRequiredParams).omit({});
export const schemaUserPublic = User.omit({
identityProvider: true,
identityProviderId: true,
plan: true,
metadata: true,
password: true,
twoFactorEnabled: true,
twoFactorSecret: true,
trialEndsAt: true,
completedOnboarding: true,
// @note: These are the values that are always returned when reading a user
export const schemaUserReadPublic = User.pick({
id: true,
username: true,
name: true,
email: true,
emailVerified: true,
bio: true,
avatar: true,
timeZone: true,
weekStart: true,
endTime: true,
bufferTime: true,
theme: true,
defaultScheduleId: true,
locale: true,
timeFormat: true,
brandColor: true,
darkBrandColor: true,
allowDynamicBooking: true,
away: true,
createdDate: true,
verified: true,
invitedTo: true,
});
export const withValidUser = withValidation({
schema: schemaUserBodyParams,
type: "Zod",
mode: "body",
});
// @note: This is the validation for the PATCH method on the user Model. Not used for now.
export const withValidUser = withValidation({ schema: schemaUserEditBodyParams, type: "Zod", mode: "body" });
+3 -2
View File
@@ -86,13 +86,13 @@ import {
* description: Authorization information is missing or invalid.
*/
export async function attendeeById(req: NextApiRequest, res: NextApiResponse<AttendeeResponse>) {
const { method, query, body } = req;
const { method, query, body, userId } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaAttendeeBodyParams.safeParse(body);
if (!safeQuery.success) {
res.status(400).json({ error: safeQuery.error });
throw new Error("Invalid request query", safeQuery.error);
}
const userId = req.userId;
const userBookings = await prisma.booking.findMany({
where: { userId },
include: { attendees: true },
@@ -118,6 +118,7 @@ export async function attendeeById(req: NextApiRequest, res: NextApiResponse<Att
case "PATCH":
if (!safeBody.success) {
res.status(400).json({ message: "Bad request", error: safeBody.error });
throw new Error("Invalid request body");
}
await prisma.attendee
+8 -4
View File
@@ -114,16 +114,20 @@ export async function availabilityById(req: NextApiRequest, res: NextApiResponse
case "PATCH":
if (!safeBody.success) throw new Error("Invalid request body");
await prisma.availability
const edited = await prisma.availability
.update({
where: { id: safeQuery.data.id },
data: safeBody.data,
})
.then((data) => schemaAvailabilityPublic.parse(data))
.then((availability) => res.status(200).json({ availability }))
.catch((error: Error) =>
res.status(404).json({ message: `Availability with id: ${safeQuery.data.id} not found`, error })
);
.catch((error: Error) => {
console.log(error);
res.status(404).json({
message: `Availability with id: ${safeQuery.data.id} not found`,
error,
});
});
break;
case "DELETE":
+2
View File
@@ -59,10 +59,12 @@ async function createOrlistAllAvailabilities(
error,
});
} else if (method === "POST") {
console.log(req.body);
const safe = schemaAvailabilityBodyParams.safeParse(req.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 = schemaAvailabilityPublic.parse(data);
if (availability) res.status(201).json({ availability, message: "Availability created successfully" });
+13 -9
View File
@@ -8,7 +8,7 @@ import {
schemaQueryIdParseInt,
withValidQueryIdTransformParseInt,
} from "@lib/validations/shared/queryIdTransformParseInt";
import { schemaUserBodyParams, schemaUserPublic } from "@lib/validations/user";
import { schemaUserEditBodyParams, schemaUserReadPublic, withValidUser } from "@lib/validations/user";
/**
* @swagger
@@ -85,19 +85,18 @@ import { schemaUserBodyParams, schemaUserPublic } from "@lib/validations/user";
* 401:
* description: Authorization information is missing or invalid.
*/
export async function userById(req: NextApiRequest, res: NextApiResponse<UserResponse>) {
const { method, query, body } = req;
export async function userById(req: NextApiRequest, res: NextApiResponse<any>) {
const { method, query, body, userId } = req;
const safeQuery = schemaQueryIdParseInt.safeParse(query);
const safeBody = schemaUserBodyParams.safeParse(body);
console.log(body);
if (!safeQuery.success) throw new Error("Invalid request query", safeQuery.error);
const userId = req.userId;
if (safeQuery.data.id !== userId) res.status(401).json({ message: "Unauthorized" });
else {
switch (method) {
case "GET":
await prisma.user
.findUnique({ where: { id: safeQuery.data.id } })
.then((data) => schemaUserPublic.parse(data))
.then((data) => schemaUserReadPublic.parse(data))
.then((user) => res.status(200).json({ user }))
.catch((error: Error) =>
res.status(404).json({ message: `User with id: ${safeQuery.data.id} not found`, error })
@@ -105,13 +104,18 @@ export async function userById(req: NextApiRequest, res: NextApiResponse<UserRes
break;
case "PATCH":
if (!safeBody.success) throw new Error("Invalid request body");
// FIXME: Validate body against different Edit validation, skip username.
const safeBody = schemaUserEditBodyParams.safeParse(body);
if (!safeBody.success) {
res.status(400).json({ message: "Bad request", error: safeBody.error });
throw new Error("Invalid request body");
}
await prisma.user
.update({
where: { id: safeQuery.data.id },
where: { id: userId },
data: safeBody.data,
})
.then((data) => schemaUserPublic.parse(data))
.then((data) => schemaUserReadPublic.parse(data))
.then((user) => res.status(200).json({ user }))
.catch((error: Error) =>
res.status(404).json({ message: `User with id: ${safeQuery.data.id} not found`, error })
+2 -2
View File
@@ -4,7 +4,7 @@ import prisma from "@calcom/prisma";
import { withMiddleware } from "@lib/helpers/withMiddleware";
import { UsersResponse } from "@lib/types";
import { schemaUserPublic } from "@lib/validations/user";
import { schemaUserReadPublic } from "@lib/validations/user";
/**
* @swagger
@@ -30,7 +30,7 @@ async function allUsers(req: NextApiRequest, res: NextApiResponse<UsersResponse>
id: userId,
},
});
const users = data.map((user) => schemaUserPublic.parse(user));
const users = data.map((user) => schemaUserReadPublic.parse(user));
if (users) res.status(200).json({ users });
else
(error: Error) =>