.
This commit is contained in:
parent
6ead69908c
commit
52de165a52
@ -6,34 +6,9 @@ import { IAuthRepository } from "../domain/repository";
|
|||||||
export const findUserByEmail = async (
|
export const findUserByEmail = async (
|
||||||
email: Email,
|
email: Email,
|
||||||
adapter: IAdapter,
|
adapter: IAdapter,
|
||||||
repository: RepositoryBuilder<IAuthRepository>,
|
repository: RepositoryBuilder<IAuthRepository>
|
||||||
): Promise<AuthUser | null> => {
|
): Promise<AuthUser | null> => {
|
||||||
return await adapter
|
return await adapter
|
||||||
.startTransaction()
|
.startTransaction()
|
||||||
.complete(async (t) =>
|
.complete(async (t) => repository({ transaction: t }).findUserByEmail(email));
|
||||||
repository({ transaction: t }).findUserByEmail(email),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*export class AuthService extends ApplicationService {
|
|
||||||
private _adapter: ISequelizeAdapter;
|
|
||||||
private _repository: IRepositoryManager;
|
|
||||||
private _authRepository: IAuthRepository;
|
|
||||||
|
|
||||||
constructor(props: {
|
|
||||||
adapter: ISequelizeAdapter,
|
|
||||||
repository: IRepositoryManager,
|
|
||||||
}) {
|
|
||||||
super();
|
|
||||||
this._adapter = props.adapter;
|
|
||||||
|
|
||||||
this._repository = props.repository;
|
|
||||||
|
|
||||||
this._repository.getRepository<IAuthRepository>("auth")
|
|
||||||
|
|
||||||
this._authRepository = ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@ -1,11 +1,20 @@
|
|||||||
import { Password } from "@/contexts/common/domain";
|
import { Password } from "@/contexts/common/domain";
|
||||||
import { AggregateRoot, Email, IDomainError, Name, Result, UniqueID } from "@shared/contexts";
|
import {
|
||||||
|
AggregateRoot,
|
||||||
|
Email,
|
||||||
|
IDomainError,
|
||||||
|
Language,
|
||||||
|
Name,
|
||||||
|
Result,
|
||||||
|
UniqueID,
|
||||||
|
} from "@shared/contexts";
|
||||||
import { AuthUserRole } from "./AuthUserRole";
|
import { AuthUserRole } from "./AuthUserRole";
|
||||||
|
|
||||||
export interface IAuthUserProps {
|
export interface IAuthUserProps {
|
||||||
name: Name;
|
name: Name;
|
||||||
email: Email;
|
email: Email;
|
||||||
password: Password;
|
password: Password;
|
||||||
|
language: Language;
|
||||||
roles: AuthUserRole[];
|
roles: AuthUserRole[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +23,7 @@ export interface IAuthUser {
|
|||||||
name: Name;
|
name: Name;
|
||||||
email: Email;
|
email: Email;
|
||||||
password: Password;
|
password: Password;
|
||||||
|
language: Language;
|
||||||
isUser: boolean;
|
isUser: boolean;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
getRoles: () => AuthUserRole[];
|
getRoles: () => AuthUserRole[];
|
||||||
@ -51,6 +61,10 @@ export class AuthUser extends AggregateRoot<IAuthUserProps> implements IAuthUser
|
|||||||
return this.props.password;
|
return this.props.password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get language(): Language {
|
||||||
|
return this.props.language;
|
||||||
|
}
|
||||||
|
|
||||||
get isUser(): boolean {
|
get isUser(): boolean {
|
||||||
return this._hasRole(AuthUserRole.ROLE_USER);
|
return this._hasRole(AuthUserRole.ROLE_USER);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,37 +4,7 @@ import { IServerError } from "@/contexts/common/domain/errors";
|
|||||||
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
import { ExpressController } from "@/contexts/common/infrastructure/express";
|
||||||
import passport from "passport";
|
import passport from "passport";
|
||||||
|
|
||||||
// Export a middleware function to authenticate incoming requests
|
|
||||||
/*export const authenticate = (req, res, next) => {
|
|
||||||
// Use Passport to authenticate the request using the "jwt" strategy
|
|
||||||
passport.authenticate("jwt", { session: false }, (err, user) => {
|
|
||||||
console.log(user);
|
|
||||||
if (err) next(err); // If there's an error, pass it on to the next middleware
|
|
||||||
if (!user) {
|
|
||||||
// If the user is not authenticated, send a 401 Unauthorized response
|
|
||||||
return res.status(401).json({
|
|
||||||
message: "Unauthorized access. No token provided.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// If the user is authenticated, attach the user object to the request and move on to the next middleware
|
|
||||||
req.user = user;
|
|
||||||
next();
|
|
||||||
})(req, res, next);
|
|
||||||
};*/
|
|
||||||
|
|
||||||
export class AuthenticateController extends ExpressController {
|
export class AuthenticateController extends ExpressController {
|
||||||
//private context: AuthContext;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
//context: IAuthContext,
|
|
||||||
super();
|
|
||||||
|
|
||||||
/*const { useCase, presenter } = props;
|
|
||||||
this.useCase = useCase;
|
|
||||||
this.presenter = presenter;
|
|
||||||
this.context = context;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
async executeImpl() {
|
async executeImpl() {
|
||||||
try {
|
try {
|
||||||
return passport.authenticate(
|
return passport.authenticate(
|
||||||
@ -44,22 +14,20 @@ export class AuthenticateController extends ExpressController {
|
|||||||
err: any,
|
err: any,
|
||||||
user?: AuthUser | false | null,
|
user?: AuthUser | false | null,
|
||||||
info?: object | string | Array<string | undefined>,
|
info?: object | string | Array<string | undefined>,
|
||||||
status?: number | Array<number | undefined>,
|
status?: number | Array<number | undefined>
|
||||||
) => {
|
) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return this.next(err);
|
return this.next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return this.unauthorizedError(
|
return this.unauthorizedError("Unauthorized access. No token provided.");
|
||||||
"Unauthorized access. No token provided.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is authenticated, attach the user object to the request and move on to the next middleware
|
// If the user is authenticated, attach the user object to the request and move on to the next middleware
|
||||||
this.req.user = user;
|
this.req.user = user;
|
||||||
return this.next();
|
return this.next();
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
return this.fail(e as IServerError);
|
return this.fail(e as IServerError);
|
||||||
|
|||||||
@ -2,9 +2,7 @@ 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;
|
||||||
@ -17,7 +15,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",
|
language: user.language.toString(),
|
||||||
roles: user.getRoles()?.map((rol) => rol.toString()),
|
roles: user.getRoles()?.map((rol) => rol.toString()),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export const loginPresenter: ILoginPresenter = {
|
|||||||
id: user.id.toString(),
|
id: user.id.toString(),
|
||||||
name: user.name.toString(),
|
name: user.name.toString(),
|
||||||
email: user.email.toString(),
|
email: user.email.toString(),
|
||||||
|
lang_code: user.language.toString(),
|
||||||
roles,
|
roles,
|
||||||
token,
|
token,
|
||||||
refresh_token: refreshToken,
|
refresh_token: refreshToken,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
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 { UserRole } from "@/contexts/users/domain";
|
import { UserRole } from "@/contexts/users/domain";
|
||||||
import { Email, Name, UniqueID } from "@shared/contexts";
|
import { Email, Language, 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 { AuthUserCreationAttributes, AuthUser_Model } from "../sequelize/authUser.model";
|
import { AuthUserCreationAttributes, AuthUser_Model } from "../sequelize/authUser.model";
|
||||||
@ -22,6 +22,9 @@ class AuthUserMapper
|
|||||||
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(source, "password", Password.createFromHashedTextPassword),
|
password: this.mapsValue(source, "password", Password.createFromHashedTextPassword),
|
||||||
|
language: this.mapsValue(source, "lang_code", Language.createFromCode, {
|
||||||
|
defaultValue: Language.DEFAULT_LANGUAGE_CODE,
|
||||||
|
}),
|
||||||
roles: source.roles.map((rol) => UserRole.create(rol).object),
|
roles: source.roles.map((rol) => UserRole.create(rol).object),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,6 +44,7 @@ class AuthUserMapper
|
|||||||
name: source.name.toPrimitive(),
|
name: source.name.toPrimitive(),
|
||||||
email: source.email.toPrimitive(),
|
email: source.email.toPrimitive(),
|
||||||
password: source.password.toPrimitive(),
|
password: source.password.toPrimitive(),
|
||||||
|
lang_code: source.language.toPrimitive(),
|
||||||
roles: source.getRoles().map((role) => role.toPrimitive()),
|
roles: source.getRoles().map((role) => role.toPrimitive()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,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 lang_code: string;
|
||||||
declare roles: string[];
|
declare roles: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +45,12 @@ export default (sequelize: Sequelize) => {
|
|||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
lang_code: {
|
||||||
|
type: DataTypes.STRING(2),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "es",
|
||||||
|
},
|
||||||
|
|
||||||
roles: {
|
roles: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import {
|
|||||||
AggregateRoot,
|
AggregateRoot,
|
||||||
Description,
|
Description,
|
||||||
IDomainError,
|
IDomainError,
|
||||||
|
Language,
|
||||||
|
Name,
|
||||||
Quantity,
|
Quantity,
|
||||||
Result,
|
Result,
|
||||||
Slug,
|
Slug,
|
||||||
@ -11,9 +13,10 @@ import {
|
|||||||
import { ArticleIdentifier } from "./ArticleIdentifier";
|
import { ArticleIdentifier } from "./ArticleIdentifier";
|
||||||
|
|
||||||
export interface IArticleProps {
|
export interface IArticleProps {
|
||||||
catalog_name: Slug;
|
catalog_name: Name;
|
||||||
id_article: ArticleIdentifier;
|
id_article: ArticleIdentifier;
|
||||||
reference: Slug;
|
reference: Slug;
|
||||||
|
language: Language;
|
||||||
description: Description;
|
description: Description;
|
||||||
points: Quantity;
|
points: Quantity;
|
||||||
retail_price: UnitPrice;
|
retail_price: UnitPrice;
|
||||||
@ -21,9 +24,10 @@ export interface IArticleProps {
|
|||||||
|
|
||||||
export interface IArticle {
|
export interface IArticle {
|
||||||
id: UniqueID;
|
id: UniqueID;
|
||||||
catalog_name: Slug;
|
catalog_name: Name;
|
||||||
id_article: ArticleIdentifier;
|
id_article: ArticleIdentifier;
|
||||||
reference: Slug;
|
reference: Slug;
|
||||||
|
language: Language;
|
||||||
description: Description;
|
description: Description;
|
||||||
points: Quantity;
|
points: Quantity;
|
||||||
retail_price: UnitPrice;
|
retail_price: UnitPrice;
|
||||||
@ -63,6 +67,10 @@ export class Article extends AggregateRoot<IArticleProps> implements IArticle {
|
|||||||
return this.props.reference;
|
return this.props.reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get language(): Language {
|
||||||
|
return this.props.language;
|
||||||
|
}
|
||||||
|
|
||||||
get description(): Description {
|
get description(): Description {
|
||||||
return this.props.description;
|
return this.props.description;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import Joi from "joi";
|
import Joi from "joi";
|
||||||
|
|
||||||
|
import { AuthUser } from "@/contexts/auth/domain";
|
||||||
import { ListArticlesResult, ListArticlesUseCase } from "@/contexts/catalog/application";
|
import { ListArticlesResult, ListArticlesUseCase } from "@/contexts/catalog/application";
|
||||||
import { Article } from "@/contexts/catalog/domain";
|
import { Article } from "@/contexts/catalog/domain";
|
||||||
import { QueryCriteriaService } from "@/contexts/common/application/services";
|
import { QueryCriteriaService } from "@/contexts/common/application/services";
|
||||||
@ -10,6 +11,7 @@ import {
|
|||||||
IListArticles_Response_DTO,
|
IListArticles_Response_DTO,
|
||||||
IListResponse_DTO,
|
IListResponse_DTO,
|
||||||
IQueryCriteria,
|
IQueryCriteria,
|
||||||
|
Language,
|
||||||
Result,
|
Result,
|
||||||
RuleValidator,
|
RuleValidator,
|
||||||
} from "@shared/contexts";
|
} from "@shared/contexts";
|
||||||
@ -49,7 +51,13 @@ export class ListArticlesController extends ExpressController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async executeImpl() {
|
async executeImpl() {
|
||||||
const queryOrError = this.validateQuery(this.req.query);
|
const { language = Language.createDefaultCode() } = <AuthUser>this.req.user;
|
||||||
|
|
||||||
|
const queryOrError = this.validateQuery({
|
||||||
|
$filters: `lang_code[eq]${language.toString()}`,
|
||||||
|
...this.req.query,
|
||||||
|
});
|
||||||
|
|
||||||
if (queryOrError.isFailure) {
|
if (queryOrError.isFailure) {
|
||||||
return this.clientError(queryOrError.error.message);
|
return this.clientError(queryOrError.error.message);
|
||||||
}
|
}
|
||||||
@ -67,10 +75,10 @@ export class ListArticlesController extends ExpressController {
|
|||||||
return this.clientError(result.error.message);
|
return this.clientError(result.error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const customers = <ICollection<Article>>result.object;
|
const articles = <ICollection<Article>>result.object;
|
||||||
|
|
||||||
return this.ok<IListResponse_DTO<IListArticles_Response_DTO>>(
|
return this.ok<IListResponse_DTO<IListArticles_Response_DTO>>(
|
||||||
this.presenter.mapArray(customers, this.context, {
|
this.presenter.mapArray(articles, this.context, {
|
||||||
page: queryCriteria.pagination.offset,
|
page: queryCriteria.pagination.offset,
|
||||||
limit: queryCriteria.pagination.limit,
|
limit: queryCriteria.pagination.limit,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
|
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
|
||||||
import { Description, Quantity, Slug, UniqueID, UnitPrice } from "@shared/contexts";
|
import { Description, Language, Name, Quantity, Slug, UniqueID, UnitPrice } from "@shared/contexts";
|
||||||
import { ICatalogContext } from "..";
|
import { ICatalogContext } from "..";
|
||||||
import { Article, ArticleIdentifier, IArticleProps } from "../../domain/entities";
|
import { Article, ArticleIdentifier, IArticleProps } from "../../domain/entities";
|
||||||
import { ArticleCreationAttributes, Article_Model } from "../sequelize/article.model";
|
import { ArticleCreationAttributes, Article_Model } from "../sequelize";
|
||||||
|
|
||||||
export interface IArticleMapper
|
export interface IArticleMapper
|
||||||
extends ISequelizeMapper<Article_Model, ArticleCreationAttributes, Article> {}
|
extends ISequelizeMapper<Article_Model, ArticleCreationAttributes, Article> {}
|
||||||
@ -16,15 +16,27 @@ class ArticleMapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected toDomainMappingImpl(source: Article_Model, params: any): Article {
|
protected toDomainMappingImpl(source: Article_Model, params: any): Article {
|
||||||
|
const catalog_name = this.mapsValue(source, "catalog_name", Name.create);
|
||||||
|
const id_article = this.mapsValue(source, "id_article", ArticleIdentifier.create);
|
||||||
|
const reference = this.mapsValue(source, "reference", Slug.create);
|
||||||
|
const points = this.mapsValue(source, "points", (value: any) =>
|
||||||
|
Quantity.create({ amount: value, precision: 4 })
|
||||||
|
);
|
||||||
|
const retail_price = this.mapsValue(source, "retail_price", (value: any) =>
|
||||||
|
UnitPrice.create({ amount: value, precision: 4 })
|
||||||
|
);
|
||||||
|
|
||||||
|
const language = this.mapsValue(source, "lang_code", Language.createFromCode);
|
||||||
|
const description = this.mapsValue(source, "description", Description.create);
|
||||||
|
|
||||||
const props: IArticleProps = {
|
const props: IArticleProps = {
|
||||||
catalog_name: this.mapsValue(source, "catalog_name", Slug.create),
|
catalog_name,
|
||||||
id_article: this.mapsValue(source, "id_article", ArticleIdentifier.create),
|
id_article,
|
||||||
reference: this.mapsValue(source, "reference", Slug.create),
|
reference,
|
||||||
description: this.mapsValue(source, "description", Description.create),
|
points,
|
||||||
points: this.mapsValue(source, "points", Quantity.create),
|
retail_price,
|
||||||
retail_price: this.mapsValue(source, "retail_price", (value: any) =>
|
language,
|
||||||
UnitPrice.create({ amount: value, precision: 4 })
|
description,
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = this.mapsValue(source, "id", UniqueID.create);
|
const id = this.mapsValue(source, "id", UniqueID.create);
|
||||||
|
|||||||
@ -15,9 +15,9 @@ export class Article_Model extends Model<
|
|||||||
InferCreationAttributes<Article_Model>
|
InferCreationAttributes<Article_Model>
|
||||||
> {
|
> {
|
||||||
// To avoid table creation
|
// To avoid table creation
|
||||||
/*static async sync(): Promise<any> {
|
static async sync(): Promise<any> {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}*/
|
}
|
||||||
|
|
||||||
static associate(connection: Sequelize) {}
|
static associate(connection: Sequelize) {}
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ 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 lang_code: 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>;
|
||||||
@ -43,37 +44,38 @@ export default (sequelize: Sequelize) => {
|
|||||||
type: DataTypes.STRING(),
|
type: DataTypes.STRING(),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
id_article: {
|
id_article: {
|
||||||
type: DataTypes.BIGINT().UNSIGNED,
|
type: DataTypes.BIGINT().UNSIGNED,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
reference: DataTypes.STRING(),
|
reference: DataTypes.STRING(),
|
||||||
|
|
||||||
|
lang_code: {
|
||||||
|
type: DataTypes.STRING(2),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "es",
|
||||||
|
},
|
||||||
|
|
||||||
description: DataTypes.STRING(),
|
description: DataTypes.STRING(),
|
||||||
|
|
||||||
points: {
|
points: {
|
||||||
type: DataTypes.SMALLINT().UNSIGNED,
|
type: DataTypes.BIGINT().UNSIGNED,
|
||||||
defaultValue: 0,
|
defaultValue: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
retail_price: DataTypes.BIGINT(),
|
retail_price: DataTypes.BIGINT(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize,
|
sequelize,
|
||||||
tableName: "catalog",
|
tableName: "v_catalog",
|
||||||
|
|
||||||
//paranoid: true, // softs deletes
|
paranoid: true, // softs deletes
|
||||||
timestamps: true,
|
timestamps: false,
|
||||||
//version: true,
|
|
||||||
|
|
||||||
createdAt: "created_at",
|
|
||||||
updatedAt: "updated_at",
|
|
||||||
deletedAt: "deleted_at",
|
|
||||||
|
|
||||||
indexes: [
|
|
||||||
{ name: "catalog_name_idx", fields: ["catalog_name"] },
|
|
||||||
{ name: "id_article_idx", fields: ["id_article"] },
|
|
||||||
{ name: "updated_at_idx", fields: ["updated_at"] },
|
|
||||||
],
|
|
||||||
|
|
||||||
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
|
||||||
scopes: {
|
scopes: {
|
||||||
quickSearch(value) {
|
quickSearch(value) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -0,0 +1,140 @@
|
|||||||
|
import {
|
||||||
|
CreationOptional,
|
||||||
|
DataTypes,
|
||||||
|
InferAttributes,
|
||||||
|
InferCreationAttributes,
|
||||||
|
Model,
|
||||||
|
NonAttribute,
|
||||||
|
Op,
|
||||||
|
Sequelize,
|
||||||
|
} from "sequelize";
|
||||||
|
import { ArticleTranslation_Model } from "./articleTraslation.model.ts.bak";
|
||||||
|
|
||||||
|
export type ArticleCreationAttributes = InferCreationAttributes<
|
||||||
|
Article_Model,
|
||||||
|
{
|
||||||
|
omit: "translations";
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
export class Article_Model extends Model<
|
||||||
|
InferAttributes<Article_Model, { omit: "translations" }>,
|
||||||
|
InferCreationAttributes<Article_Model, { omit: "translations" }>
|
||||||
|
> {
|
||||||
|
// To avoid table creation
|
||||||
|
static async sync(): Promise<any> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
static associate(connection: Sequelize) {
|
||||||
|
const { Article_Model, ArticleTranslation_Model } = connection.models;
|
||||||
|
|
||||||
|
Article_Model.hasMany(ArticleTranslation_Model, {
|
||||||
|
as: "translations",
|
||||||
|
foreignKey: "catalog_id",
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
declare id: string;
|
||||||
|
|
||||||
|
declare catalog_name: string;
|
||||||
|
declare id_article: string; // number ??
|
||||||
|
declare reference: CreationOptional<string>;
|
||||||
|
//declare description: CreationOptional<string>;
|
||||||
|
declare points: CreationOptional<number>;
|
||||||
|
declare retail_price: CreationOptional<number>;
|
||||||
|
|
||||||
|
declare translations?: NonAttribute<ArticleTranslation_Model[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (sequelize: Sequelize) => {
|
||||||
|
Article_Model.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: new DataTypes.UUID(),
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
catalog_name: {
|
||||||
|
type: DataTypes.STRING(),
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
id_article: {
|
||||||
|
type: DataTypes.BIGINT().UNSIGNED,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
reference: DataTypes.STRING(),
|
||||||
|
//description: DataTypes.STRING(),
|
||||||
|
points: {
|
||||||
|
type: DataTypes.BIGINT().UNSIGNED,
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
retail_price: DataTypes.BIGINT(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
tableName: "catalog",
|
||||||
|
|
||||||
|
paranoid: true, // softs deletes
|
||||||
|
timestamps: true,
|
||||||
|
//version: true,
|
||||||
|
|
||||||
|
createdAt: "created_at",
|
||||||
|
updatedAt: "updated_at",
|
||||||
|
deletedAt: "deleted_at",
|
||||||
|
|
||||||
|
indexes: [
|
||||||
|
{ name: "catalog_name_idx", fields: ["catalog_name"] },
|
||||||
|
{ name: "id_article_idx", fields: ["id_article"] },
|
||||||
|
{ name: "updated_at_idx", fields: ["updated_at"] },
|
||||||
|
],
|
||||||
|
|
||||||
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
|
||||||
|
defaultScope: {
|
||||||
|
attributes: { exclude: ["id_article", "reference"] },
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
attributes: ["description"],
|
||||||
|
model: ArticleTranslation_Model,
|
||||||
|
as: "translations",
|
||||||
|
required: true,
|
||||||
|
where: {
|
||||||
|
lang_code: "es",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
scopes: {
|
||||||
|
quickSearch(value) {
|
||||||
|
return {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: ArticleTranslation_Model,
|
||||||
|
as: "translations",
|
||||||
|
required: true,
|
||||||
|
where: {
|
||||||
|
[Op.or]: {
|
||||||
|
reference: {
|
||||||
|
[Op.like]: `%${value}%`,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
[Op.like]: `%${value}%`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Article_Model;
|
||||||
|
};
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
import {
|
||||||
|
CreationOptional,
|
||||||
|
DataTypes,
|
||||||
|
InferAttributes,
|
||||||
|
InferCreationAttributes,
|
||||||
|
Model,
|
||||||
|
Op,
|
||||||
|
Sequelize,
|
||||||
|
} from "sequelize";
|
||||||
|
|
||||||
|
export type ArticleTranslationCreationAttributes =
|
||||||
|
InferCreationAttributes<ArticleTranslation_Model>;
|
||||||
|
|
||||||
|
export class ArticleTranslation_Model extends Model<
|
||||||
|
InferAttributes<ArticleTranslation_Model>,
|
||||||
|
InferCreationAttributes<ArticleTranslation_Model>
|
||||||
|
> {
|
||||||
|
// To avoid table creation
|
||||||
|
/*static async sync(): Promise<any> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static associate(connection: Sequelize) {
|
||||||
|
const { Article_Model, ArticleTranslation_Model } = connection.models;
|
||||||
|
|
||||||
|
ArticleTranslation_Model.belongsTo(Article_Model, {
|
||||||
|
as: "translations",
|
||||||
|
foreignKey: "catalog_id",
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
declare id: string;
|
||||||
|
|
||||||
|
declare lang_code: CreationOptional<string>;
|
||||||
|
declare description: CreationOptional<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (sequelize: Sequelize) => {
|
||||||
|
ArticleTranslation_Model.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: new DataTypes.UUID(),
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
lang_code: {
|
||||||
|
type: DataTypes.STRING(2),
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "es",
|
||||||
|
},
|
||||||
|
|
||||||
|
description: DataTypes.STRING(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize,
|
||||||
|
tableName: "catalog_translations",
|
||||||
|
|
||||||
|
//paranoid: true, // softs deletes
|
||||||
|
timestamps: false,
|
||||||
|
//version: true,
|
||||||
|
|
||||||
|
indexes: [{ name: "lang_code_idx", fields: ["lang_code"] }],
|
||||||
|
|
||||||
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
scopes: {
|
||||||
|
quickSearch(value) {
|
||||||
|
return {
|
||||||
|
where: {
|
||||||
|
[Op.or]: {
|
||||||
|
description: {
|
||||||
|
[Op.like]: `%${value}%`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return ArticleTranslation_Model;
|
||||||
|
};
|
||||||
@ -9,10 +9,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
protected _transaction: Transaction;
|
protected _transaction: Transaction;
|
||||||
protected _adapter: ISequelizeAdapter;
|
protected _adapter: ISequelizeAdapter;
|
||||||
|
|
||||||
public constructor(props: {
|
public constructor(props: { adapter: ISequelizeAdapter; transaction: Transaction }) {
|
||||||
adapter: ISequelizeAdapter;
|
|
||||||
transaction: Transaction;
|
|
||||||
}) {
|
|
||||||
this._adapter = props.adapter;
|
this._adapter = props.adapter;
|
||||||
this._transaction = props.transaction;
|
this._transaction = props.transaction;
|
||||||
}
|
}
|
||||||
@ -49,7 +46,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
modelName: string,
|
modelName: string,
|
||||||
field: string,
|
field: string,
|
||||||
value: any,
|
value: any,
|
||||||
params: any = {},
|
params: any = {}
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const _model = this._adapter.getModel(modelName);
|
const _model = this._adapter.getModel(modelName);
|
||||||
const where: { [key: string]: any } = {};
|
const where: { [key: string]: any } = {};
|
||||||
@ -63,11 +60,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _getById(
|
protected async _getById(modelName: string, id: UniqueID | string, params: any = {}): Promise<T> {
|
||||||
modelName: string,
|
|
||||||
id: UniqueID | string,
|
|
||||||
params: any = {},
|
|
||||||
): Promise<T> {
|
|
||||||
const _model = this._adapter.getModel(modelName);
|
const _model = this._adapter.getModel(modelName);
|
||||||
return _model.findByPk(id.toString(), params);
|
return _model.findByPk(id.toString(), params);
|
||||||
}
|
}
|
||||||
@ -75,7 +68,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
protected async _findAll(
|
protected async _findAll(
|
||||||
modelName: string,
|
modelName: string,
|
||||||
queryCriteria?: IQueryCriteria,
|
queryCriteria?: IQueryCriteria,
|
||||||
params: any = {},
|
params: any = {}
|
||||||
): Promise<{ rows: any[]; count: number }> {
|
): Promise<{ rows: any[]; count: number }> {
|
||||||
console.time("_findAll");
|
console.time("_findAll");
|
||||||
|
|
||||||
@ -84,6 +77,8 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
queryCriteria,
|
queryCriteria,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(query);
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
...query,
|
...query,
|
||||||
distinct: true,
|
distinct: true,
|
||||||
@ -102,7 +97,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
modelName: string,
|
modelName: string,
|
||||||
field: string,
|
field: string,
|
||||||
value: any,
|
value: any,
|
||||||
params: any = {},
|
params: any = {}
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const _model = this._adapter.getModel(modelName) as ModelDefined<any, any>;
|
const _model = this._adapter.getModel(modelName) as ModelDefined<any, any>;
|
||||||
const where = {};
|
const where = {};
|
||||||
@ -120,7 +115,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
modelName: string,
|
modelName: string,
|
||||||
id: UniqueID,
|
id: UniqueID,
|
||||||
data: any,
|
data: any,
|
||||||
params: any = {},
|
params: any = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const _model = this._adapter.getModel(modelName);
|
const _model = this._adapter.getModel(modelName);
|
||||||
|
|
||||||
@ -134,7 +129,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
where: { id: id.toPrimitive() },
|
where: { id: id.toPrimitive() },
|
||||||
transaction: this._transaction,
|
transaction: this._transaction,
|
||||||
...params,
|
...params,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await _model.create(
|
await _model.create(
|
||||||
@ -146,7 +141,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
include: [{ all: true }],
|
include: [{ all: true }],
|
||||||
transaction: this._transaction,
|
transaction: this._transaction,
|
||||||
...params,
|
...params,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,7 +150,7 @@ export abstract class SequelizeRepository<T> implements IRepository<T> {
|
|||||||
modelName: string,
|
modelName: string,
|
||||||
id: UniqueID,
|
id: UniqueID,
|
||||||
force: boolean = false,
|
force: boolean = false,
|
||||||
params: any = {},
|
params: any = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const model: ModelDefined<any, any> = this._adapter.getModel(modelName);
|
const model: ModelDefined<any, any> = this._adapter.getModel(modelName);
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +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 lang_code: string;
|
||||||
declare roles: string[];
|
declare roles: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ export default (sequelize: Sequelize) => {
|
|||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
language: {
|
lang_code: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING(2),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: "es",
|
defaultValue: "es",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
|
import { checkUser, createLoginController } from "@/contexts/auth";
|
||||||
|
import { createIdentityController } from "@/contexts/auth/infrastructure/express/controllers/identity";
|
||||||
import Express from "express";
|
import Express from "express";
|
||||||
import passport from "passport";
|
import passport from "passport";
|
||||||
import { createLoginController } from "../../../../contexts/auth/infrastructure/express/controllers";
|
|
||||||
import { createIdentityController } from "../../../../contexts/auth/infrastructure/express/controllers/identity";
|
|
||||||
import { checkUser } from "../../../../contexts/auth/infrastructure/express/passport";
|
|
||||||
|
|
||||||
export const authRouter = (appRouter: Express.Router) => {
|
export const authRouter = (appRouter: Express.Router) => {
|
||||||
const authRoutes: Express.Router = Express.Router({ mergeParams: true });
|
const authRoutes: Express.Router = Express.Router({ mergeParams: true });
|
||||||
|
|||||||
@ -2,6 +2,7 @@ export interface ILogin_Response_DTO {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
lang_code: string;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
token: string;
|
token: string;
|
||||||
refresh_token: string;
|
refresh_token: string;
|
||||||
|
|||||||
@ -3,8 +3,8 @@ import { IMoney_Response_DTO } from "../../../../common";
|
|||||||
export interface IListArticles_Response_DTO {
|
export interface IListArticles_Response_DTO {
|
||||||
id: string;
|
id: string;
|
||||||
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;
|
||||||
|
|||||||
@ -3,15 +3,12 @@ import { UndefinedOr } from "../../../../utilities";
|
|||||||
import { RuleValidator } from "../RuleValidator";
|
import { RuleValidator } from "../RuleValidator";
|
||||||
import { DomainError, handleDomainError } from "../errors";
|
import { DomainError, handleDomainError } from "../errors";
|
||||||
import { Result } from "./Result";
|
import { Result } from "./Result";
|
||||||
import {
|
import { IStringValueObjectOptions, StringValueObject } from "./StringValueObject";
|
||||||
IStringValueObjectOptions,
|
|
||||||
StringValueObject,
|
|
||||||
} from "./StringValueObject";
|
|
||||||
|
|
||||||
export interface INameOptions extends IStringValueObjectOptions {}
|
export interface INameOptions extends IStringValueObjectOptions {}
|
||||||
|
|
||||||
export class Name extends StringValueObject {
|
export class Name extends StringValueObject {
|
||||||
private static readonly MIN_LENGTH = 2;
|
//private static readonly MIN_LENGTH = 1;
|
||||||
private static readonly MAX_LENGTH = 100;
|
private static readonly MAX_LENGTH = 100;
|
||||||
|
|
||||||
protected static validate(value: UndefinedOr<string>, options: INameOptions) {
|
protected static validate(value: UndefinedOr<string>, options: INameOptions) {
|
||||||
@ -20,7 +17,7 @@ export class Name extends StringValueObject {
|
|||||||
.allow("")
|
.allow("")
|
||||||
.default("")
|
.default("")
|
||||||
.trim()
|
.trim()
|
||||||
.min(Name.MIN_LENGTH)
|
//.min(Name.MIN_LENGTH)
|
||||||
.max(Name.MAX_LENGTH)
|
.max(Name.MAX_LENGTH)
|
||||||
.label(options.label ? options.label : "value");
|
.label(options.label ? options.label : "value");
|
||||||
|
|
||||||
@ -37,11 +34,7 @@ export class Name extends StringValueObject {
|
|||||||
|
|
||||||
if (validationResult.isFailure) {
|
if (validationResult.isFailure) {
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
handleDomainError(
|
handleDomainError(DomainError.INVALID_INPUT_DATA, validationResult.error.message, _options)
|
||||||
DomainError.INVALID_INPUT_DATA,
|
|
||||||
validationResult.error.message,
|
|
||||||
_options
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user