From c040a247e7723406637a298af3bb7d8b85f4af93 Mon Sep 17 00:00:00 2001 From: David Arranz Date: Mon, 20 May 2024 10:59:15 +0200 Subject: [PATCH] . --- .../common/domain/entities/Password.ts | 4 +- .../sequelize/SequelizeRepository.ts | 10 +-- .../users/application/CreateUser.useCase.ts | 84 +++++++++++-------- .../repository/UserRepository.interface.ts | 9 +- .../users/infrastructure/User.repository.ts | 17 +++- 5 files changed, 76 insertions(+), 48 deletions(-) diff --git a/server/src/contexts/common/domain/entities/Password.ts b/server/src/contexts/common/domain/entities/Password.ts index b3673bd..eee60e6 100644 --- a/server/src/contexts/common/domain/entities/Password.ts +++ b/server/src/contexts/common/domain/entities/Password.ts @@ -57,7 +57,7 @@ export class Password extends StringValueObject { return Result.ok(new Password(validationResult.object)); } - public static async createFromPlainTextPassword( + public static createFromPlainTextPassword( value: UndefinedOr, options: IPasswordOptions = {}, ) { @@ -79,7 +79,7 @@ export class Password extends StringValueObject { } return Result.ok( - new Password(await Password.hashPassword(validationResult.object)), + new Password(Password.hashPassword(validationResult.object)), ); } diff --git a/server/src/contexts/common/infrastructure/sequelize/SequelizeRepository.ts b/server/src/contexts/common/infrastructure/sequelize/SequelizeRepository.ts index 1a1991d..f6e550c 100644 --- a/server/src/contexts/common/infrastructure/sequelize/SequelizeRepository.ts +++ b/server/src/contexts/common/infrastructure/sequelize/SequelizeRepository.ts @@ -126,14 +126,14 @@ export abstract class SequelizeRepository implements IRepository { ): Promise { const _model = this.adapter.getModel(modelName); - if (await this._exists(modelName, "id", id.toString())) { + if (await this._exists(modelName, "id", id.toPrimitive())) { await _model.update( { ...data, id: undefined, }, { - where: { id: id.toString() }, + where: { id: id.toPrimitive() }, transaction: this.transaction, ...params, }, @@ -142,7 +142,7 @@ export abstract class SequelizeRepository implements IRepository { await _model.create( { ...data, - id: id.toString(), + id: id.toPrimitive(), }, { include: [{ all: true }], @@ -163,7 +163,7 @@ export abstract class SequelizeRepository implements IRepository { await model.destroy({ where: { - id: id.toString(), + id: id.toPrimitive(), }, transaction: this.transaction, force, @@ -192,7 +192,7 @@ export abstract class SequelizeRepository implements IRepository { modelName: string, ids: UniqueID[] | string[] ): Promise { - const _ids = ids.map((id: UniqueID | string) => id.toString()); + const _ids = ids.map((id: UniqueID | string) => id.toPrimitive()); const destroyedRows: Promise = await this.adapter.models[ modelName diff --git a/server/src/contexts/users/application/CreateUser.useCase.ts b/server/src/contexts/users/application/CreateUser.useCase.ts index 61bd1d5..43dedc1 100644 --- a/server/src/contexts/users/application/CreateUser.useCase.ts +++ b/server/src/contexts/users/application/CreateUser.useCase.ts @@ -3,7 +3,7 @@ import { IUseCaseError, UseCaseError, } from "@/contexts/common/application"; -import { IRepositoryManager } from "@/contexts/common/domain"; +import { IRepositoryManager, Password } from "@/contexts/common/domain"; import { IInfrastructureError } from "@/contexts/common/infrastructure"; import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; import { @@ -12,14 +12,13 @@ import { ICreateUser_Request_DTO, IDomainError, Name, - Password, Result, UniqueID, ensureEmailIsValid, ensureIdIsValid, + ensureNameIsValid, } from "@shared/contexts"; import { IUserRepository, User } from "../domain"; -import { existsUserByEmail, existsUserByID } from "./userServices"; export type CreateUserResponseOrError = | Result // Misc errors (value objects) @@ -41,15 +40,12 @@ export class CreateUserUseCase } async execute(request: ICreateUser_Request_DTO) { - const { id, email } = request; - - const userRepository = this._getUserRepository(); + const { id, name, email } = request; // Validaciones de datos - - const userIdOrError = ensureIdIsValid(id); - if (userIdOrError.isFailure) { - const message = userIdOrError.error.message; //`User ID ${userDTO.id} is not valid`; + const idOrError = ensureIdIsValid(id); + if (idOrError.isFailure) { + const message = idOrError.error.message; //`User ID ${userDTO.id} is not valid`; return Result.fail( UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [ { path: "id" }, @@ -57,13 +53,32 @@ export class CreateUserUseCase ); } - const idExists = await existsUserByID( - userIdOrError.object, - this._adapter, - userRepository, - ); + const nameOrError = ensureNameIsValid(name); + if (nameOrError.isFailure) { + const message = nameOrError.error.message; //`User ID ${userDTO.id} is not valid`; + return Result.fail( + UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [ + { path: "name" }, + ]), + ); + } + + const emailOrError = ensureEmailIsValid(email); + if (emailOrError.isFailure) { + const message = emailOrError.error.message; + return Result.fail( + UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [ + { path: "email" }, + ]), + ); + } + + // Comprobar que no existe un usuario previo con esos datos + const userRepository = this._getUserRepository(); + + const idExists = await userRepository().existsUserWithId(idOrError.object); if (idExists) { - const message = `Another user with ID ${id} exists`; + const message = `Another user with same ID exists`; return Result.fail( UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, { path: "id", @@ -71,38 +86,33 @@ export class CreateUserUseCase ); } - const emailOrError = ensureEmailIsValid(email); - if (emailOrError.isFailure) { + const nameExists = await userRepository().existsUserWithName( + nameOrError.object, + ); + if (nameExists) { + const message = `Another user with same name exists`; return Result.fail( - UseCaseError.create( - UseCaseError.INVALID_INPUT_DATA, - "Email or password is not valid", - emailOrError.error, - ), + UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, { + path: "name", + }), ); } - const emailExists = await existsUserByEmail( + const emailExists = await userRepository().existsUserWithEmail( emailOrError.object, - this._adapter, - userRepository, ); if (emailExists) { + const message = `Another user with same email exists`; return Result.fail( - UseCaseError.create( - UseCaseError.RESOURCE_ALREADY_EXITS, - `Another user with email ${email} exists`, - { path: "email" }, - ), + UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, { + path: "email", + }), ); } // Crear user - const userOrError = this._tryCreateUserInstance( - request, - userIdOrError.object, - ); + const userOrError = this._tryCreateUserInstance(request, idOrError.object); if (userOrError.isFailure) { const { error: domainError } = userOrError; @@ -180,7 +190,9 @@ export class CreateUserUseCase return Result.fail(emailOrError.error); } - const passwordOrError = Password.createFromPlainText(userDTO.password); + const passwordOrError = Password.createFromPlainTextPassword( + userDTO.password, + ); if (passwordOrError.isFailure) { return Result.fail(passwordOrError.error); } diff --git a/server/src/contexts/users/domain/repository/UserRepository.interface.ts b/server/src/contexts/users/domain/repository/UserRepository.interface.ts index 1fc8ff1..7c6b21d 100644 --- a/server/src/contexts/users/domain/repository/UserRepository.interface.ts +++ b/server/src/contexts/users/domain/repository/UserRepository.interface.ts @@ -1,5 +1,11 @@ import { IRepository } from "@/contexts/common/domain"; -import { Email, ICollection, IQueryCriteria, UniqueID } from "@shared/contexts"; +import { + Email, + ICollection, + IQueryCriteria, + Name, + UniqueID, +} from "@shared/contexts"; import { User } from "../entities"; export interface IUserRepository extends IRepository { @@ -13,5 +19,6 @@ export interface IUserRepository extends IRepository { removeById(id: UniqueID): Promise; existsUserWithId(id: UniqueID): Promise; + existsUserWithName(name: Name): Promise; existsUserWithEmail(email: Email): Promise; } diff --git a/server/src/contexts/users/infrastructure/User.repository.ts b/server/src/contexts/users/infrastructure/User.repository.ts index 3bef551..c272c45 100644 --- a/server/src/contexts/users/infrastructure/User.repository.ts +++ b/server/src/contexts/users/infrastructure/User.repository.ts @@ -2,7 +2,13 @@ import { ISequelizeAdapter, SequelizeRepository, } from "@/contexts/common/infrastructure/sequelize"; -import { Email, ICollection, IQueryCriteria, UniqueID } from "@shared/contexts"; +import { + Email, + ICollection, + IQueryCriteria, + Name, + UniqueID, +} from "@shared/contexts"; import { Transaction } from "sequelize"; import { User } from "../domain"; import { IUserRepository } from "../domain/repository"; @@ -40,7 +46,6 @@ export class UserRepository // borrando y luego creando await this.removeById(user.id, true); - await this._save("User_Model", user.id, userData, {}); } @@ -87,11 +92,15 @@ export class UserRepository } public async existsUserWithId(id: UniqueID): Promise { - return this._exists("User_Model", "id", id.toString()); + return this._exists("User_Model", "id", id.toPrimitive()); + } + + public async existsUserWithName(name: Name): Promise { + return this._exists("User_Model", "name", name.toPrimitive()); } public async existsUserWithEmail(email: Email): Promise { - return this._exists("User_Model", "email", email.toString()); + return this._exists("User_Model", "email", email.toPrimitive()); } }