.
This commit is contained in:
parent
8d280cbb48
commit
27717cc9b8
@ -1,17 +1,12 @@
|
||||
import { Password } from "@/contexts/common/domain";
|
||||
import {
|
||||
AggregateRoot,
|
||||
Email,
|
||||
IDomainError,
|
||||
Name,
|
||||
Result,
|
||||
UniqueID,
|
||||
} from "@shared/contexts";
|
||||
import { AggregateRoot, Email, IDomainError, Name, Result, UniqueID } from "@shared/contexts";
|
||||
import { AuthUserRole } from "./AuthUserRole";
|
||||
|
||||
export interface IAuthUserProps {
|
||||
name: Name;
|
||||
email: Email;
|
||||
password: Password;
|
||||
roles: AuthUserRole[];
|
||||
}
|
||||
|
||||
export interface IAuthUser {
|
||||
@ -21,18 +16,13 @@ export interface IAuthUser {
|
||||
password: Password;
|
||||
isUser: boolean;
|
||||
isAdmin: boolean;
|
||||
getRoles: () => AuthUserRole[];
|
||||
|
||||
verifyPassword: (candidatePassword: string) => boolean;
|
||||
}
|
||||
|
||||
export class AuthUser
|
||||
extends AggregateRoot<IAuthUserProps>
|
||||
implements IAuthUser
|
||||
{
|
||||
public static create(
|
||||
props: IAuthUserProps,
|
||||
id?: UniqueID,
|
||||
): Result<AuthUser, IDomainError> {
|
||||
export class AuthUser extends AggregateRoot<IAuthUserProps> implements IAuthUser {
|
||||
public static create(props: IAuthUserProps, id?: UniqueID): Result<AuthUser, IDomainError> {
|
||||
const user = new AuthUser(props, id);
|
||||
return Result.ok<AuthUser>(user);
|
||||
}
|
||||
@ -41,6 +31,14 @@ export class AuthUser
|
||||
return Password.hashPassword(password);
|
||||
}
|
||||
|
||||
private roles: AuthUserRole[];
|
||||
|
||||
constructor(props: IAuthUserProps, id?: UniqueID) {
|
||||
const { roles } = props;
|
||||
super(props, id);
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
get name(): Name {
|
||||
return this.props.name;
|
||||
}
|
||||
@ -54,14 +52,22 @@ export class AuthUser
|
||||
}
|
||||
|
||||
get isUser(): boolean {
|
||||
return true;
|
||||
return this._hasRole(AuthUserRole.ROLE_USER);
|
||||
}
|
||||
|
||||
get isAdmin(): boolean {
|
||||
return true;
|
||||
return this._hasRole(AuthUserRole.ROLE_ADMIN);
|
||||
}
|
||||
|
||||
public getRoles(): AuthUserRole[] {
|
||||
return this.roles;
|
||||
}
|
||||
|
||||
public verifyPassword(candidatePassword: string): boolean {
|
||||
return this.props.password.verifyPassword(candidatePassword);
|
||||
}
|
||||
|
||||
private _hasRole(role: AuthUserRole): boolean {
|
||||
return this.roles.some((r) => r.equals(role));
|
||||
}
|
||||
}
|
||||
|
||||
21
server/src/contexts/auth/domain/entities/AuthUserRole.ts
Normal file
21
server/src/contexts/auth/domain/entities/AuthUserRole.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { DomainError, Result, ValueObject, handleDomainError } from "@shared/contexts";
|
||||
|
||||
export class AuthUserRole extends ValueObject<string> {
|
||||
static ROLE_ADMIN = new AuthUserRole("ROLE_ADMIN");
|
||||
static ROLE_USER = new AuthUserRole("ROLE_USER");
|
||||
|
||||
public static create(value: string) {
|
||||
switch (value) {
|
||||
case "ROLE_ADMIN":
|
||||
return Result.ok(AuthUserRole.ROLE_ADMIN);
|
||||
case "ROLE_USER":
|
||||
return Result.ok(AuthUserRole.ROLE_USER);
|
||||
default:
|
||||
return Result.fail(handleDomainError(DomainError.INVALID_INPUT_DATA));
|
||||
}
|
||||
}
|
||||
|
||||
public toPrimitive(): string {
|
||||
return this.toString();
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from "./AuthUser";
|
||||
export * from "./AuthUserRole";
|
||||
|
||||
@ -21,7 +21,7 @@ export const loginPresenter: ILoginPresenter = {
|
||||
id: user.id.toString(),
|
||||
name: user.name.toString(),
|
||||
email: user.email.toString(),
|
||||
roles: ["ROLE_USER"],
|
||||
roles: user.getRoles().map((rol) => rol.toString()),
|
||||
token,
|
||||
refresh_token: refreshToken,
|
||||
};
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
import { Name, UniqueID } from "@shared/contexts";
|
||||
import { Dealer, IDealerProps } from "../../domain/entities";
|
||||
import { ISalesContext } from "../Sales.context";
|
||||
import { DealerCreationAttributes, DealerStatus, Dealer_Model } from "../sequelize";
|
||||
import { DEALER_STATUS, DealerCreationAttributes, Dealer_Model } from "../sequelize";
|
||||
|
||||
export interface IDealerMapper
|
||||
extends ISequelizeMapper<Dealer_Model, DealerCreationAttributes, Dealer> {}
|
||||
@ -44,7 +44,7 @@ class DealerMapper
|
||||
default_notes: "",
|
||||
default_legal_terms: "",
|
||||
default_quote_validity: "",
|
||||
status: DealerStatus.ACTIVE,
|
||||
status: DEALER_STATUS.STATUS_ACTIVE,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,9 +8,9 @@ import {
|
||||
} from "sequelize";
|
||||
import { Quote_Model } from "./quote.model";
|
||||
|
||||
export enum DealerStatus {
|
||||
ACTIVE = "active",
|
||||
BLOCKED = "blocked",
|
||||
export enum DEALER_STATUS {
|
||||
STATUS_ACTIVE = "active",
|
||||
STATUS_BLOCKED = "blocked",
|
||||
}
|
||||
|
||||
export type DealerCreationAttributes = InferCreationAttributes<Dealer_Model>;
|
||||
@ -49,7 +49,7 @@ export class Dealer_Model extends Model<
|
||||
declare default_notes: string;
|
||||
declare default_legal_terms: string;
|
||||
declare default_quote_validity: string;
|
||||
declare status: DealerStatus;
|
||||
declare status: DEALER_STATUS;
|
||||
}
|
||||
|
||||
export default (sequelize: Sequelize) => {
|
||||
@ -77,7 +77,7 @@ export default (sequelize: Sequelize) => {
|
||||
default_quote_validity: DataTypes.STRING,
|
||||
|
||||
status: {
|
||||
type: DataTypes.ENUM(...Object.values(DealerStatus)),
|
||||
type: DataTypes.ENUM(...Object.values(DEALER_STATUS)),
|
||||
allowNull: false,
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
import {
|
||||
IUseCase,
|
||||
IUseCaseError,
|
||||
UseCaseError,
|
||||
} from "@/contexts/common/application";
|
||||
import { IUseCase, IUseCaseError, UseCaseError } from "@/contexts/common/application";
|
||||
import { IRepositoryManager, Password } from "@/contexts/common/domain";
|
||||
import { IInfrastructureError } from "@/contexts/common/infrastructure";
|
||||
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
|
||||
@ -18,23 +14,19 @@ import {
|
||||
ensureIdIsValid,
|
||||
ensureNameIsValid,
|
||||
} from "@shared/contexts";
|
||||
import { IUserRepository, User } from "../domain";
|
||||
import { IUserRepository, User, UserRole } from "../domain";
|
||||
|
||||
export type CreateUserResponseOrError =
|
||||
| Result<never, IUseCaseError> // Misc errors (value objects)
|
||||
| Result<User, never>; // Success!
|
||||
|
||||
export class CreateUserUseCase
|
||||
implements
|
||||
IUseCase<ICreateUser_Request_DTO, Promise<CreateUserResponseOrError>>
|
||||
implements IUseCase<ICreateUser_Request_DTO, Promise<CreateUserResponseOrError>>
|
||||
{
|
||||
private _adapter: ISequelizeAdapter;
|
||||
private _repositoryManager: IRepositoryManager;
|
||||
|
||||
constructor(props: {
|
||||
adapter: ISequelizeAdapter;
|
||||
repositoryManager: IRepositoryManager;
|
||||
}) {
|
||||
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
|
||||
this._adapter = props.adapter;
|
||||
this._repositoryManager = props.repositoryManager;
|
||||
}
|
||||
@ -47,9 +39,7 @@ export class CreateUserUseCase
|
||||
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" },
|
||||
]),
|
||||
UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [{ path: "id" }])
|
||||
);
|
||||
}
|
||||
|
||||
@ -57,9 +47,7 @@ export class CreateUserUseCase
|
||||
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" },
|
||||
]),
|
||||
UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [{ path: "name" }])
|
||||
);
|
||||
}
|
||||
|
||||
@ -67,9 +55,7 @@ export class CreateUserUseCase
|
||||
if (emailOrError.isFailure) {
|
||||
const message = emailOrError.error.message;
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [
|
||||
{ path: "email" },
|
||||
]),
|
||||
UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [{ path: "email" }])
|
||||
);
|
||||
}
|
||||
|
||||
@ -82,32 +68,28 @@ export class CreateUserUseCase
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, {
|
||||
path: "id",
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const nameExists = await userRepository().existsUserWithName(
|
||||
nameOrError.object,
|
||||
);
|
||||
const nameExists = await userRepository().existsUserWithName(nameOrError.object);
|
||||
if (nameExists) {
|
||||
const message = `Another user with same name exists`;
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, {
|
||||
path: "name",
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const emailExists = await userRepository().existsUserWithEmail(
|
||||
emailOrError.object,
|
||||
);
|
||||
const emailExists = await userRepository().existsUserWithEmail(emailOrError.object);
|
||||
|
||||
if (emailExists) {
|
||||
const message = `Another user with same email exists`;
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, {
|
||||
path: "email",
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -157,15 +139,13 @@ export class CreateUserUseCase
|
||||
return Result.ok<User>(user);
|
||||
} catch (error: unknown) {
|
||||
const _error = error as IInfrastructureError;
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message),
|
||||
);
|
||||
return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message));
|
||||
}
|
||||
}
|
||||
|
||||
private _tryCreateUserInstance(
|
||||
userDTO: ICreateUser_Request_DTO,
|
||||
userId: UniqueID,
|
||||
userId: UniqueID
|
||||
): Result<User, IDomainError> {
|
||||
const nameOrError = Name.create(userDTO.name);
|
||||
if (nameOrError.isFailure) {
|
||||
@ -177,9 +157,7 @@ export class CreateUserUseCase
|
||||
return Result.fail(emailOrError.error);
|
||||
}
|
||||
|
||||
const passwordOrError = Password.createFromPlainTextPassword(
|
||||
userDTO.password,
|
||||
);
|
||||
const passwordOrError = Password.createFromPlainTextPassword(userDTO.password);
|
||||
if (passwordOrError.isFailure) {
|
||||
return Result.fail(passwordOrError.error);
|
||||
}
|
||||
@ -189,8 +167,9 @@ export class CreateUserUseCase
|
||||
name: nameOrError.object,
|
||||
email: emailOrError.object,
|
||||
password: passwordOrError.object,
|
||||
roles: [UserRole.ROLE_USER],
|
||||
},
|
||||
userId,
|
||||
userId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import {
|
||||
Result,
|
||||
UniqueID,
|
||||
} from "@shared/contexts";
|
||||
import { IUserRepository, User } from "../domain";
|
||||
import { IUserRepository, User, UserRole } from "../domain";
|
||||
|
||||
export interface IUpdateUserUseCaseRequest extends IUseCaseRequest {
|
||||
id: UniqueID;
|
||||
@ -28,23 +28,17 @@ export type UpdateUserResponseOrError =
|
||||
| Result<User, never>; // Success!
|
||||
|
||||
export class UpdateUserUseCase
|
||||
implements
|
||||
IUseCase<IUpdateUserUseCaseRequest, Promise<UpdateUserResponseOrError>>
|
||||
implements IUseCase<IUpdateUserUseCaseRequest, Promise<UpdateUserResponseOrError>>
|
||||
{
|
||||
private _adapter: ISequelizeAdapter;
|
||||
private _repositoryManager: IRepositoryManager;
|
||||
|
||||
constructor(props: {
|
||||
adapter: ISequelizeAdapter;
|
||||
repositoryManager: IRepositoryManager;
|
||||
}) {
|
||||
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
|
||||
this._adapter = props.adapter;
|
||||
this._repositoryManager = props.repositoryManager;
|
||||
}
|
||||
|
||||
async execute(
|
||||
request: IUpdateUserUseCaseRequest,
|
||||
): Promise<UpdateUserResponseOrError> {
|
||||
async execute(request: IUpdateUserUseCaseRequest): Promise<UpdateUserResponseOrError> {
|
||||
const { id, userDTO } = request;
|
||||
const userRepository = this._getUserRepository();
|
||||
|
||||
@ -55,7 +49,7 @@ export class UpdateUserUseCase
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, {
|
||||
path: "id",
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -106,15 +100,13 @@ export class UpdateUserUseCase
|
||||
return Result.ok<User>(user);
|
||||
} catch (error: unknown) {
|
||||
const _error = error as IInfrastructureError;
|
||||
return Result.fail(
|
||||
UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message),
|
||||
);
|
||||
return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message));
|
||||
}
|
||||
}
|
||||
|
||||
private _tryCreateUserInstance(
|
||||
userDTO: IUpdateUser_Request_DTO,
|
||||
userId: UniqueID,
|
||||
userId: UniqueID
|
||||
): Result<User, IDomainError> {
|
||||
const nameOrError = Name.create(userDTO.name);
|
||||
if (nameOrError.isFailure) {
|
||||
@ -126,9 +118,7 @@ export class UpdateUserUseCase
|
||||
return Result.fail(emailOrError.error);
|
||||
}
|
||||
|
||||
const passwordOrError = Password.createFromPlainTextPassword(
|
||||
userDTO.password,
|
||||
);
|
||||
const passwordOrError = Password.createFromPlainTextPassword(userDTO.password);
|
||||
if (passwordOrError.isFailure) {
|
||||
return Result.fail(passwordOrError.error);
|
||||
}
|
||||
@ -138,8 +128,9 @@ export class UpdateUserUseCase
|
||||
name: nameOrError.object,
|
||||
email: emailOrError.object,
|
||||
password: passwordOrError.object,
|
||||
roles: [UserRole.ROLE_USER],
|
||||
},
|
||||
userId,
|
||||
userId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -9,14 +9,16 @@ import {
|
||||
handleDomainError,
|
||||
} from "@shared/contexts";
|
||||
import { UserHasName } from "./User.specifications";
|
||||
import { UserRole } from "./UserRole";
|
||||
|
||||
export interface IUserProps {
|
||||
name: Name;
|
||||
email: Email;
|
||||
password: Password;
|
||||
roles: UserRole[];
|
||||
}
|
||||
|
||||
//type ISecuredUserProps = Omit<IUserProps, "password">;
|
||||
//type ISecuredUserProps = ;
|
||||
|
||||
export interface IUser {
|
||||
id: UniqueID;
|
||||
@ -30,10 +32,7 @@ export interface IUser {
|
||||
export class User extends AggregateRoot<IUserProps> implements IUser {
|
||||
static readonly ERROR_USER_WITHOUT_NAME = "ERROR_USER_WITHOUT_NAME";
|
||||
|
||||
public static create(
|
||||
props: IUserProps,
|
||||
id?: UniqueID,
|
||||
): Result<User, IDomainError> {
|
||||
public static create(props: IUserProps, id?: UniqueID): Result<User, IDomainError> {
|
||||
const user = new User(props, id);
|
||||
|
||||
// Reglas de negocio / validaciones
|
||||
@ -50,6 +49,14 @@ export class User extends AggregateRoot<IUserProps> implements IUser {
|
||||
return Password.hashPassword(password);
|
||||
}
|
||||
|
||||
private roles: UserRole[];
|
||||
|
||||
constructor(props: IUserProps, id?: UniqueID) {
|
||||
const { roles } = props;
|
||||
super(props, id);
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
get name(): Name {
|
||||
return this.props.name;
|
||||
}
|
||||
@ -63,10 +70,28 @@ export class User extends AggregateRoot<IUserProps> implements IUser {
|
||||
}
|
||||
|
||||
get isUser(): boolean {
|
||||
return true;
|
||||
return this.hasRole(UserRole.ROLE_USER);
|
||||
}
|
||||
|
||||
get isAdmin(): boolean {
|
||||
return true;
|
||||
return this.hasRole(UserRole.ROLE_ADMIN);
|
||||
}
|
||||
|
||||
public hasRole(role: UserRole): boolean {
|
||||
return this.roles.some((r) => r.equals(role));
|
||||
}
|
||||
|
||||
public getRoles(): UserRole[] {
|
||||
return this.roles;
|
||||
}
|
||||
|
||||
public addRole(role: UserRole): void {
|
||||
if (!this.roles.some((r) => r.equals(role))) {
|
||||
this.roles.push(role);
|
||||
}
|
||||
}
|
||||
|
||||
public removeRole(role: UserRole): void {
|
||||
this.roles = this.roles.filter((r) => !r.equals(role));
|
||||
}
|
||||
}
|
||||
|
||||
21
server/src/contexts/users/domain/entities/UserRole.ts
Normal file
21
server/src/contexts/users/domain/entities/UserRole.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { DomainError, Result, ValueObject, handleDomainError } from "@shared/contexts";
|
||||
|
||||
export class UserRole extends ValueObject<string> {
|
||||
static ROLE_ADMIN = new UserRole("ROLE_ADMIN");
|
||||
static ROLE_USER = new UserRole("ROLE_USER");
|
||||
|
||||
public static create(value: string) {
|
||||
switch (value) {
|
||||
case "ROLE_ADMIN":
|
||||
return Result.ok(UserRole.ROLE_ADMIN);
|
||||
case "ROLE_USER":
|
||||
return Result.ok(UserRole.ROLE_USER);
|
||||
default:
|
||||
return Result.fail(handleDomainError(DomainError.INVALID_INPUT_DATA));
|
||||
}
|
||||
}
|
||||
|
||||
public toPrimitive(): string {
|
||||
return this.toString();
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from "./User";
|
||||
export * from "./UserRole";
|
||||
|
||||
@ -12,6 +12,7 @@ export const CreateUserPresenter: ICreateUserPresenter = {
|
||||
id: user.id.toString(),
|
||||
name: user.name.toString(),
|
||||
email: user.email.toString(),
|
||||
roles: user.getRoles().map((rol) => rol.toString()),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -12,6 +12,7 @@ export const GetUserPresenter: IGetUserPresenter = {
|
||||
id: user.id.toString(),
|
||||
name: user.name.toString(),
|
||||
email: user.email.toString(),
|
||||
roles: user.getRoles().map((rol) => rol.toString()),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,10 +1,6 @@
|
||||
import { User } from "@/contexts/users/domain";
|
||||
import { IUserContext } from "@/contexts/users/infrastructure/User.context";
|
||||
import {
|
||||
ICollection,
|
||||
IListResponse_DTO,
|
||||
IListUsers_Response_DTO,
|
||||
} from "@shared/contexts";
|
||||
import { ICollection, IListResponse_DTO, IListUsers_Response_DTO } from "@shared/contexts";
|
||||
|
||||
export interface IListUsersPresenter {
|
||||
map: (user: User, context: IUserContext) => IListUsers_Response_DTO;
|
||||
@ -15,7 +11,7 @@ export interface IListUsersPresenter {
|
||||
params: {
|
||||
page: number;
|
||||
limit: number;
|
||||
},
|
||||
}
|
||||
) => IListResponse_DTO<IListUsers_Response_DTO>;
|
||||
}
|
||||
|
||||
@ -26,6 +22,7 @@ export const listUsersPresenter: IListUsersPresenter = {
|
||||
id: user.id.toString(),
|
||||
name: user.name.toString(),
|
||||
email: user.email.toString(),
|
||||
roles: user.getRoles().map((rol) => rol.toString()),
|
||||
};
|
||||
},
|
||||
|
||||
@ -35,14 +32,12 @@ export const listUsersPresenter: IListUsersPresenter = {
|
||||
params: {
|
||||
page: number;
|
||||
limit: number;
|
||||
},
|
||||
}
|
||||
): IListResponse_DTO<IListUsers_Response_DTO> => {
|
||||
const { page, limit } = params;
|
||||
|
||||
const totalCount = users.totalCount ?? 0;
|
||||
const items = users.items.map((user: User) =>
|
||||
listUsersPresenter.map(user, context),
|
||||
);
|
||||
const items = users.items.map((user: User) => listUsersPresenter.map(user, context));
|
||||
|
||||
const result = {
|
||||
page,
|
||||
|
||||
@ -12,6 +12,7 @@ export const UpdateUserPresenter: IUpdateUserPresenter = {
|
||||
id: user.id.toString(),
|
||||
name: user.name.toString(),
|
||||
email: user.email.toString(),
|
||||
roles: user.getRoles().map((rol) => rol.toString()),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import { Password } from "@/contexts/common/domain";
|
||||
import {
|
||||
ISequelizeMapper,
|
||||
SequelizeMapper,
|
||||
} from "@/contexts/common/infrastructure";
|
||||
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
|
||||
import { Email, Name, UniqueID } from "@shared/contexts";
|
||||
import { IUserProps, User } from "../../domain";
|
||||
import { IUserProps, User, UserRole } from "../../domain";
|
||||
import { IUserContext } from "../User.context";
|
||||
import { UserCreationAttributes, User_Model } from "../sequelize/user.model";
|
||||
|
||||
export interface IUserMapper
|
||||
extends ISequelizeMapper<User_Model, UserCreationAttributes, User> {}
|
||||
export interface IUserMapper extends ISequelizeMapper<User_Model, UserCreationAttributes, User> {}
|
||||
|
||||
class UserMapper
|
||||
extends SequelizeMapper<User_Model, UserCreationAttributes, User>
|
||||
@ -23,11 +19,8 @@ class UserMapper
|
||||
const props: IUserProps = {
|
||||
name: this.mapsValue(source, "name", Name.create),
|
||||
email: this.mapsValue(source, "email", Email.create),
|
||||
password: this.mapsValue(
|
||||
source,
|
||||
"password",
|
||||
Password.createFromHashedTextPassword,
|
||||
),
|
||||
password: this.mapsValue(source, "password", Password.createFromHashedTextPassword),
|
||||
roles: source.roles.map((rol) => UserRole.create(rol).object),
|
||||
};
|
||||
|
||||
const id = this.mapsValue(source, "id", UniqueID.create);
|
||||
@ -40,15 +33,13 @@ class UserMapper
|
||||
return userOrError.object;
|
||||
}
|
||||
|
||||
protected toPersistenceMappingImpl(
|
||||
source: User,
|
||||
params?: Record<string, any> | undefined,
|
||||
) {
|
||||
protected toPersistenceMappingImpl(source: User, params?: Record<string, any> | undefined) {
|
||||
return {
|
||||
id: source.id.toPrimitive(),
|
||||
name: source.name.toPrimitive(),
|
||||
email: source.email.toPrimitive(),
|
||||
password: source.password.toPrimitive(),
|
||||
roles: source.getRoles().map((rol) => rol.toPrimitive()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,11 @@ import {
|
||||
Sequelize,
|
||||
} from "sequelize";
|
||||
|
||||
export enum USER_ROLES {
|
||||
ROLE_ADMIN = "ROLE_ADMIN",
|
||||
ROLE_USER = "ROLE_USER",
|
||||
}
|
||||
|
||||
export type UserCreationAttributes = InferCreationAttributes<User_Model>;
|
||||
|
||||
export class User_Model extends Model<
|
||||
@ -33,6 +38,7 @@ export class User_Model extends Model<
|
||||
declare name: string;
|
||||
declare email: string;
|
||||
declare password: string;
|
||||
declare roles: string[];
|
||||
}
|
||||
|
||||
export default (sequelize: Sequelize) => {
|
||||
@ -56,6 +62,18 @@ export default (sequelize: Sequelize) => {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
|
||||
roles: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: USER_ROLES.ROLE_USER,
|
||||
get(this: User_Model): string[] {
|
||||
return this.getDataValue("roles").split(";");
|
||||
},
|
||||
set(this: User_Model, value: string[]) {
|
||||
this.setDataValue("roles", value.join(";"));
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
|
||||
@ -25,7 +25,7 @@ export const currentState = assign(
|
||||
environment: config.enviroment,
|
||||
connections: {},
|
||||
},
|
||||
config,
|
||||
config
|
||||
);
|
||||
|
||||
const serverStop = (server: http.Server) => {
|
||||
@ -35,9 +35,7 @@ const serverStop = (server: http.Server) => {
|
||||
logger.warn("⚡️ Shutting down server");
|
||||
|
||||
setTimeout(() => {
|
||||
logger.error(
|
||||
"Could not close connections in time, forcefully shutting down",
|
||||
);
|
||||
logger.error("Could not close connections in time, forcefully shutting down");
|
||||
resolve();
|
||||
}, forceTimeout).unref();
|
||||
|
||||
@ -67,9 +65,7 @@ const serverStop = (server: http.Server) => {
|
||||
const serverError = (error: any) => {
|
||||
if (error.code === "EADDRINUSE") {
|
||||
logger.debug(`⛔️ Server wasn't able to start properly.`);
|
||||
logger.error(
|
||||
`The port ${error.port} is already used by another application.`,
|
||||
);
|
||||
logger.error(`The port ${error.port} is already used by another application.`);
|
||||
} else {
|
||||
logger.debug(`⛔️ Server wasn't able to start properly.`);
|
||||
logger.error(error);
|
||||
@ -99,12 +95,10 @@ const server: http.Server = http
|
||||
process.on("SIGINT", () => {
|
||||
//firebirdConn.disconnect();
|
||||
serverStop(server);
|
||||
}),
|
||||
})
|
||||
)
|
||||
.on("close", () =>
|
||||
logger.info(
|
||||
`Shut down at: ${DateTime.now().toLocaleString(DateTime.DATETIME_FULL)}`,
|
||||
),
|
||||
logger.info(`Shut down at: ${DateTime.now().toLocaleString(DateTime.DATETIME_FULL)}`)
|
||||
)
|
||||
.on("connection", serverConnection)
|
||||
.on("error", serverError);
|
||||
@ -115,18 +109,12 @@ try {
|
||||
// Launch server
|
||||
server.listen(currentState.server.port, () => {
|
||||
const now = DateTime.now();
|
||||
logger.info(
|
||||
`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`,
|
||||
);
|
||||
logger.info(
|
||||
`Launched in: ${now.diff(currentState.launchedAt).toMillis()} ms`,
|
||||
);
|
||||
logger.info(`Time: ${now.toLocaleString(DateTime.DATETIME_FULL)} ${now.zoneName}`);
|
||||
logger.info(`Launched in: ${now.diff(currentState.launchedAt).toMillis()} ms`);
|
||||
logger.info(`Environment: ${currentState.environment}`);
|
||||
logger.info(`Process PID: ${process.pid}`);
|
||||
logger.info("To shut down your server, press <CTRL> + C at any time");
|
||||
logger.info(
|
||||
`⚡️ Server: http://${currentState.server.hostname}:${currentState.server.port}`,
|
||||
);
|
||||
logger.info(`⚡️ Server: http://${currentState.server.hostname}:${currentState.server.port}`);
|
||||
});
|
||||
});
|
||||
//});
|
||||
|
||||
@ -2,4 +2,5 @@ export interface ICreateUser_Response_DTO {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
@ -2,4 +2,5 @@ export interface IGetUserResponse_DTO {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
@ -2,4 +2,5 @@ export interface IListUsers_Response_DTO {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
@ -2,4 +2,5 @@ export interface IUpdateUser_Response_DTO {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
roles: string[];
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user