From d32a33771c54b67c9093c80c9dd7874659f3d0c2 Mon Sep 17 00:00:00 2001 From: Gabriel Machin Date: Mon, 15 Jan 2024 14:56:15 -0300 Subject: [PATCH] feat: Add body validation --- src/controllers/auth.ts | 5 +++++ src/middlewares/error.ts | 8 +++++++- src/utils/validator.ts | 11 +++++++++++ src/validator/auth.ts | 35 +++++++++++++++++++++++++++++++++++ tsconfig.json | 1 + tsoa.json | 1 + 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/utils/validator.ts create mode 100644 src/validator/auth.ts diff --git a/src/controllers/auth.ts b/src/controllers/auth.ts index 0a75a7a..935041d 100644 --- a/src/controllers/auth.ts +++ b/src/controllers/auth.ts @@ -8,11 +8,14 @@ import { AuthenticatedRequest, LoginParams, } from 'types'; +import { validateLoginSchema, validateUserSchema } from 'validator/auth'; @Route('v1/auth') export class AuthControllerV1 extends Controller { @Post('/register') public async register(@Body() user: CreateUserParams): Promise { + validateUserSchema(user); + const authReturn = await AuthService.register(user); this.setStatus(httpStatus.CREATED); return authReturn; @@ -20,6 +23,8 @@ export class AuthControllerV1 extends Controller { @Post('/login') public async login(@Body() loginParams: LoginParams): Promise { + validateLoginSchema(loginParams); + const authReturn = await AuthService.login(loginParams); this.setStatus(httpStatus.OK); return authReturn; diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts index 37552d3..33dc1be 100644 --- a/src/middlewares/error.ts +++ b/src/middlewares/error.ts @@ -21,7 +21,13 @@ export const errorConverter = ( next(error); }; -export const errorHandler = (err: ApiError, req: Request, res: Response) => { +export const errorHandler = ( + err: ApiError, + req: Request, + res: Response, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + next: NextFunction, +) => { let { httpCode, message } = err; if (!err.isOperational) { httpCode = diff --git a/src/utils/validator.ts b/src/utils/validator.ts new file mode 100644 index 0000000..fee471c --- /dev/null +++ b/src/utils/validator.ts @@ -0,0 +1,11 @@ +import { ZodError } from 'zod'; + +export const formatZodError = (zodError: ZodError) => { + const formattedError = zodError.errors.map((error) => { + return { + field: error.path, + error: error.message, + }; + }); + return formattedError; +}; diff --git a/src/validator/auth.ts b/src/validator/auth.ts new file mode 100644 index 0000000..2f0521a --- /dev/null +++ b/src/validator/auth.ts @@ -0,0 +1,35 @@ +import { ZodError, z } from 'zod'; + +import { CreateUserParams, LoginParams } from 'types'; +import { ApiError } from 'utils/apiError'; +import { errors } from 'config/errors'; +import { formatZodError } from 'utils/validator'; + +const userSchema = z.object({ + email: z.string().email({ message: 'Invalid email' }), + name: z.string(), + password: z.string().min(1, { message: "Can't be an empty password" }), +}); + +const loginSchema = z.object({ + email: z.string().email({ message: 'Invalid email' }), + password: z.string().min(1, { message: "Can't be an empty password" }), +}); + +export const validateUserSchema = (user: CreateUserParams) => { + try { + userSchema.parse(user); + } catch (err) { + const formattedZodError = formatZodError(err as ZodError); + throw new ApiError(errors.VALIDATION_ERROR, true, formattedZodError); + } +}; + +export const validateLoginSchema = (loginParams: LoginParams) => { + try { + loginSchema.parse(loginParams); + } catch (err) { + const formattedZodError = formatZodError(err as ZodError); + throw new ApiError(errors.VALIDATION_ERROR, true, formattedZodError); + } +}; diff --git a/tsconfig.json b/tsconfig.json index a9be72c..3a452b4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,6 +21,7 @@ "tests/*": ["tests/*"], "types/*": ["types/*"], "utils/*": ["utils/*"], + "validator/*": ["validator/*"], "root/*": ["../*"] } } diff --git a/tsoa.json b/tsoa.json index 4ce8c61..4ffc662 100644 --- a/tsoa.json +++ b/tsoa.json @@ -26,6 +26,7 @@ "tests/*": ["tests/*"], "types/*": ["types/*"], "utils/*": ["utils/*"], + "validator/*": ["validator/*"], "root/*": ["../*"] } }