.
This commit is contained in:
parent
923bd92220
commit
1685a44fc2
@ -8,7 +8,7 @@ import {
|
|||||||
import { IRepositoryManager } from "@/contexts/common/domain";
|
import { IRepositoryManager } from "@/contexts/common/domain";
|
||||||
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
||||||
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import { Result, ensureUserEmailIsValid } from "@shared/contexts";
|
import { Result, ensureEmailIsValid } from "@shared/contexts";
|
||||||
import { AuthUser } from "../domain";
|
import { AuthUser } from "../domain";
|
||||||
import { findUserByEmail } from "./authServices";
|
import { findUserByEmail } from "./authServices";
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ export class FindUserByEmailUseCase
|
|||||||
|
|
||||||
// Validaciones de datos
|
// Validaciones de datos
|
||||||
|
|
||||||
const emailOrError = ensureUserEmailIsValid(email);
|
const emailOrError = ensureEmailIsValid(email);
|
||||||
if (emailOrError.isFailure) {
|
if (emailOrError.isFailure) {
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleUseCaseError(
|
handleUseCaseError(
|
||||||
@ -57,7 +57,6 @@ export class FindUserByEmailUseCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear auth
|
|
||||||
try {
|
try {
|
||||||
const user = await findUserByEmail(
|
const user = await findUserByEmail(
|
||||||
emailOrError.object,
|
emailOrError.object,
|
||||||
|
|||||||
@ -8,11 +8,9 @@ export const findUserByEmail = async (
|
|||||||
adapter: IAdapter,
|
adapter: IAdapter,
|
||||||
repository: RepositoryBuilder<IAuthRepository>,
|
repository: RepositoryBuilder<IAuthRepository>,
|
||||||
): Promise<AuthUser | null> => {
|
): Promise<AuthUser | null> => {
|
||||||
const user = await adapter
|
return await adapter
|
||||||
.startTransaction()
|
.startTransaction()
|
||||||
.complete(async (t) =>
|
.complete(async (t) =>
|
||||||
repository({ transaction: t }).findUserByEmail(email),
|
repository({ transaction: t }).findUserByEmail(email),
|
||||||
);
|
);
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -46,15 +46,9 @@ export abstract class ExpressController implements IController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fail(error: IServerError) {
|
public fail(error: IServerError) {
|
||||||
console.group("ExpressController FAIL RESPONSE ====================");
|
console.error("ExpressController FAIL RESPONSE:", error);
|
||||||
console.log(error);
|
|
||||||
console.trace("Show me");
|
|
||||||
console.groupEnd();
|
|
||||||
|
|
||||||
return this._errorResponse(
|
return this._errorResponse(httpStatus.INTERNAL_SERVER_ERROR, error.message);
|
||||||
httpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
error ? error.toString() : "Fail",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public created<T>(dto?: T) {
|
public created<T>(dto?: T) {
|
||||||
|
|||||||
@ -14,25 +14,12 @@ export const generateExpressErrorResponse = (
|
|||||||
message?: string,
|
message?: string,
|
||||||
error?: Error | InfrastructureError,
|
error?: Error | InfrastructureError,
|
||||||
): Express.Response<IError_Response_DTO> => {
|
): Express.Response<IError_Response_DTO> => {
|
||||||
const context = {};
|
const context = {
|
||||||
|
user: res.locals.user || undefined,
|
||||||
if (Object.keys(res.locals).length) {
|
params: req.params || undefined,
|
||||||
if ("user" in res.locals) {
|
query: req.query || undefined,
|
||||||
context["user"] = res.locals.user;
|
body: req.body || undefined,
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(req.params).length) {
|
|
||||||
context["params"] = req.params;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(req.query).length) {
|
|
||||||
context["query"] = req.query;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(req.body).length) {
|
|
||||||
context["body"] = req.body;
|
|
||||||
}
|
|
||||||
|
|
||||||
const extension = new ProblemDocumentExtension({
|
const extension = new ProblemDocumentExtension({
|
||||||
context,
|
context,
|
||||||
@ -54,11 +41,11 @@ export const generateExpressErrorResponse = (
|
|||||||
function generateExpressError(
|
function generateExpressError(
|
||||||
error: Error | InfrastructureError,
|
error: Error | InfrastructureError,
|
||||||
): IErrorExtra_Response_DTO {
|
): IErrorExtra_Response_DTO {
|
||||||
const useCaseError = <UseCaseError>error;
|
const useCaseError = error as UseCaseError;
|
||||||
|
|
||||||
const payload = !Array.isArray(useCaseError.payload)
|
const payload = Array.isArray(useCaseError.payload)
|
||||||
? Array(useCaseError.payload)
|
? useCaseError.payload
|
||||||
: useCaseError.payload;
|
: [useCaseError.payload];
|
||||||
|
|
||||||
const errors = payload.map((item) => {
|
const errors = payload.map((item) => {
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
|
|||||||
@ -2,54 +2,30 @@ import {
|
|||||||
IUseCase,
|
IUseCase,
|
||||||
IUseCaseError,
|
IUseCaseError,
|
||||||
UseCaseError,
|
UseCaseError,
|
||||||
handleInvalidInputDataFailure,
|
|
||||||
handleResourceAlreadyExitsFailure,
|
|
||||||
handleUseCaseError,
|
handleUseCaseError,
|
||||||
} from "@/contexts/common/application/useCases";
|
} from "@/contexts/common/application";
|
||||||
import { IRepositoryManager } from "@/contexts/common/domain";
|
import { IRepositoryManager } from "@/contexts/common/domain";
|
||||||
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||||
import {
|
import {
|
||||||
AddressTitle,
|
Email,
|
||||||
City,
|
ICreateUser_Request_DTO,
|
||||||
Collection,
|
|
||||||
Country,
|
|
||||||
DomainError,
|
|
||||||
ICreateUser_DTO,
|
|
||||||
IDomainError,
|
IDomainError,
|
||||||
Note,
|
Name,
|
||||||
PostalCode,
|
|
||||||
Province,
|
|
||||||
Result,
|
Result,
|
||||||
ResultCollection,
|
|
||||||
Street,
|
|
||||||
UniqueID,
|
UniqueID,
|
||||||
UserEmail,
|
ensureIdIsValid,
|
||||||
UserJobTitle,
|
ensureUserEmailIsValid,
|
||||||
UserName,
|
|
||||||
UserPhone,
|
|
||||||
UserTIN,
|
|
||||||
ensureUserIdIsValid,
|
|
||||||
ensureUserTINIsValid,
|
|
||||||
} from "@shared/contexts";
|
} from "@shared/contexts";
|
||||||
|
import { IUserRepository, User } from "../domain";
|
||||||
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
import { existsUserByEmail, existsUserByID } from "./userServices";
|
||||||
import {
|
|
||||||
IBillingAddressUser_DTO,
|
|
||||||
IShippingAddressUser_DTO,
|
|
||||||
} from "@shared/contexts/users/application/dto/IUserAddressDTO";
|
|
||||||
import {
|
|
||||||
IUserRepository,
|
|
||||||
User,
|
|
||||||
UserBillingAddress as UserShippingAddress,
|
|
||||||
} from "../domain";
|
|
||||||
import { UserAddressType } from "../domain/entities/UserAddress";
|
|
||||||
|
|
||||||
export type CreateUserResponseOrError =
|
export type CreateUserResponseOrError =
|
||||||
| Result<never, IUseCaseError> // Misc errors (value objects)
|
| Result<never, IUseCaseError> // Misc errors (value objects)
|
||||||
| Result<User, never>; // Success!
|
| Result<User, never>; // Success!
|
||||||
|
|
||||||
export class CreateUserUseCase
|
export class CreateUserUseCase
|
||||||
implements IUseCase<ICreateUser_DTO, Promise<CreateUserResponseOrError>>
|
implements
|
||||||
|
IUseCase<ICreateUser_Request_DTO, Promise<CreateUserResponseOrError>>
|
||||||
{
|
{
|
||||||
private _adapter: ISequelizeAdapter;
|
private _adapter: ISequelizeAdapter;
|
||||||
private _repositoryManager: IRepositoryManager;
|
private _repositoryManager: IRepositoryManager;
|
||||||
@ -66,43 +42,65 @@ export class CreateUserUseCase
|
|||||||
return this._repositoryManager.getRepository<T>(name);
|
return this._repositoryManager.getRepository<T>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(request: ICreateUser_DTO): Promise<CreateUserResponseOrError> {
|
async execute(
|
||||||
|
request: ICreateUser_Request_DTO,
|
||||||
|
): Promise<CreateUserResponseOrError> {
|
||||||
const userDTO = request;
|
const userDTO = request;
|
||||||
|
|
||||||
|
const userRepository = this.getRepositoryByName<IUserRepository>("User");
|
||||||
|
|
||||||
// Validaciones de datos
|
// Validaciones de datos
|
||||||
|
|
||||||
const userIdOrError = ensureUserIdIsValid(userDTO.id);
|
const userIdOrError = ensureIdIsValid(userDTO.id);
|
||||||
if (userIdOrError.isFailure) {
|
if (userIdOrError.isFailure) {
|
||||||
return handleInvalidInputDataFailure(
|
return Result.fail(
|
||||||
"User ID is not valid",
|
handleUseCaseError(
|
||||||
userIdOrError.error,
|
UseCaseError.INVALID_INPUT_DATA,
|
||||||
|
"User ID is not valid",
|
||||||
|
userIdOrError.error,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const idExists = await this.findUserID(userIdOrError.object);
|
const idExists = await existsUserByID(
|
||||||
|
userIdOrError.object,
|
||||||
|
this._adapter,
|
||||||
|
userRepository,
|
||||||
|
);
|
||||||
if (idExists) {
|
if (idExists) {
|
||||||
return handleResourceAlreadyExitsFailure(
|
return Result.fail(
|
||||||
`Another user with ID ${userDTO.id} exists`,
|
handleUseCaseError(
|
||||||
userIdOrError.error,
|
UseCaseError.RESOURCE_ALREADY_EXITS,
|
||||||
|
`Another user with ID ${userDTO.id} exists`,
|
||||||
|
userIdOrError.error,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tinOrError = ensureUserTINIsValid(userDTO.tin);
|
const emailOrError = ensureUserEmailIsValid(userDTO.email);
|
||||||
if (tinOrError.isFailure) {
|
if (emailOrError.isFailure) {
|
||||||
return handleInvalidInputDataFailure(
|
return Result.fail(
|
||||||
`User TIN is not valid: ${tinOrError.error.message}`,
|
handleUseCaseError(
|
||||||
userIdOrError.error,
|
UseCaseError.INVALID_INPUT_DATA,
|
||||||
|
"Email or password is not valid",
|
||||||
|
emailOrError.error,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tinExists =
|
const emailExists = await existsUserByEmail(
|
||||||
!tinOrError.object.isEmpty() &&
|
emailOrError.object,
|
||||||
(await this.findUserTIN(tinOrError.object));
|
this._adapter,
|
||||||
|
userRepository,
|
||||||
|
);
|
||||||
|
|
||||||
if (tinExists) {
|
if (emailExists) {
|
||||||
return handleResourceAlreadyExitsFailure(
|
return Result.fail(
|
||||||
`User with TIN ${tinOrError.object.toString()} exists`,
|
handleUseCaseError(
|
||||||
userIdOrError.error,
|
UseCaseError.RESOURCE_ALREADY_EXITS,
|
||||||
|
`Another user with email ${userDTO.email} exists`,
|
||||||
|
userIdOrError.error,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,10 +140,10 @@ export class CreateUserUseCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.createUser(userOrError.object);
|
return this.saveUser(userOrError.object);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createUser(user: User) {
|
private async saveUser(user: User) {
|
||||||
// Guardar el contacto
|
// Guardar el contacto
|
||||||
const transaction = this._adapter.startTransaction();
|
const transaction = this._adapter.startTransaction();
|
||||||
const userRepoBuilder = this.getRepositoryByName<IUserRepository>("User");
|
const userRepoBuilder = this.getRepositoryByName<IUserRepository>("User");
|
||||||
@ -170,197 +168,26 @@ export class CreateUserUseCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findUserID(id: UniqueID) {
|
|
||||||
const userRepoBuilder = this.getRepositoryByName<IUserRepository>("User");
|
|
||||||
return await userRepoBuilder().exists(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async findUserTIN(tin: UserTIN) {
|
|
||||||
const userRepoBuilder = this.getRepositoryByName<IUserRepository>("User");
|
|
||||||
return await userRepoBuilder().existsWithSameTIN(tin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private tryCreateUserInstance(
|
private tryCreateUserInstance(
|
||||||
userDTO: ICreateUser_DTO,
|
userDTO: ICreateUser_Request_DTO,
|
||||||
userId: UniqueID,
|
userId: UniqueID,
|
||||||
): Result<User, IDomainError> {
|
): Result<User, IDomainError> {
|
||||||
const userTINOrError = ensureUserTINIsValid(userDTO.tin);
|
const nameOrError = Name.create(userDTO.name);
|
||||||
if (userTINOrError.isFailure) {
|
if (nameOrError.isFailure) {
|
||||||
return Result.fail(userTINOrError.error);
|
return Result.fail(nameOrError.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const companyNameOrError = UserName.create(userDTO.company_name);
|
const emailOrError = Email.create(userDTO.email);
|
||||||
if (companyNameOrError.isFailure) {
|
|
||||||
return Result.fail(companyNameOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const firstNameOrError = UserName.create(userDTO.first_name);
|
|
||||||
if (firstNameOrError.isFailure) {
|
|
||||||
return Result.fail(firstNameOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastNameOrError = UserName.create(userDTO.last_name);
|
|
||||||
if (lastNameOrError.isFailure) {
|
|
||||||
return Result.fail(lastNameOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const jobTitleOrError = UserJobTitle.create(userDTO.job_title);
|
|
||||||
if (jobTitleOrError.isFailure) {
|
|
||||||
return Result.fail(jobTitleOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailOrError = UserEmail.create(userDTO.email);
|
|
||||||
if (emailOrError.isFailure) {
|
if (emailOrError.isFailure) {
|
||||||
return Result.fail(emailOrError.error);
|
return Result.fail(emailOrError.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const phoneOrError = UserPhone.create(userDTO.phone);
|
|
||||||
if (phoneOrError.isFailure) {
|
|
||||||
return Result.fail(phoneOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*const taxIdOrError = UniqueID.create(userDTO.tax_id);
|
|
||||||
if (taxIdOrError.isFailure) {
|
|
||||||
return Result.fail(taxIdOrError.error);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const notesOrError = Note.create(userDTO.notes);
|
|
||||||
if (notesOrError.isFailure) {
|
|
||||||
return Result.fail(notesOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Billing address
|
|
||||||
const billingAddressOrError = this.tryCreateUserAddress(
|
|
||||||
userDTO.billing_address,
|
|
||||||
"billing",
|
|
||||||
);
|
|
||||||
if (billingAddressOrError.isFailure) {
|
|
||||||
return Result.fail(billingAddressOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shipping address
|
|
||||||
const shippingAddressesOrError = this.tryCreateUserShippingAddresses(
|
|
||||||
userDTO.shipping_addresses,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shippingAddressesOrError.isFailure) {
|
|
||||||
return Result.fail(shippingAddressesOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return User.create(
|
return User.create(
|
||||||
{
|
{
|
||||||
tin: userTINOrError.object,
|
name: nameOrError.object,
|
||||||
companyName: companyNameOrError.object,
|
|
||||||
firstName: firstNameOrError.object,
|
|
||||||
lastName: lastNameOrError.object,
|
|
||||||
jobTitle: jobTitleOrError.object,
|
|
||||||
email: emailOrError.object,
|
email: emailOrError.object,
|
||||||
phone: phoneOrError.object,
|
|
||||||
//taxId: taxIdOrError.object,
|
|
||||||
notes: notesOrError.object,
|
|
||||||
|
|
||||||
billingAddress: billingAddressOrError.object,
|
|
||||||
shippingAddresses: shippingAddressesOrError.object,
|
|
||||||
},
|
},
|
||||||
userId,
|
userId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private tryCreateUserShippingAddresses(
|
|
||||||
addressesDTO: IShippingAddressUser_DTO[] | undefined,
|
|
||||||
) {
|
|
||||||
const shippingAddressesOrError = new ResultCollection<
|
|
||||||
UserShippingAddress,
|
|
||||||
DomainError
|
|
||||||
>();
|
|
||||||
|
|
||||||
if (addressesDTO) {
|
|
||||||
addressesDTO.map((value, index) => {
|
|
||||||
const result = this.tryCreateUserAddress(value, "shipping");
|
|
||||||
if (result.error) {
|
|
||||||
const { path } = result.error.payload;
|
|
||||||
const newPath = `shipping_addresses.${index}.${path}`;
|
|
||||||
|
|
||||||
result.error.payload.path = newPath;
|
|
||||||
}
|
|
||||||
shippingAddressesOrError.add(result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shippingAddressesOrError.hasSomeFaultyResult()) {
|
|
||||||
return Result.fail(shippingAddressesOrError.getFirstFaultyResult().error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(new Collection(shippingAddressesOrError.objects));
|
|
||||||
}
|
|
||||||
|
|
||||||
private tryCreateUserAddress(
|
|
||||||
addressDTO: IBillingAddressUser_DTO | IShippingAddressUser_DTO | undefined,
|
|
||||||
addressType: UserAddressType,
|
|
||||||
) {
|
|
||||||
const titleOrError = AddressTitle.create(addressDTO?.title);
|
|
||||||
if (titleOrError.isFailure) {
|
|
||||||
return Result.fail(titleOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const streetOrError = Street.create(addressDTO?.street);
|
|
||||||
if (streetOrError.isFailure) {
|
|
||||||
return Result.fail(streetOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const postalCodeOrError = PostalCode.create(addressDTO?.postal_code);
|
|
||||||
if (postalCodeOrError.isFailure) {
|
|
||||||
return Result.fail(postalCodeOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cityOrError = City.create(addressDTO?.city);
|
|
||||||
if (cityOrError.isFailure) {
|
|
||||||
return Result.fail(cityOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const provinceOrError = Province.create(addressDTO?.province);
|
|
||||||
if (provinceOrError.isFailure) {
|
|
||||||
return Result.fail(provinceOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const countryOrError = Country.create(addressDTO?.country);
|
|
||||||
if (countryOrError.isFailure) {
|
|
||||||
return Result.fail(countryOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailOrError = UserEmail.create(addressDTO?.email, {
|
|
||||||
label: "email",
|
|
||||||
path: "email",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (emailOrError.isFailure) {
|
|
||||||
return Result.fail(emailOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const phoneOrError = UserPhone.create(addressDTO?.phone);
|
|
||||||
if (phoneOrError.isFailure) {
|
|
||||||
return Result.fail(phoneOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const notesOrError = Note.create(addressDTO?.notes);
|
|
||||||
if (notesOrError.isFailure) {
|
|
||||||
return Result.fail(notesOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const addressProps = {
|
|
||||||
title: titleOrError.object,
|
|
||||||
street: streetOrError.object,
|
|
||||||
city: cityOrError.object,
|
|
||||||
province: provinceOrError.object,
|
|
||||||
postalCode: postalCodeOrError.object,
|
|
||||||
country: countryOrError.object,
|
|
||||||
email: emailOrError.object,
|
|
||||||
phone: phoneOrError.object,
|
|
||||||
notes: notesOrError.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
return addressType === "billing"
|
|
||||||
? UserShippingAddress.create(addressProps)
|
|
||||||
: UserShippingAddress.create(addressProps);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
export * from "./CreateUser.useCase";
|
||||||
export * from "./DeleteUser.useCase";
|
export * from "./DeleteUser.useCase";
|
||||||
export * from "./GetUser.useCase";
|
export * from "./GetUser.useCase";
|
||||||
export * from "./ListUsers.useCase";
|
export * from "./ListUsers.useCase";
|
||||||
//export * from "./CreateUser.useCase";
|
export * from "./UpdateUser.useCase";
|
||||||
//export * from "./UpdateUser.useCase";
|
|
||||||
|
|||||||
47
server/src/contexts/users/application/userServices.ts
Normal file
47
server/src/contexts/users/application/userServices.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { IAdapter, RepositoryBuilder } from "@/contexts/common/domain";
|
||||||
|
import { Email, UniqueID } from "@shared/contexts";
|
||||||
|
import { IUserRepository, User } from "../domain";
|
||||||
|
|
||||||
|
export const existsUserByID = async (
|
||||||
|
id: UniqueID,
|
||||||
|
adapter: IAdapter,
|
||||||
|
repository: RepositoryBuilder<IUserRepository>,
|
||||||
|
): Promise<boolean> => {
|
||||||
|
return await adapter
|
||||||
|
.startTransaction()
|
||||||
|
.complete(async (t) => repository({ transaction: t }).existsUserWithId(id));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findUserByID = async (
|
||||||
|
id: UniqueID,
|
||||||
|
adapter: IAdapter,
|
||||||
|
repository: RepositoryBuilder<IUserRepository>,
|
||||||
|
): Promise<User | null> => {
|
||||||
|
return await adapter
|
||||||
|
.startTransaction()
|
||||||
|
.complete(async (t) => repository({ transaction: t }).getById(id));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const existsUserByEmail = async (
|
||||||
|
email: Email,
|
||||||
|
adapter: IAdapter,
|
||||||
|
repository: RepositoryBuilder<IUserRepository>,
|
||||||
|
): Promise<boolean> => {
|
||||||
|
return await adapter
|
||||||
|
.startTransaction()
|
||||||
|
.complete(async (t) =>
|
||||||
|
repository({ transaction: t }).existsUserWithEmail(email),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findUserByEmail = async (
|
||||||
|
email: Email,
|
||||||
|
adapter: IAdapter,
|
||||||
|
repository: RepositoryBuilder<IUserRepository>,
|
||||||
|
): Promise<User | null> => {
|
||||||
|
return await adapter
|
||||||
|
.startTransaction()
|
||||||
|
.complete(async (t) =>
|
||||||
|
repository({ transaction: t }).findUserByEmail(email),
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,12 +1,14 @@
|
|||||||
import { IRepository } from "@/contexts/common/domain";
|
import { IRepository } from "@/contexts/common/domain";
|
||||||
import { ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
|
import { Email, ICollection, IQueryCriteria, UniqueID } from "@shared/contexts";
|
||||||
import { User } from "../entities";
|
import { User } from "../entities";
|
||||||
|
|
||||||
export interface IUserRepository extends IRepository<any> {
|
export interface IUserRepository extends IRepository<any> {
|
||||||
getById(id: UniqueID): Promise<User | null>;
|
getById(id: UniqueID): Promise<User | null>;
|
||||||
|
findUserByEmail(email: Email): Promise<User | null>;
|
||||||
findAll(queryCriteria?: IQueryCriteria): Promise<ICollection<User>>;
|
findAll(queryCriteria?: IQueryCriteria): Promise<ICollection<User>>;
|
||||||
|
|
||||||
removeById(id: UniqueID): Promise<void>;
|
removeById(id: UniqueID): Promise<void>;
|
||||||
|
|
||||||
exists(id: UniqueID): Promise<boolean>;
|
existsUserWithId(id: UniqueID): Promise<boolean>;
|
||||||
|
existsUserWithEmail(email: Email): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,9 +72,13 @@ export class UserRepository
|
|||||||
return this._removeById("User_Model", id);
|
return this._removeById("User_Model", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async exists(id: UniqueID): Promise<boolean> {
|
public async existsUserWithId(id: UniqueID): Promise<boolean> {
|
||||||
return this._exists("User_Model", "id", id.toString());
|
return this._exists("User_Model", "id", id.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async existsUserWithEmail(email: Email): Promise<boolean> {
|
||||||
|
return this._exists("User_Model", "email", email.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const registerUserRepository = (context: IUserContext) => {
|
export const registerUserRepository = (context: IUserContext) => {
|
||||||
|
|||||||
@ -0,0 +1,120 @@
|
|||||||
|
import { IUseCaseError, UseCaseError } from "@/contexts/common/application";
|
||||||
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
|
import {
|
||||||
|
IInfrastructureError,
|
||||||
|
InfrastructureError,
|
||||||
|
handleInfrastructureError,
|
||||||
|
} from "@/contexts/common/infrastructure";
|
||||||
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
|
import {
|
||||||
|
CreateUserResponseOrError,
|
||||||
|
CreateUserUseCase,
|
||||||
|
} from "@/contexts/users/application";
|
||||||
|
import { User } from "@/contexts/users/domain";
|
||||||
|
import {
|
||||||
|
ICreateUser_Request_DTO,
|
||||||
|
ICreateUser_Response_DTO,
|
||||||
|
ensureCreateUser_Request_DTOIsValid,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
import { ICreateUserPresenter } from "./presenter/CreateUser.presenter";
|
||||||
|
|
||||||
|
export class CreateUserController extends ExpressController {
|
||||||
|
private useCase: CreateUserUseCase;
|
||||||
|
private presenter: ICreateUserPresenter;
|
||||||
|
private context: IUserContext;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
props: {
|
||||||
|
useCase: CreateUserUseCase;
|
||||||
|
presenter: ICreateUserPresenter;
|
||||||
|
},
|
||||||
|
context: IUserContext,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const { useCase, presenter } = props;
|
||||||
|
this.useCase = useCase;
|
||||||
|
this.presenter = presenter;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeImpl(): Promise<any> {
|
||||||
|
try {
|
||||||
|
const userDTO: ICreateUser_Request_DTO = this.req.body;
|
||||||
|
|
||||||
|
// Validaciones de DTO
|
||||||
|
const userDTOOrError = ensureCreateUser_Request_DTOIsValid(userDTO);
|
||||||
|
|
||||||
|
if (userDTOOrError.isFailure) {
|
||||||
|
const errorMessage = "User data not valid";
|
||||||
|
const infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
userDTOOrError.error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Llamar al caso de uso
|
||||||
|
const result: CreateUserResponseOrError = await this.useCase.execute(
|
||||||
|
userDTO,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
return this._handleExecuteError(result.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = <User>result.object;
|
||||||
|
|
||||||
|
return this.created<ICreateUser_Response_DTO>(
|
||||||
|
this.presenter.map(user, this.context),
|
||||||
|
);
|
||||||
|
} catch (e: unknown) {
|
||||||
|
return this.fail(e as IServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleExecuteError(error: IUseCaseError) {
|
||||||
|
let errorMessage: string;
|
||||||
|
let infraError: IInfrastructureError;
|
||||||
|
|
||||||
|
switch (error.code) {
|
||||||
|
case UseCaseError.INVALID_INPUT_DATA:
|
||||||
|
errorMessage = "User data not valid";
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UseCaseError.RESOURCE_ALREADY_EXITS:
|
||||||
|
errorMessage = "User already exists";
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.conflictError(error.message, error);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UseCaseError.UNEXCEPTED_ERROR:
|
||||||
|
errorMessage = error.message;
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.UNEXCEPTED_ERROR,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.internalServerError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorMessage = error.message;
|
||||||
|
return this.clientError(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { CreateUserUseCase } from "@/contexts/users/application";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
import { registerUserRepository } from "../../../User.repository";
|
||||||
|
import { CreateUserController } from "./CreateUser.controller";
|
||||||
|
import { CreateUserPresenter } from "./presenter/CreateUser.presenter";
|
||||||
|
|
||||||
|
export const createCreateUserController = (context: IUserContext) => {
|
||||||
|
registerUserRepository(context);
|
||||||
|
|
||||||
|
return new CreateUserController(
|
||||||
|
{
|
||||||
|
useCase: new CreateUserUseCase(context),
|
||||||
|
presenter: CreateUserPresenter,
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { User } from "@/contexts/users/domain";
|
||||||
|
import { IUserContext } from "@/contexts/users/infrastructure/User.context";
|
||||||
|
import { ICreateUser_Response_DTO } from "@shared/contexts";
|
||||||
|
|
||||||
|
export interface ICreateUserPresenter {
|
||||||
|
map: (user: User, context: IUserContext) => ICreateUser_Response_DTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CreateUserPresenter: ICreateUserPresenter = {
|
||||||
|
map: (user: User, context: IUserContext): ICreateUser_Response_DTO => {
|
||||||
|
return {
|
||||||
|
id: user.id.toString(),
|
||||||
|
name: user.name.toString(),
|
||||||
|
email: user.email.toString(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./CreateUser.presenter";
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
IUseCaseError,
|
||||||
|
UseCaseError,
|
||||||
|
} from "@/contexts/common/application/useCases";
|
||||||
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
|
import {
|
||||||
|
IInfrastructureError,
|
||||||
|
InfrastructureError,
|
||||||
|
handleInfrastructureError,
|
||||||
|
} from "@/contexts/common/infrastructure";
|
||||||
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
|
import { DeleteUserUseCase } from "@/contexts/users/application";
|
||||||
|
import { ensureIdIsValid } from "@shared/contexts";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
|
||||||
|
export class DeleteUserController extends ExpressController {
|
||||||
|
private useCase: DeleteUserUseCase;
|
||||||
|
private context: IUserContext;
|
||||||
|
|
||||||
|
constructor(props: { useCase: DeleteUserUseCase }, context: IUserContext) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const { useCase } = props;
|
||||||
|
this.useCase = useCase;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeImpl(): Promise<any> {
|
||||||
|
try {
|
||||||
|
const { userId } = this.req.params;
|
||||||
|
|
||||||
|
// Validar ID
|
||||||
|
const userIdOrError = ensureIdIsValid(userId);
|
||||||
|
if (userIdOrError.isFailure) {
|
||||||
|
const errorMessage = "User ID is not valid";
|
||||||
|
const infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
userIdOrError.error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Llamar al caso de uso
|
||||||
|
const result = await this.useCase.execute({
|
||||||
|
id: userIdOrError.object,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
return this._handleExecuteError(result.error);
|
||||||
|
}
|
||||||
|
return this.noContent();
|
||||||
|
} catch (e: unknown) {
|
||||||
|
return this.fail(e as IServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleExecuteError(error: IUseCaseError) {
|
||||||
|
let errorMessage: string;
|
||||||
|
let infraError: IInfrastructureError;
|
||||||
|
|
||||||
|
switch (error.code) {
|
||||||
|
case UseCaseError.NOT_FOUND_ERROR:
|
||||||
|
errorMessage = "User not found";
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.RESOURCE_NOT_FOUND_ERROR,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.notFoundError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UseCaseError.UNEXCEPTED_ERROR:
|
||||||
|
errorMessage = error.message;
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.UNEXCEPTED_ERROR,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.internalServerError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorMessage = error.message;
|
||||||
|
return this.clientError(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { DeleteUserUseCase } from "@/contexts/users/application";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
import { registerUserRepository } from "../../../User.repository";
|
||||||
|
import { DeleteUserController } from "./DeleteUser.controller";
|
||||||
|
|
||||||
|
export const createDeleteUserController = (context: IUserContext) => {
|
||||||
|
registerUserRepository(context);
|
||||||
|
return new DeleteUserController(
|
||||||
|
{
|
||||||
|
useCase: new DeleteUserUseCase(context),
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -5,7 +5,7 @@ import {
|
|||||||
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
import { GetUserUseCase } from "@/contexts/users/application";
|
import { GetUserUseCase } from "@/contexts/users/application";
|
||||||
import { User } from "@/contexts/users/domain/entities/User";
|
import { User } from "@/contexts/users/domain/entities/User";
|
||||||
import { IGetUser_Response_DTO, ensureIdIsValid } from "@shared/contexts";
|
import { IGetUserResponse_DTO, ensureIdIsValid } from "@shared/contexts";
|
||||||
|
|
||||||
import { IServerError } from "@/contexts/common/domain/errors";
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
import {
|
import {
|
||||||
@ -62,7 +62,7 @@ export class GetUserController extends ExpressController {
|
|||||||
|
|
||||||
const user = <User>result.object;
|
const user = <User>result.object;
|
||||||
|
|
||||||
return this.ok<IGetUser_Response_DTO>(
|
return this.ok<IGetUserResponse_DTO>(
|
||||||
this.presenter.map(user, this.context),
|
this.presenter.map(user, this.context),
|
||||||
);
|
);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { IGetUser_Response_DTO } from "@shared/contexts";
|
import { IGetUserResponse_DTO } from "@shared/contexts";
|
||||||
import { User } from "../../../../../domain";
|
import { User } from "../../../../../domain";
|
||||||
import { IUserContext } from "../../../../User.context";
|
import { IUserContext } from "../../../../User.context";
|
||||||
|
|
||||||
export interface IGetUserPresenter {
|
export interface IGetUserPresenter {
|
||||||
map: (user: User, context: IUserContext) => IGetUser_Response_DTO;
|
map: (user: User, context: IUserContext) => IGetUserResponse_DTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GetUserPresenter: IGetUserPresenter = {
|
export const GetUserPresenter: IGetUserPresenter = {
|
||||||
map: (user: User, context: IUserContext): IGetUser_Response_DTO => {
|
map: (user: User, context: IUserContext): IGetUserResponse_DTO => {
|
||||||
return {
|
return {
|
||||||
id: user.id.toString(),
|
id: user.id.toString(),
|
||||||
name: user.name.toString(),
|
name: user.name.toString(),
|
||||||
|
|||||||
@ -1,2 +1,5 @@
|
|||||||
|
export * from "./createUser";
|
||||||
|
export * from "./deleteUser";
|
||||||
export * from "./getUser";
|
export * from "./getUser";
|
||||||
export * from "./listUsers";
|
export * from "./listUsers";
|
||||||
|
export * from "./updateUser";
|
||||||
|
|||||||
@ -0,0 +1,137 @@
|
|||||||
|
import { IUseCaseError, UseCaseError } from "@/contexts/common/application";
|
||||||
|
import { IServerError } from "@/contexts/common/domain/errors";
|
||||||
|
import {
|
||||||
|
IInfrastructureError,
|
||||||
|
InfrastructureError,
|
||||||
|
handleInfrastructureError,
|
||||||
|
} from "@/contexts/common/infrastructure";
|
||||||
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
|
import {
|
||||||
|
UpdateUserResponseOrError,
|
||||||
|
UpdateUserUseCase,
|
||||||
|
} from "@/contexts/users/application";
|
||||||
|
import { User } from "@/contexts/users/domain";
|
||||||
|
import {
|
||||||
|
IUpdateUser_Request_DTO,
|
||||||
|
IUpdateUser_Response_DTO,
|
||||||
|
ensureIdIsValid,
|
||||||
|
ensureUpdateUser_Request_DTOIsValid,
|
||||||
|
} from "@shared/contexts";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
import { IUpdateUserPresenter } from "./presenter/UpdateUser.presenter";
|
||||||
|
|
||||||
|
export class UpdateUserController extends ExpressController {
|
||||||
|
private useCase: UpdateUserUseCase;
|
||||||
|
private presenter: IUpdateUserPresenter;
|
||||||
|
private context: IUserContext;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
props: {
|
||||||
|
useCase: UpdateUserUseCase;
|
||||||
|
presenter: IUpdateUserPresenter;
|
||||||
|
},
|
||||||
|
context: IUserContext,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const { useCase, presenter } = props;
|
||||||
|
this.useCase = useCase;
|
||||||
|
this.presenter = presenter;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeImpl(): Promise<any> {
|
||||||
|
try {
|
||||||
|
const { userId } = this.req.params;
|
||||||
|
const userDTO: IUpdateUser_Request_DTO = this.req.body;
|
||||||
|
|
||||||
|
// Validar ID
|
||||||
|
const userIdOrError = ensureIdIsValid(userId);
|
||||||
|
if (userIdOrError.isFailure) {
|
||||||
|
const errorMessage = "User ID is not valid";
|
||||||
|
const infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
userIdOrError.error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validar DTO de datos
|
||||||
|
const userDTOOrError = ensureUpdateUser_Request_DTOIsValid(userDTO);
|
||||||
|
|
||||||
|
if (userDTOOrError.isFailure) {
|
||||||
|
const errorMessage = "User data not valid";
|
||||||
|
const infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
errorMessage,
|
||||||
|
userDTOOrError.error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Llamar al caso de uso
|
||||||
|
const result: UpdateUserResponseOrError = await this.useCase.execute({
|
||||||
|
id: userIdOrError.object,
|
||||||
|
userDTO,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
return this.handleExecuteError(result.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = <User>result.object;
|
||||||
|
|
||||||
|
return this.ok<IUpdateUser_Response_DTO>(
|
||||||
|
this.presenter.map(user, this.context),
|
||||||
|
);
|
||||||
|
} catch (e: unknown) {
|
||||||
|
return this.fail(e as IServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleExecuteError(error: IUseCaseError) {
|
||||||
|
let errorMessage: string;
|
||||||
|
let infraError: IInfrastructureError;
|
||||||
|
|
||||||
|
switch (error.code) {
|
||||||
|
case UseCaseError.NOT_FOUND_ERROR:
|
||||||
|
errorMessage = "User not found";
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.RESOURCE_NOT_FOUND_ERROR,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.notFoundError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UseCaseError.INVALID_INPUT_DATA:
|
||||||
|
errorMessage = "User data not valid";
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.INVALID_INPUT_DATA,
|
||||||
|
"Datos del cliente a actulizar erróneos",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.invalidInputError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UseCaseError.UNEXCEPTED_ERROR:
|
||||||
|
errorMessage = error.message;
|
||||||
|
|
||||||
|
infraError = handleInfrastructureError(
|
||||||
|
InfrastructureError.UNEXCEPTED_ERROR,
|
||||||
|
errorMessage,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return this.internalServerError(errorMessage, infraError);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorMessage = error.message;
|
||||||
|
return this.clientError(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { UpdateUserUseCase } from "@/contexts/users/application";
|
||||||
|
import { IUserContext } from "../../../User.context";
|
||||||
|
import { registerUserRepository } from "../../../User.repository";
|
||||||
|
import { UpdateUserController } from "./UpdateUser.controller";
|
||||||
|
import { UpdateUserPresenter } from "./presenter/UpdateUser.presenter";
|
||||||
|
|
||||||
|
export const createUpdateUserController = (context: IUserContext) => {
|
||||||
|
registerUserRepository(context);
|
||||||
|
return new UpdateUserController(
|
||||||
|
{
|
||||||
|
useCase: new UpdateUserUseCase(context),
|
||||||
|
presenter: UpdateUserPresenter,
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { User } from "@/contexts/users/domain";
|
||||||
|
import { IUserContext } from "@/contexts/users/infrastructure/User.context";
|
||||||
|
import { IUpdateUser_Response_DTO } from "@shared/contexts";
|
||||||
|
|
||||||
|
export interface IUpdateUserPresenter {
|
||||||
|
map: (user: User, context: IUserContext) => IUpdateUser_Response_DTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UpdateUserPresenter: IUpdateUserPresenter = {
|
||||||
|
map: (user: User, context: IUserContext): IUpdateUser_Response_DTO => {
|
||||||
|
return {
|
||||||
|
id: user.id.toString(),
|
||||||
|
name: user.name.toString(),
|
||||||
|
email: user.email.toString(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./UpdateUser.presenter";
|
||||||
@ -1,8 +1,11 @@
|
|||||||
import { applyMiddleware } from "@/contexts/common/infrastructure/express";
|
import { applyMiddleware } from "@/contexts/common/infrastructure/express";
|
||||||
import Express from "express";
|
import Express from "express";
|
||||||
import {
|
import {
|
||||||
|
createCreateUserController,
|
||||||
|
createDeleteUserController,
|
||||||
createGetUserController,
|
createGetUserController,
|
||||||
createListUsersController,
|
createListUsersController,
|
||||||
|
createUpdateUserController,
|
||||||
} from "./controllers";
|
} from "./controllers";
|
||||||
|
|
||||||
export const UserRouter = (appRouter: Express.Router) => {
|
export const UserRouter = (appRouter: Express.Router) => {
|
||||||
@ -22,5 +25,26 @@ export const UserRouter = (appRouter: Express.Router) => {
|
|||||||
createGetUserController(res.locals["context"]).execute(req, res, next),
|
createGetUserController(res.locals["context"]).execute(req, res, next),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
userRoutes.post(
|
||||||
|
"/",
|
||||||
|
applyMiddleware("isAdminUser"),
|
||||||
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
|
||||||
|
createCreateUserController(res.locals["context"]).execute(req, res, next),
|
||||||
|
);
|
||||||
|
|
||||||
|
userRoutes.put(
|
||||||
|
"/:userId",
|
||||||
|
applyMiddleware("isAdminUser"),
|
||||||
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
|
||||||
|
createUpdateUserController(res.locals["context"]).execute(req, res, next),
|
||||||
|
);
|
||||||
|
|
||||||
|
userRoutes.delete(
|
||||||
|
"/:userId",
|
||||||
|
applyMiddleware("isAdminUser"),
|
||||||
|
(req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
|
||||||
|
createDeleteUserController(res.locals["context"]).execute(req, res, next),
|
||||||
|
);
|
||||||
|
|
||||||
appRouter.use("/users", userRoutes);
|
appRouter.use("/users", userRoutes);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1 @@
|
|||||||
import { UndefinedOr } from "../../../utilities";
|
export {};
|
||||||
import { Email, Result } from "../../common";
|
|
||||||
|
|
||||||
export const ensureUserEmailIsValid = (value: UndefinedOr<string>) => {
|
|
||||||
const valueOrError = Email.create(value);
|
|
||||||
|
|
||||||
return valueOrError.isSuccess
|
|
||||||
? Result.ok(valueOrError.object)
|
|
||||||
: Result.fail(valueOrError.error);
|
|
||||||
};
|
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
import Joi from "joi";
|
||||||
|
import { Result, RuleValidator } from "../../../../common";
|
||||||
|
|
||||||
|
export interface ICreateUser_Request_DTO {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureCreateUser_Request_DTOIsValid(
|
||||||
|
userDTO: ICreateUser_Request_DTO,
|
||||||
|
): Result<boolean, Error> {
|
||||||
|
const schema = Joi.object({
|
||||||
|
id: Joi.string(),
|
||||||
|
name: Joi.string(),
|
||||||
|
email: Joi.string(),
|
||||||
|
}).unknown(true);
|
||||||
|
|
||||||
|
const result = RuleValidator.validate<ICreateUser_Request_DTO>(
|
||||||
|
schema,
|
||||||
|
userDTO,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
return Result.fail(result.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok(true);
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export interface ICreateUser_Response_DTO {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./ICreateUser_Request.dto";
|
||||||
|
export * from "./ICreateUser_Response.dto";
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { UniqueID } from "../../../../common";
|
|
||||||
|
|
||||||
export interface IGetUserRequest_DTO {
|
|
||||||
id: UniqueID;
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
export interface IGetUser_Response_DTO {
|
export interface IGetUserResponse_DTO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
export * from "./IGetUser.dto";
|
|
||||||
export * from "./IGetUser_Response.dto";
|
export * from "./IGetUser_Response.dto";
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
import Joi from "joi";
|
||||||
|
import { Result, RuleValidator } from "../../../../common";
|
||||||
|
|
||||||
|
export interface IUpdateUser_Request_DTO {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureUpdateUser_Request_DTOIsValid(
|
||||||
|
userDTO: IUpdateUser_Request_DTO,
|
||||||
|
): Result<boolean, Error> {
|
||||||
|
const schema = Joi.object({
|
||||||
|
id: Joi.string(),
|
||||||
|
name: Joi.string(),
|
||||||
|
email: Joi.string(),
|
||||||
|
}).unknown(true);
|
||||||
|
|
||||||
|
const result = RuleValidator.validate<IUpdateUser_Request_DTO>(
|
||||||
|
schema,
|
||||||
|
userDTO,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
return Result.fail(result.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok(true);
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export interface IUpdateUser_Response_DTO {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./IUpdateUser_Request.dto";
|
||||||
|
export * from "./IUpdateUser_Response.dto";
|
||||||
@ -1,2 +1,4 @@
|
|||||||
|
export * from "./CreateUser.dto";
|
||||||
export * from "./GetUser.dto";
|
export * from "./GetUser.dto";
|
||||||
export * from "./IListUsers.dto";
|
export * from "./IListUsers.dto";
|
||||||
|
export * from "./UpdateUser.dto";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user