Skip to content

Commit

Permalink
Edit user pass useCase
Browse files Browse the repository at this point in the history
  • Loading branch information
MatheusSanchez committed Feb 4, 2024
1 parent 836ea3a commit 6dd34ff
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 5 deletions.
21 changes: 19 additions & 2 deletions src/repositories/in-memory-db/inMemoryUserRepository.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { Prisma, User } from '@prisma/client'
import { UserRepository, editUserRequestPrisma } from '../user-repository'
import {
UserRepository,
editUserPasswordRequestPrisma,
editUserRequestPrisma,
} from '../user-repository'
import { randomUUID } from 'crypto'

export class InMemoryUserRepository implements UserRepository {
public db: User[] = []
constructor() {}
async editPassword({
password_hash,
userId,
}: editUserPasswordRequestPrisma): Promise<User> {
const indexToUpdate = this.db.findIndex((user) => user.id === userId)

this.db[indexToUpdate] = {
...this.db[indexToUpdate],
password_hash,
}

return this.db[indexToUpdate]
}

async findByEmail(email: string): Promise<User | null> {
const User = this.db.find((User) => User.email === email)
Expand Down Expand Up @@ -52,7 +69,6 @@ export class InMemoryUserRepository implements UserRepository {
return user
}


async edit({
name,
surname,
Expand All @@ -70,6 +86,7 @@ export class InMemoryUserRepository implements UserRepository {

return this.db[indexToUpdate]
}

async addPhotoUrl(projectId: string, photoUrl: string): Promise<Project> {
throw new Error('Method not implemented.')
}
Expand Down
15 changes: 12 additions & 3 deletions src/repositories/prisma/prisma-users-repository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Prisma, User } from '@prisma/client'
import { prisma } from '../../lib/prisma'
import { UserRepository, editUserRequestPrisma } from '../user-repository'
import {
UserRepository,
editUserPasswordRequestPrisma,
editUserRequestPrisma,
} from '../user-repository'

export class PrismaUsersRepository implements UserRepository {
async findByEmail(email: string): Promise<User | null> {
Expand Down Expand Up @@ -31,7 +35,6 @@ export class PrismaUsersRepository implements UserRepository {
return user
}


async edit({
name,
surname,
Expand All @@ -45,7 +48,13 @@ export class PrismaUsersRepository implements UserRepository {

return user
}


async editPassword({
password_hash,
userId,
}: editUserPasswordRequestPrisma): Promise<User> {
throw new Error('Method not implemented.')
}

async addPhotoUrl(userId: string, photoUrl: string): Promise<User> {
const user = await prisma.user.update({
Expand Down
9 changes: 9 additions & 0 deletions src/repositories/user-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ export interface editUserRequestPrisma {
userId: string
}

export interface editUserPasswordRequestPrisma {
password_hash: string
userId: string
}

export interface UserRepository {
create(data: Prisma.UserCreateInput): Promise<User>
findByEmail(email: string): Promise<User | null>
findById(id: string): Promise<User | null>
edit({ name, surname, country, userId }: editUserRequestPrisma): Promise<User>
addPhotoUrl(userId: string, photoUrl: string): Promise<User>
editPassword({
password_hash,
userId,
}: editUserPasswordRequestPrisma): Promise<User>
}
73 changes: 73 additions & 0 deletions src/use-cases/user/editUserPasswordUseCase.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { expect, describe, it, beforeEach } from 'vitest'
import { CreateUserUseCase } from './createUserUseCase'
import { compare } from 'bcryptjs'
import { InMemoryUserRepository } from '../../repositories/in-memory-db/inMemoryUserRepository'
import { UserRepository } from '../../repositories/user-repository'
import { EditUserPasswordUseCase } from './editUserPasswordUseCase'
import { InvalidCredentialsError } from '../errors/InvalidCredentialsError'
import { randomUUID } from 'crypto'
import { ResourceNotFoundError } from '../errors/ResourceNotFoundError'

let usersRepository: UserRepository
let editUserPasswordUseCase: EditUserPasswordUseCase
let createUserUseCase: CreateUserUseCase

describe('Edit User Pass Use Case', () => {
beforeEach(() => {
usersRepository = new InMemoryUserRepository()
editUserPasswordUseCase = new EditUserPasswordUseCase(usersRepository)
createUserUseCase = new CreateUserUseCase(usersRepository)
})

it('should be able to edit a user pass', async () => {
const { user } = await createUserUseCase.execute({
name: 'John',
surname: 'Doe',
email: '[email protected]',
password: '123456',
})

const { user: editedPassUser } = await editUserPasswordUseCase.execute({
userId: user.id,
newPassword: 'newAwesomePass',
oldPassword: '123456',
})

expect(editedPassUser.email).toEqual('[email protected]')
expect(editedPassUser.name).toEqual('John')

const isPasswordCorrectlyHashed = await compare(
'newAwesomePass',
editedPassUser.password_hash,
)

expect(isPasswordCorrectlyHashed).toBe(true)
})

it('should not be able to edit an user pass with the wrong old pass', async () => {
const { user } = await createUserUseCase.execute({
name: 'John',
surname: 'Doe',
email: '[email protected]',
password: '123456',
})

await expect(() =>
editUserPasswordUseCase.execute({
userId: user.id,
newPassword: 'newAwesomePass',
oldPassword: 'oldWrongPass',
}),
).rejects.toBeInstanceOf(InvalidCredentialsError)
})

it('should not be able to edit an user pass from an user that does not exist', async () => {
await expect(() =>
editUserPasswordUseCase.execute({
userId: randomUUID(),
newPassword: 'newAwesomePass',
oldPassword: 'oldWrongPass',
}),
).rejects.toBeInstanceOf(ResourceNotFoundError)
})
})
48 changes: 48 additions & 0 deletions src/use-cases/user/editUserPasswordUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { compare, hash } from 'bcryptjs'
import { UserRepository } from '../../repositories/user-repository'
import { User } from '@prisma/client'
import { ResourceNotFoundError } from '../errors/ResourceNotFoundError'
import { InvalidCredentialsError } from '../errors/InvalidCredentialsError'

interface EditUserPasswordUseCaseRequest {
userId: string
oldPassword: string
newPassword: string
}

interface EditUserPasswordUseCaseResponse {
user: User
}

export class EditUserPasswordUseCase {
constructor(private userRepository: UserRepository) {}

async execute({
userId,
newPassword,
oldPassword,
}: EditUserPasswordUseCaseRequest): Promise<EditUserPasswordUseCaseResponse> {
const user = await this.userRepository.findById(userId)

if (!user) {
throw new ResourceNotFoundError()
}

const passwordMatched = await compare(oldPassword, user.password_hash)

if (!passwordMatched) {
throw new InvalidCredentialsError('Email e/ou senha inválido.')
}

const password_hash = await hash(newPassword, 6)

const userUpdated = await this.userRepository.editPassword({
userId,
password_hash,
})

return {
user: userUpdated,
}
}
}

0 comments on commit 6dd34ff

Please sign in to comment.