This commit is contained in:
David Arranz 2024-06-10 19:16:39 +02:00
parent 33010c0c6b
commit 090f8acf5c
24 changed files with 132 additions and 101 deletions

View File

@ -40,6 +40,7 @@ module.exports = {
name: "Administrador", name: "Administrador",
email: "darranz@rodax-software.com", email: "darranz@rodax-software.com",
password: "123456", password: "123456",
language: "es",
}, },
uploads: { uploads: {

View File

@ -68,6 +68,6 @@ export class AuthUser extends AggregateRoot<IAuthUserProps> implements IAuthUser
} }
private _hasRole(role: AuthUserRole): boolean { private _hasRole(role: AuthUserRole): boolean {
return this.roles.some((r) => r.equals(role)); return (this.roles || []).some((r) => r.equals(role));
} }
} }

View File

@ -2,7 +2,9 @@ import { IAuthUser } from "@/contexts/auth/domain";
import { IAuthContext } from "@/contexts/auth/infrastructure/Auth.context"; import { IAuthContext } from "@/contexts/auth/infrastructure/Auth.context";
import { IIdentity_Response_DTO } from "@shared/contexts"; import { IIdentity_Response_DTO } from "@shared/contexts";
export interface IIdentityUser extends IAuthUser {} export interface IIdentityUser extends IAuthUser {
language: string;
}
export interface IIdentityPresenter { export interface IIdentityPresenter {
map: (user: IIdentityUser, context: IAuthContext) => IIdentity_Response_DTO; map: (user: IIdentityUser, context: IAuthContext) => IIdentity_Response_DTO;
@ -15,6 +17,7 @@ export const identityPresenter: IIdentityPresenter = {
id: user.id.toString(), id: user.id.toString(),
name: user.name.toString(), name: user.name.toString(),
email: user.email.toString(), email: user.email.toString(),
language: "es",
roles: user.getRoles()?.map((rol) => rol.toString()), roles: user.getRoles()?.map((rol) => rol.toString()),
}; };
}, },

View File

@ -16,12 +16,13 @@ export const loginPresenter: ILoginPresenter = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
map: (loginUser: ILoginUser, context: IAuthContext): ILogin_Response_DTO => { map: (loginUser: ILoginUser, context: IAuthContext): ILogin_Response_DTO => {
const { user, token, refreshToken } = loginUser; const { user, token, refreshToken } = loginUser;
const roles = user.getRoles()?.map((rol) => rol.toString()) || [];
return { return {
id: user.id.toString(), id: user.id.toString(),
name: user.name.toString(), name: user.name.toString(),
email: user.email.toString(), email: user.email.toString(),
roles: user.getRoles()?.map((rol) => rol.toString()), roles,
token, token,
refresh_token: refreshToken, refresh_token: refreshToken,
}; };

View File

@ -0,0 +1,17 @@
import { AuthUser } from "@/contexts/auth/domain";
import { generateExpressError } from "@/contexts/common/infrastructure/express";
import Express from "express";
import httpStatus from "http-status";
const profileMiddleware = (
req: Express.Request,
res: Express.Response,
next: Express.NextFunction
) => {
const user = <AuthUser>req.user;
if (!user.isAdmin) {
generateExpressError(req, res, httpStatus.UNAUTHORIZED);
}
next();
};

View File

@ -1,5 +1,6 @@
import { AuthUser } from "@/contexts/auth/domain"; import { AuthUser } from "@/contexts/auth/domain";
import { composeMiddleware, generateExpressError } from "@/contexts/common/infrastructure/express"; import { composeMiddleware, generateExpressError } from "@/contexts/common/infrastructure/express";
import { UniqueID } from "@shared/contexts";
import Express from "express"; import Express from "express";
import httpStatus from "http-status"; import httpStatus from "http-status";
import passport from "passport"; import passport from "passport";
@ -25,10 +26,22 @@ export const isUser = composeMiddleware([
export const isAdmin = composeMiddleware([ export const isAdmin = composeMiddleware([
isUser, isUser,
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => { (req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
const user = <AuthUser>req.authInfo; const user = <AuthUser>req.user;
if (!user.isAdmin) { if (!user.isAdmin) {
generateExpressError(req, res, httpStatus.UNAUTHORIZED); generateExpressError(req, res, httpStatus.UNAUTHORIZED);
} }
next(); next();
}, },
]); ]);
export const isAdminOrMe = composeMiddleware([
isUser,
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => {
const user = <AuthUser>req.user;
const { userId } = req.params;
if (user.isAdmin || user.id.equals(UniqueID.create(userId).object)) {
next();
} else generateExpressError(req, res, httpStatus.UNAUTHORIZED);
},
]);

View File

@ -1,22 +1,13 @@
import { Password } from "@/contexts/common/domain"; import { Password } from "@/contexts/common/domain";
import { import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
ISequelizeMapper, import { UserRole } from "@/contexts/users/domain";
SequelizeMapper,
} from "@/contexts/common/infrastructure";
import { Email, Name, UniqueID } from "@shared/contexts"; import { Email, Name, UniqueID } from "@shared/contexts";
import { AuthUser, IAuthUserProps } from "../../domain/entities"; import { AuthUser, IAuthUserProps } from "../../domain/entities";
import { IAuthContext } from "../Auth.context"; import { IAuthContext } from "../Auth.context";
import { import { AuthUserCreationAttributes, AuthUser_Model } from "../sequelize/authUser.model";
AuthUserCreationAttributes,
AuthUser_Model,
} from "../sequelize/authUser.model";
export interface IUserMapper export interface IUserMapper
extends ISequelizeMapper< extends ISequelizeMapper<AuthUser_Model, AuthUserCreationAttributes, AuthUser> {}
AuthUser_Model,
AuthUserCreationAttributes,
AuthUser
> {}
class AuthUserMapper class AuthUserMapper
extends SequelizeMapper<AuthUser_Model, AuthUserCreationAttributes, AuthUser> extends SequelizeMapper<AuthUser_Model, AuthUserCreationAttributes, AuthUser>
@ -30,11 +21,8 @@ class AuthUserMapper
const props: IAuthUserProps = { const props: IAuthUserProps = {
name: this.mapsValue(source, "name", Name.create), name: this.mapsValue(source, "name", Name.create),
email: this.mapsValue(source, "email", Email.create), email: this.mapsValue(source, "email", Email.create),
password: this.mapsValue( password: this.mapsValue(source, "password", Password.createFromHashedTextPassword),
source, roles: source.roles.map((rol) => UserRole.create(rol).object),
"password",
Password.createFromHashedTextPassword,
),
}; };
const id = this.mapsValue(source, "id", UniqueID.create); const id = this.mapsValue(source, "id", UniqueID.create);
@ -47,15 +35,13 @@ class AuthUserMapper
return userOrError.object; return userOrError.object;
} }
protected toPersistenceMappingImpl( protected toPersistenceMappingImpl(source: AuthUser, params?: Record<string, any> | undefined) {
source: AuthUser,
params?: Record<string, any> | undefined,
) {
return { return {
id: source.id.toPrimitive(), id: source.id.toPrimitive(),
name: source.name.toPrimitive(), name: source.name.toPrimitive(),
email: source.email.toPrimitive(), email: source.email.toPrimitive(),
password: source.password.toPrimitive(), password: source.password.toPrimitive(),
roles: source.getRoles().map((role) => role.toPrimitive()),
}; };
} }
} }

View File

@ -1,3 +1,4 @@
import { USER_ROLES } from "@/contexts/users";
import { DataTypes, InferAttributes, InferCreationAttributes, Model, Sequelize } from "sequelize"; import { DataTypes, InferAttributes, InferCreationAttributes, Model, Sequelize } from "sequelize";
export type AuthUserCreationAttributes = InferCreationAttributes<AuthUser_Model>; export type AuthUserCreationAttributes = InferCreationAttributes<AuthUser_Model>;
@ -18,6 +19,7 @@ export class AuthUser_Model extends Model<
declare name: string; declare name: string;
declare email: string; declare email: string;
declare password: string; declare password: string;
declare roles: string[];
} }
export default (sequelize: Sequelize) => { export default (sequelize: Sequelize) => {
@ -41,6 +43,20 @@ export default (sequelize: Sequelize) => {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,
}, },
roles: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: USER_ROLES.ROLE_USER,
get(this: AuthUser_Model): string[] {
const rawValue = this.getDataValue("roles") as any;
return String(rawValue).split(";");
},
set(this: AuthUser_Model, value: string[]) {
const rawValue = value.join(";") as any;
this.setDataValue("roles", rawValue);
},
},
}, },
{ {
sequelize, sequelize,

View File

@ -14,8 +14,8 @@ export interface IArticleProps {
catalog_name: Slug; catalog_name: Slug;
id_article: ArticleIdentifier; id_article: ArticleIdentifier;
reference: Slug; reference: Slug;
family: Description; //family: Description;
subfamily: Description; //subfamily: Description;
description: Description; description: Description;
points: Quantity; points: Quantity;
retail_price: UnitPrice; retail_price: UnitPrice;
@ -26,18 +26,15 @@ export interface IArticle {
catalog_name: Slug; catalog_name: Slug;
id_article: ArticleIdentifier; id_article: ArticleIdentifier;
reference: Slug; reference: Slug;
family: Description; //family: Description;
subfamily: Description; //subfamily: Description;
description: Description; description: Description;
points: Quantity; points: Quantity;
retail_price: UnitPrice; retail_price: UnitPrice;
} }
export class Article extends AggregateRoot<IArticleProps> implements IArticle { export class Article extends AggregateRoot<IArticleProps> implements IArticle {
public static create( public static create(props: IArticleProps, id?: UniqueID): Result<Article, IDomainError> {
props: IArticleProps,
id?: UniqueID,
): Result<Article, IDomainError> {
//const isNew = !!id === false; //const isNew = !!id === false;
// Se hace en el constructor de la Entidad // Se hace en el constructor de la Entidad
@ -70,13 +67,13 @@ export class Article extends AggregateRoot<IArticleProps> implements IArticle {
return this.props.reference; return this.props.reference;
} }
get family(): Description { /*get family(): Description {
return this.props.family; return this.props.family;
} }
get subfamily(): Description { get subfamily(): Description {
return this.props.subfamily; return this.props.subfamily;
} }*/
get description(): Description { get description(): Description {
return this.props.description; return this.props.description;

View File

@ -1,16 +1,9 @@
import { Article } from "@/contexts/catalog/domain"; import { Article } from "@/contexts/catalog/domain";
import { ICatalogContext } from "@/contexts/catalog/infrastructure"; import { ICatalogContext } from "@/contexts/catalog/infrastructure";
import { import { ICollection, IListArticles_Response_DTO, IListResponse_DTO } from "@shared/contexts";
ICollection,
IListArticles_Response_DTO,
IListResponse_DTO,
} from "@shared/contexts";
export interface IListArticlesPresenter { export interface IListArticlesPresenter {
map: ( map: (article: Article, context: ICatalogContext) => IListArticles_Response_DTO;
article: Article,
context: ICatalogContext,
) => IListArticles_Response_DTO;
mapArray: ( mapArray: (
articles: ICollection<Article>, articles: ICollection<Article>,
@ -18,23 +11,20 @@ export interface IListArticlesPresenter {
params: { params: {
page: number; page: number;
limit: number; limit: number;
}, }
) => IListResponse_DTO<IListArticles_Response_DTO>; ) => IListResponse_DTO<IListArticles_Response_DTO>;
} }
export const listArticlesPresenter: IListArticlesPresenter = { export const listArticlesPresenter: IListArticlesPresenter = {
map: ( map: (article: Article, context: ICatalogContext): IListArticles_Response_DTO => {
article: Article,
context: ICatalogContext,
): IListArticles_Response_DTO => {
const result: IListArticles_Response_DTO = { const result: IListArticles_Response_DTO = {
id: article.id.toString(), id: article.id.toString(),
catalog_name: article.catalog_name.toString(), catalog_name: article.catalog_name.toString(),
id_article: article.id_article.toString(), id_article: article.id_article.toString(),
reference: article.reference.toString(), reference: article.reference.toString(),
description: article.description.toString(), description: article.description.toString(),
family: article.family.toString(), //family: article.family.toString(),
subfamily: article.subfamily.toString(), //subfamily: article.subfamily.toString(),
points: article.points.toNumber(), points: article.points.toNumber(),
retail_price: article.retail_price.toObject(), retail_price: article.retail_price.toObject(),
}; };
@ -47,13 +37,13 @@ export const listArticlesPresenter: IListArticlesPresenter = {
params: { params: {
page: number; page: number;
limit: number; limit: number;
}, }
): IListResponse_DTO<IListArticles_Response_DTO> => { ): IListResponse_DTO<IListArticles_Response_DTO> => {
const { page, limit } = params; const { page, limit } = params;
const totalCount = articles.totalCount ?? 0; const totalCount = articles.totalCount ?? 0;
const items = articles.items.map((article: Article) => const items = articles.items.map((article: Article) =>
listArticlesPresenter.map(article, context), listArticlesPresenter.map(article, context)
); );
const result = { const result = {

View File

@ -13,11 +13,10 @@ export const CatalogRouter = (appRouter: Express.Router) => {
catalogRoutes.get( catalogRoutes.get(
"/", "/",
isUser,
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => (req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
listArticlesController(res.locals["context"]).execute(req, res, next) listArticlesController(res.locals["context"]).execute(req, res, next)
); );
catalogRoutes.use(isUser);
appRouter.use("/catalog", catalogRoutes); appRouter.use("/catalog", catalogRoutes);
}; };

View File

@ -1,24 +1,8 @@
import { import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
ISequelizeMapper, import { Description, Quantity, Slug, UniqueID, UnitPrice } from "@shared/contexts";
SequelizeMapper,
} from "@/contexts/common/infrastructure";
import {
Description,
Quantity,
Slug,
UniqueID,
UnitPrice,
} from "@shared/contexts";
import { ICatalogContext } from ".."; import { ICatalogContext } from "..";
import { import { Article, ArticleIdentifier, IArticleProps } from "../../domain/entities";
Article, import { ArticleCreationAttributes, Article_Model } from "../sequelize/article.model";
ArticleIdentifier,
IArticleProps,
} from "../../domain/entities";
import {
ArticleCreationAttributes,
Article_Model,
} from "../sequelize/article.model";
export interface IArticleMapper export interface IArticleMapper
extends ISequelizeMapper<Article_Model, ArticleCreationAttributes, Article> {} extends ISequelizeMapper<Article_Model, ArticleCreationAttributes, Article> {}
@ -34,18 +18,14 @@ class ArticleMapper
protected toDomainMappingImpl(source: Article_Model, params: any): Article { protected toDomainMappingImpl(source: Article_Model, params: any): Article {
const props: IArticleProps = { const props: IArticleProps = {
catalog_name: this.mapsValue(source, "catalog_name", Slug.create), catalog_name: this.mapsValue(source, "catalog_name", Slug.create),
id_article: this.mapsValue( id_article: this.mapsValue(source, "id_article", ArticleIdentifier.create),
source,
"id_article",
ArticleIdentifier.create,
),
reference: this.mapsValue(source, "reference", Slug.create), reference: this.mapsValue(source, "reference", Slug.create),
family: this.mapsValue(source, "family", Description.create), //family: this.mapsValue(source, "family", Description.create),
subfamily: this.mapsValue(source, "subfamily", Description.create), //subfamily: this.mapsValue(source, "subfamily", Description.create),
description: this.mapsValue(source, "description", Description.create), description: this.mapsValue(source, "description", Description.create),
points: this.mapsValue(source, "points", Quantity.create), points: this.mapsValue(source, "points", Quantity.create),
retail_price: this.mapsValue(source, "retail_price", (value: any) => retail_price: this.mapsValue(source, "retail_price", (value: any) =>
UnitPrice.create({ amount: value, precision: 4 }), UnitPrice.create({ amount: value, precision: 4 })
), ),
}; };

View File

@ -26,8 +26,8 @@ export class Article_Model extends Model<
declare catalog_name: string; declare catalog_name: string;
declare id_article: string; // number ?? declare id_article: string; // number ??
declare reference: CreationOptional<string>; declare reference: CreationOptional<string>;
declare family: CreationOptional<string>; //declare family: CreationOptional<string>;
declare subfamily: CreationOptional<string>; //declare subfamily: CreationOptional<string>;
declare description: CreationOptional<string>; declare description: CreationOptional<string>;
declare points: CreationOptional<number>; declare points: CreationOptional<number>;
declare retail_price: CreationOptional<number>; declare retail_price: CreationOptional<number>;
@ -50,8 +50,8 @@ export default (sequelize: Sequelize) => {
allowNull: false, allowNull: false,
}, },
reference: DataTypes.STRING(), reference: DataTypes.STRING(),
family: DataTypes.STRING(), //family: DataTypes.STRING(),
subfamily: DataTypes.STRING(), //subfamily: DataTypes.STRING(),
description: DataTypes.STRING(), description: DataTypes.STRING(),
points: { points: {
type: DataTypes.SMALLINT().UNSIGNED, type: DataTypes.SMALLINT().UNSIGNED,
@ -74,8 +74,8 @@ export default (sequelize: Sequelize) => {
indexes: [ indexes: [
{ name: "catalog_name_idx", fields: ["catalog_name"] }, { name: "catalog_name_idx", fields: ["catalog_name"] },
{ name: "id_article_idx", fields: ["id_article"] }, { name: "id_article_idx", fields: ["id_article"] },
{ name: "family_idx", fields: ["family"] }, //{ name: "family_idx", fields: ["family"] },
{ name: "family_subfamily_idx", fields: ["family", "subfamily"] }, //{ name: "family_subfamily_idx", fields: ["family", "subfamily"] },
{ name: "updated_at_idx", fields: ["updated_at"] }, { name: "updated_at_idx", fields: ["updated_at"] },
], ],
@ -88,12 +88,12 @@ export default (sequelize: Sequelize) => {
reference: { reference: {
[Op.like]: `%${value}%`, [Op.like]: `%${value}%`,
}, },
family: { /*family: {
[Op.like]: `%${value}%`, [Op.like]: `%${value}%`,
}, },
subfamily: { subfamily: {
[Op.like]: `%${value}%`, [Op.like]: `%${value}%`,
}, },*/
description: { description: {
[Op.like]: `%${value}%`, [Op.like]: `%${value}%`,
}, },
@ -102,7 +102,7 @@ export default (sequelize: Sequelize) => {
}; };
}, },
}, },
}, }
); );
return Article_Model; return Article_Model;

View File

@ -50,6 +50,7 @@ export class Dealer_Model extends Model<
declare default_legal_terms: string; declare default_legal_terms: string;
declare default_quote_validity: string; declare default_quote_validity: string;
declare status: DEALER_STATUS; declare status: DEALER_STATUS;
declare language: string;
} }
export default (sequelize: Sequelize) => { export default (sequelize: Sequelize) => {
@ -75,6 +76,7 @@ export default (sequelize: Sequelize) => {
default_notes: DataTypes.STRING, default_notes: DataTypes.STRING,
default_legal_terms: DataTypes.STRING, default_legal_terms: DataTypes.STRING,
default_quote_validity: DataTypes.STRING, default_quote_validity: DataTypes.STRING,
language: DataTypes.STRING,
status: { status: {
type: DataTypes.ENUM(...Object.values(DEALER_STATUS)), type: DataTypes.ENUM(...Object.values(DEALER_STATUS)),

View File

@ -1,6 +1,6 @@
import { config } from "@/config"; import { config } from "@/config";
import { IAdapter, Password, RepositoryBuilder } from "@/contexts/common/domain"; import { IAdapter, Password, RepositoryBuilder } from "@/contexts/common/domain";
import { Email, Name, UniqueID } from "@shared/contexts"; import { Email, Language, Name, UniqueID } from "@shared/contexts";
import { IUserRepository, User, UserRole } from "../domain"; import { IUserRepository, User, UserRole } from "../domain";
export const existsUserByID = async ( export const existsUserByID = async (
@ -66,6 +66,7 @@ export const initializeAdmin = async (
name: Name.create(config.admin.name).object, name: Name.create(config.admin.name).object,
email: Email.create(config.admin.email).object, email: Email.create(config.admin.email).object,
password: Password.createFromPlainTextPassword(config.admin.password).object, password: Password.createFromPlainTextPassword(config.admin.password).object,
language: Language.createFromCode(config.admin.language).object,
roles: [UserRole.ROLE_ADMIN], roles: [UserRole.ROLE_ADMIN],
}, },
UniqueID.generateNewID().object UniqueID.generateNewID().object

View File

@ -3,6 +3,7 @@ import {
AggregateRoot, AggregateRoot,
Email, Email,
IDomainError, IDomainError,
Language,
Name, Name,
Result, Result,
UniqueID, UniqueID,
@ -16,6 +17,7 @@ export interface IUserProps {
email: Email; email: Email;
password: Password; password: Password;
roles: UserRole[]; roles: UserRole[];
language: Language;
} }
//type ISecuredUserProps = ; //type ISecuredUserProps = ;
@ -25,6 +27,7 @@ export interface IUser {
name: Name; name: Name;
email: Email; email: Email;
password: Password; password: Password;
language: Language;
isUser: boolean; isUser: boolean;
isAdmin: boolean; isAdmin: boolean;
} }
@ -69,6 +72,10 @@ export class User extends AggregateRoot<IUserProps> implements IUser {
return this.props.password; return this.props.password;
} }
get language(): Language {
return this.props.language;
}
get isUser(): boolean { get isUser(): boolean {
return this.hasRole(UserRole.ROLE_USER); return this.hasRole(UserRole.ROLE_USER);
} }

View File

@ -15,6 +15,10 @@ export class UserRole extends ValueObject<string> {
} }
} }
public toString(): string {
return this.props.toString();
}
public toPrimitive(): string { public toPrimitive(): string {
return this.toString(); return this.toString();
} }

View File

@ -12,6 +12,7 @@ export const GetUserPresenter: IGetUserPresenter = {
id: user.id.toString(), id: user.id.toString(),
name: user.name.toString(), name: user.name.toString(),
email: user.email.toString(), email: user.email.toString(),
language: "es",
roles: user.getRoles().map((rol) => rol.toString()), roles: user.getRoles().map((rol) => rol.toString()),
}; };
}, },

View File

@ -1,4 +1,4 @@
import { isAdmin } from "@/contexts/auth"; import { isAdmin, isAdminOrMe } from "@/contexts/auth";
import Express from "express"; import Express from "express";
import { import {
createCreateUserController, createCreateUserController,
@ -20,7 +20,7 @@ export const UserRouter = (appRouter: Express.Router) => {
userRoutes.get( userRoutes.get(
"/:userId", "/:userId",
isAdmin, isAdminOrMe,
(req: Express.Request, res: Express.Response, next: Express.NextFunction) => (req: Express.Request, res: Express.Response, next: Express.NextFunction) =>
createGetUserController(res.locals["context"]).execute(req, res, next) createGetUserController(res.locals["context"]).execute(req, res, next)
); );

View File

@ -1,6 +1,6 @@
import { Password } from "@/contexts/common/domain"; 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 { Email, Language, Name, UniqueID } from "@shared/contexts";
import { IUserProps, User, UserRole } from "../../domain"; import { IUserProps, User, UserRole } from "../../domain";
import { IUserContext } from "../User.context"; import { IUserContext } from "../User.context";
import { UserCreationAttributes, User_Model } from "../sequelize/user.model"; import { UserCreationAttributes, User_Model } from "../sequelize/user.model";
@ -21,6 +21,7 @@ class UserMapper
email: this.mapsValue(source, "email", Email.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), roles: source.roles.map((rol) => UserRole.create(rol).object),
language: this.mapsValue(source, "language", Language.createFromCode),
}; };
const id = this.mapsValue(source, "id", UniqueID.create); const id = this.mapsValue(source, "id", UniqueID.create);
@ -39,6 +40,7 @@ class UserMapper
name: source.name.toPrimitive(), name: source.name.toPrimitive(),
email: source.email.toPrimitive(), email: source.email.toPrimitive(),
password: source.password.toPrimitive(), password: source.password.toPrimitive(),
language: source.language.toPrimitive(),
roles: source.getRoles().map((rol) => rol.toPrimitive()), roles: source.getRoles().map((rol) => rol.toPrimitive()),
}; };
} }

View File

@ -38,6 +38,7 @@ export class User_Model extends Model<
declare name: string; declare name: string;
declare email: string; declare email: string;
declare password: string; declare password: string;
declare language: string;
declare roles: string[]; declare roles: string[];
} }
@ -63,15 +64,23 @@ export default (sequelize: Sequelize) => {
allowNull: false, allowNull: false,
}, },
language: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: "es",
},
roles: { roles: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,
defaultValue: USER_ROLES.ROLE_USER, defaultValue: USER_ROLES.ROLE_USER,
get(this: User_Model): string[] { get(this: User_Model): string[] {
return this.getDataValue("roles").split(";"); const rawValue = this.getDataValue("roles") as any;
return String(rawValue).split(";");
}, },
set(this: User_Model, value: string[]) { set(this: User_Model, value: string[]) {
this.setDataValue("roles", value.join(";")); const rawValue = value.join(";") as any;
this.setDataValue("roles", rawValue);
}, },
}, },
}, },

View File

@ -2,5 +2,6 @@ export interface IIdentity_Response_DTO {
id: string; id: string;
name: string; name: string;
email: string; email: string;
language: string;
roles: string[]; roles: string[];
} }

View File

@ -5,8 +5,8 @@ export interface IListArticles_Response_DTO {
catalog_name: string; catalog_name: string;
id_article: string; id_article: string;
reference: string; reference: string;
family: string; //family: string;
subfamily: string; //subfamily: string;
description: string; description: string;
points: number; points: number;
retail_price: IMoney_Response_DTO; retail_price: IMoney_Response_DTO;

View File

@ -2,5 +2,6 @@ export interface IGetUserResponse_DTO {
id: string; id: string;
name: string; name: string;
email: string; email: string;
language: string;
roles: string[]; roles: string[];
} }