Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements Accounts Controllers Validators #125

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@types/sns-validator": "0.3.0",
"@types/supertest": "2.0.11",
"@types/uuid": "8.3.1",
"@types/yup": "^0.29.13",
"@typescript-eslint/eslint-plugin": "4.29.3",
"@typescript-eslint/parser": "4.29.3",
"babel-plugin-module-resolver": "4.1.0",
Expand Down Expand Up @@ -74,6 +75,7 @@
"nodemailer": "6.6.3",
"request": "^2.88.2",
"sns-validator": "^0.3.4",
"uuid": "8.3.2"
"uuid": "8.3.2",
"yup": "^0.32.9"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { Controller } from '@core/infra/Controller'
import { PrismaUsersRepository } from '@modules/accounts/repositories/prisma/PrismaUsersRepository'
import { AuthenticateUser } from '@modules/accounts/useCases/AuthenticateUser/AuthenticateUser'
import { AuthenticateUserController } from '@modules/accounts/useCases/AuthenticateUser/AuthenticateUserController'
import { AuthenticateUserValidator } from '@modules/accounts/validation/AuthenticateUserValidator'

export function makeAuthenticateUserController(): Controller {
const prismaUsersRepository = new PrismaUsersRepository()
const authenticateUser = new AuthenticateUser(prismaUsersRepository)
const validator = new AuthenticateUserValidator()
const authenticateUserController = new AuthenticateUserController(
validator,
authenticateUser
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { Controller } from '@core/infra/Controller'
import { CompareFieldsValidator } from '@infra/validation/CompareFieldsValidator'
import { ValidatorCompositor } from '@infra/validation/Compositor'
// import { RequiredFieldsValidator } from '@infra/validation/RequiredFieldsValidator'
import { PrismaUsersRepository } from '@modules/accounts/repositories/prisma/PrismaUsersRepository'
import { RegisterUser } from '@modules/accounts/useCases/RegisterUser/RegisterUser'
import { RegisterUserController } from '@modules/accounts/useCases/RegisterUser/RegisterUserController'
import { RegisterUserValidator } from '@modules/accounts/validation/RegisterUserValidator'

export function makeRegisterUserController(): Controller {
const prismaUsersRepository = new PrismaUsersRepository()
const registerUser = new RegisterUser(prismaUsersRepository)

const validator = new ValidatorCompositor([
// new RequiredFieldsValidator(),
new CompareFieldsValidator('password', 'password_confirmation'),
])

const validator = new RegisterUserValidator()
const registerUserController = new RegisterUserController(
validator,
registerUser
Expand Down
15 changes: 0 additions & 15 deletions src/infra/validation/CompareFieldsValidator.spec.ts

This file was deleted.

19 changes: 0 additions & 19 deletions src/infra/validation/CompareFieldsValidator.ts

This file was deleted.

36 changes: 0 additions & 36 deletions src/infra/validation/Compositor.spec.ts

This file was deleted.

15 changes: 0 additions & 15 deletions src/infra/validation/Compositor.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/infra/validation/RequiredFieldsValidator.spec.ts

This file was deleted.

21 changes: 0 additions & 21 deletions src/infra/validation/RequiredFieldsValidator.ts

This file was deleted.

51 changes: 51 additions & 0 deletions src/infra/validation/adapters/YupAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Validator } from '@core/infra/Validator'
import { Either, left } from '@core/logic/Either'

import type { ValidationError as YupError } from 'yup'

export const adaptYupValidation = (validator: Validator): Validator => {
return {
validate(data: any): Either<Error, null> {
const validationResult = validator.validate(data)
if (validationResult.isRight()) return validationResult

const yupError = validationResult.value
const { params, path, type } = yupError as YupError

const error = new Error()
error.name = 'ValidationError'

switch (type) {
case 'required':
error.message = `Missing value for field "${path}"`
break

case 'typeError':
error.message = `Invalid value for field "${path}"`
break

case 'min':
error.message = `Expected at least of ${params.min} characters for field "${path}"`
break

case 'max':
error.message = `Expected a maximum of ${params.max} characters for field "${path}"`
break

case 'email':
error.message = `Value for field "${path}" is not a valid email format`
break

case 'invalid_password_comparison':
error.message = `Password and password confirmation must have the same value`
break

default:
error.message = yupError.message
break
}

return left(error)
},
}
}
6 changes: 0 additions & 6 deletions src/infra/validation/errors/InvalidParamError.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/infra/validation/errors/MissingParamError.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,13 @@ describe('Authenticate User (e2e)', () => {
})
)
})

it('should not be able to authenticate if validation fails', async () => {
const response = await request(app).post('/sessions').send({
email: '[email protected]',
password: null,
})

expect(response.status).toBe(400)
})
})
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import { Controller } from '@core/infra/Controller'
import { HttpResponse, ok, fail, clientError } from '@core/infra/HttpResponse'
import { Validator } from '@core/infra/Validator'

import { AuthenticateUser } from './AuthenticateUser'

type AuthenticateUserControllerRequest = {
export type AuthenticateUserControllerRequest = {
email: string
password: string
}

export class AuthenticateUserController implements Controller {
constructor(private authenticateUser: AuthenticateUser) {}

async handle({
email,
password,
}: AuthenticateUserControllerRequest): Promise<HttpResponse> {
constructor(
private readonly validator: Validator<AuthenticateUserControllerRequest>,
private authenticateUser: AuthenticateUser
) {}

async handle(
request: AuthenticateUserControllerRequest
): Promise<HttpResponse> {
try {
// TODO: Add validation
const validationResult = this.validator.validate(request)

if (validationResult.isLeft()) {
return clientError(validationResult.value)
}

const { email, password } = request

const result = await this.authenticateUser.execute({
email,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Validator } from '@core/infra/Validator'
import { AccountAlreadyExistsError } from './errors/AccountAlreadyExistsError'
import { RegisterUser } from './RegisterUser'

type RegisterUserControllerRequest = {
export type RegisterUserControllerRequest = {
name: string
email: string
password: string
Expand Down
29 changes: 29 additions & 0 deletions src/modules/accounts/validation/AuthenticateUserValidator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { AuthenticateUserValidator } from './AuthenticateUserValidator'

describe('AuthenticateUser Validator', () => {
const validator = new AuthenticateUserValidator()

it('should return no errors if receive all valid fields', () => {
const err = validator.validate({
email: '[email protected]',
password: 'pass123',
})
expect(err.isRight()).toBeTruthy()
})

it('should return an error if any required field is missing', () => {
let err = validator.validate({ email: null, password: 'pass123' })
expect(err.isLeft()).toBeTruthy()

err = validator.validate({ email: '[email protected]', password: null })
expect(err.isLeft()).toBeTruthy()
})

it('should return an error if receive any invalid field', () => {
let err = validator.validate({ email: '[email protected]', password: 'p ' })
expect(err.isLeft()).toBeTruthy()

err = validator.validate({ email: 'johndoe@mail', password: 'pass123' })
expect(err.isLeft()).toBeTruthy()
})
})
29 changes: 29 additions & 0 deletions src/modules/accounts/validation/AuthenticateUserValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Validator } from '@core/infra/Validator'
import { Either, left, right } from '@core/logic/Either'
import { AuthenticateUserControllerRequest } from '../useCases/AuthenticateUser/AuthenticateUserController'

import type { SchemaOf } from 'yup'
import * as yup from 'yup'

type Params = AuthenticateUserControllerRequest

export class AuthenticateUserValidator implements Validator<Params> {
public validate(data: Params): Either<Error, null> {
try {
const schema: SchemaOf<Params> = yup.object({
email: yup.string().required().trim().email(),
password: yup.string().required().trim().min(6).max(255),
})

schema.validateSync(data) // throws an error

return right(null)
} catch (error) {
if (yup.ValidationError.isError(error)) {
return left(error)
}

throw error
}
}
}
Loading