.
This commit is contained in:
parent
085a390aa6
commit
829c839f9b
@ -1,5 +1,6 @@
|
||||
import { Maybe, Result, ValueObject } from "@common/domain";
|
||||
import { Maybe, Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface EmailAddressProps {
|
||||
value: string;
|
||||
@ -47,4 +48,8 @@ export class EmailAddress extends ValueObject<EmailAddressProps> {
|
||||
getValue(): string {
|
||||
return this.props.value;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Maybe, Result, ValueObject } from "@common/domain";
|
||||
import { Maybe, Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface NameProps {
|
||||
value: string;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Maybe, Result, ValueObject } from "@common/domain";
|
||||
import { Maybe, Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface SlugProps {
|
||||
value: string;
|
||||
@ -35,7 +36,7 @@ export class Slug extends ValueObject<SlugProps> {
|
||||
return Result.ok(Maybe.None<Slug>());
|
||||
}
|
||||
|
||||
return Slug.create(value!).map((value) => Maybe.Some(value));
|
||||
return Slug.create(value!).map((value: Slug) => Maybe.Some(value));
|
||||
}
|
||||
|
||||
getValue(): string {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Result } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { ITransactionManager } from "@common/infrastructure/database";
|
||||
import { User } from "@contexts/auth/domain";
|
||||
import { IUserService } from "@contexts/auth/domain/services";
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { AggregateRoot, Result, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
import { AggregateRoot, EmailAddress, UniqueID } from "@common/domain";
|
||||
import { UserAuthenticatedEvent } from "../events";
|
||||
import { EmailAddress, HashPassword, PlainPassword, Username } from "../value-objects";
|
||||
import { HashPassword, PlainPassword, Username } from "../value-objects";
|
||||
|
||||
export interface IAuthenticatedUserProps {
|
||||
username: Username;
|
||||
@ -12,6 +14,7 @@ export interface IAuthenticatedUserProps {
|
||||
export interface IAuthenticatedUser {
|
||||
username: Username;
|
||||
email: EmailAddress;
|
||||
hashPassword: HashPassword;
|
||||
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
@ -67,6 +70,10 @@ export class AuthenticatedUser
|
||||
return this.props.email;
|
||||
}
|
||||
|
||||
get hashPassword(): HashPassword {
|
||||
return this.props.hashPassword;
|
||||
}
|
||||
|
||||
get isUser(): boolean {
|
||||
return this.hasRole("user");
|
||||
}
|
||||
@ -79,14 +86,6 @@ export class AuthenticatedUser
|
||||
* 🔹 Devuelve una representación lista para persistencia
|
||||
*/
|
||||
toPersistenceData(): any {
|
||||
return {
|
||||
id: this.id.toString(),
|
||||
username: this.props.username.toString(),
|
||||
email: this.props.email.toString(),
|
||||
hash_password: this.props.hashPassword.toString(),
|
||||
roles: this.props.roles.map((role) => role.toString()),
|
||||
access_token: this.accessToken,
|
||||
refresh_token: this.refreshToken,
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { AggregateRoot, Result, UniqueID } from "@common/domain";
|
||||
import { AggregateRoot, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
export interface IRoleProps {}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { AggregateRoot, EmailAddress, Result, UniqueID } from "@common/domain";
|
||||
import { AggregateRoot, EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { UserAuthenticatedEvent } from "../events";
|
||||
import { Username } from "../value-objects";
|
||||
|
||||
@ -14,11 +15,11 @@ export interface IUser {
|
||||
|
||||
isUser: boolean;
|
||||
isAdmin: boolean;
|
||||
isActive: boolean;
|
||||
|
||||
hasRole(role: string): boolean;
|
||||
hasRoles(roles: string[]): boolean;
|
||||
getRoles(): string[];
|
||||
toPersistenceData(): any;
|
||||
}
|
||||
|
||||
export class User extends AggregateRoot<IUserProps> implements IUser {
|
||||
@ -60,15 +61,7 @@ export class User extends AggregateRoot<IUserProps> implements IUser {
|
||||
return this.hasRole("admin");
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Devuelve una representación lista para persistencia
|
||||
*/
|
||||
toPersistenceData(): any {
|
||||
return {
|
||||
id: this.id.toString(),
|
||||
username: this.props.username.toString(),
|
||||
email: this.props.email.toString(),
|
||||
roles: this.props.roles.map((role) => role.toString()),
|
||||
};
|
||||
get isActive(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { DomainEntity, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress } from "../value-objects";
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
export interface IJWTPayloadProps {
|
||||
tabId: UniqueID;
|
||||
@ -23,10 +23,6 @@ export interface IJWTPayload {
|
||||
|
||||
export class JWTPayload extends DomainEntity<IJWTPayloadProps> implements IJWTPayload {
|
||||
static create(props: IJWTPayloadProps): Result<JWTPayload, Error> {
|
||||
if (props.email.isEmpty()) {
|
||||
return Result.fail(new Error("Email is required"));
|
||||
}
|
||||
|
||||
return Result.ok(new JWTPayload(props));
|
||||
}
|
||||
|
||||
@ -42,10 +38,6 @@ export class JWTPayload extends DomainEntity<IJWTPayloadProps> implements IJWTPa
|
||||
return Result.fail(result.error);
|
||||
}
|
||||
|
||||
if (emailOrError.data.isEmpty()) {
|
||||
return Result.fail(new Error("Email is required"));
|
||||
}
|
||||
|
||||
return JWTPayload.create({
|
||||
email: emailOrError.data,
|
||||
userId: userIdOrError.data,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { DomainEntity, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, PlainPassword } from "../value-objects";
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { PlainPassword } from "../value-objects";
|
||||
|
||||
export interface ILoginDataProps {
|
||||
email: EmailAddress;
|
||||
@ -36,10 +37,6 @@ export class LoginData extends DomainEntity<ILoginDataProps> implements ILoginDa
|
||||
return Result.fail(result.error);
|
||||
}
|
||||
|
||||
if (emailOrError.data.isEmpty()) {
|
||||
return Result.fail(new Error("Email is required"));
|
||||
}
|
||||
|
||||
return LoginData.create({
|
||||
email: emailOrError.data,
|
||||
plainPassword: plainPasswordOrError.data,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { DomainEntity, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress } from "../value-objects";
|
||||
import { DomainEntity, EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
export interface ILogoutDataProps {
|
||||
email: EmailAddress;
|
||||
@ -32,10 +32,6 @@ export class LogoutData extends DomainEntity<ILogoutDataProps> implements ILogou
|
||||
return Result.fail(result.error);
|
||||
}
|
||||
|
||||
if (emailOrError.data.isEmpty()) {
|
||||
return Result.fail(new Error("Email is required"));
|
||||
}
|
||||
|
||||
return LogoutData.create({
|
||||
email: emailOrError.data,
|
||||
tabId: tabIdOrError.data,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { DomainEntity, Result } from "@common/domain";
|
||||
import { EmailAddress, HashPassword, Username } from "../value-objects";
|
||||
import { DomainEntity, EmailAddress } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { HashPassword, Username } from "../value-objects";
|
||||
|
||||
export interface IRegisterDataProps {
|
||||
username: Username;
|
||||
@ -37,9 +38,6 @@ export class RegisterData extends DomainEntity<IRegisterDataProps> implements IR
|
||||
return Result.fail(result.error);
|
||||
}
|
||||
|
||||
if (emailOrError.data.isEmpty()) {
|
||||
return Result.fail(new Error("Email is required"));
|
||||
}
|
||||
return RegisterData.create({
|
||||
username: userNameOrError.data,
|
||||
email: emailOrError.data,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { DomainEntity, Result, UniqueID } from "@common/domain";
|
||||
import { DomainEntity, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
export interface ITabContextProps {
|
||||
tabId: UniqueID;
|
||||
@ -14,8 +15,6 @@ export interface ITabContextPrimitives {
|
||||
export interface ITabContext {
|
||||
tabId: UniqueID;
|
||||
userId: UniqueID;
|
||||
|
||||
toPersistenceData(): any;
|
||||
}
|
||||
|
||||
export class TabContext extends DomainEntity<ITabContextProps> implements ITabContext {
|
||||
@ -47,12 +46,4 @@ export class TabContext extends DomainEntity<ITabContextProps> implements ITabCo
|
||||
get userId(): UniqueID {
|
||||
return this.props.userId;
|
||||
}
|
||||
|
||||
toPersistenceData(): ITabContextPrimitives {
|
||||
return {
|
||||
id: this.id.toString(),
|
||||
tab_id: this.tabId.toString(),
|
||||
user_id: this.userId.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Result } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
|
||||
import { EmailAddress } from "@common/domain";
|
||||
import { AuthenticatedUser } from "../aggregates";
|
||||
import { EmailAddress, Username } from "../value-objects";
|
||||
import { Username } from "../value-objects";
|
||||
|
||||
export interface IAuthenticatedUserRepository {
|
||||
getUserByEmail(email: EmailAddress, transaction?: any): Promise<Result<AuthenticatedUser, Error>>;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { Transaction } from "sequelize";
|
||||
import { TabContext } from "../entities";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Collection, Result } from "@common/helpers";
|
||||
import { User } from "../aggregates";
|
||||
import { EmailAddress } from "../value-objects";
|
||||
|
||||
export interface IUserRepository {
|
||||
findAll(transaction?: any): Promise<Result<User[], Error>>;
|
||||
findAll(transaction?: any): Promise<Result<Collection<User>, Error>>;
|
||||
findById(id: UniqueID, transaction?: any): Promise<Result<User, Error>>;
|
||||
findByEmail(email: EmailAddress, transaction?: any): Promise<Result<User, Error>>;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Result } from "@common/domain";
|
||||
import { EmailAddress } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
EmailAddress,
|
||||
IJWTPayload,
|
||||
LoginData,
|
||||
LogoutData,
|
||||
|
||||
@ -1,15 +1,9 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
EmailAddress,
|
||||
IAuthenticatedUserRepository,
|
||||
IJWTPayload,
|
||||
JWTPayload,
|
||||
LoginData,
|
||||
RegisterData,
|
||||
TabContext,
|
||||
Token,
|
||||
} from "..";
|
||||
import { EmailAddress } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { AuthenticatedUser, IJWTPayload, LoginData, RegisterData, TabContext, Token } from "..";
|
||||
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { IAuthenticatedUserRepository, JWTPayload } from "..";
|
||||
import { JwtHelper } from "../../infraestructure/passport/jwt.helper";
|
||||
import { ITabContextRepository } from "../repositories/tab-context-repository.interface";
|
||||
import { IAuthService } from "./auth-service.interface";
|
||||
@ -101,11 +95,6 @@ export class AuthService implements IAuthService {
|
||||
let result: any;
|
||||
const { email, plainPassword, tabId } = loginData;
|
||||
|
||||
// Verificar que el tab ID está definido
|
||||
if (!tabId.isDefined()) {
|
||||
return Result.fail(new Error("Invalid tab id"));
|
||||
}
|
||||
|
||||
// 🔹 Verificar si el usuario existe en la base de datos
|
||||
result = await this.authUserRepo.getUserByEmail(email, transaction);
|
||||
if (result.isFailure) {
|
||||
@ -171,11 +160,6 @@ export class AuthService implements IAuthService {
|
||||
): Promise<Result<void, Error>> {
|
||||
const { email, tabId } = params;
|
||||
|
||||
// Verificar que el tab ID está definido
|
||||
if (!tabId.isDefined()) {
|
||||
return Result.fail(new Error("Invalid tab id"));
|
||||
}
|
||||
|
||||
// 🔹 Verificar si el usuario existe en la base de datos
|
||||
const userResult = await this.authUserRepo.getUserByEmail(email, transaction);
|
||||
if (userResult.isFailure) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { TabContext } from "../entities";
|
||||
|
||||
export interface ITabContextService {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { TabContext } from "../entities";
|
||||
import { ITabContextRepository } from "../repositories";
|
||||
import { ITabContextService } from "./tab-context-service.interface";
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { User } from "../aggregates";
|
||||
|
||||
export interface IUserService {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { IUserRepository, User } from "..";
|
||||
import { IUserService } from "./user-service.interface";
|
||||
|
||||
@ -12,7 +13,7 @@ export class UserService implements IUserService {
|
||||
}
|
||||
|
||||
// Solo devolver usuarios activos
|
||||
const activeUsers = usersOrError.data.filter((user) => user /*.isActive*/);
|
||||
const activeUsers = usersOrError.data.filter((user) => user.isActive);
|
||||
return Result.ok(activeUsers);
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,19 @@
|
||||
import { Result, ValueObject } from "@common/domain";
|
||||
import { ValueObject } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
|
||||
const RoleSchema = z.enum(["Admin", "User", "Manager", "Editor"]);
|
||||
|
||||
export class UserRoles extends ValueObject<string[]> {
|
||||
interface UserRolesProps {
|
||||
value: string[];
|
||||
}
|
||||
|
||||
export class UserRoles extends ValueObject<UserRolesProps> {
|
||||
static create(roles: string[]): Result<UserRoles, Error> {
|
||||
const result = UserRoles.validate(roles);
|
||||
|
||||
return result.success
|
||||
? Result.ok(new UserRoles(result.data))
|
||||
? Result.ok(new UserRoles({ value: result.data }))
|
||||
: Result.fail(new Error("Invalid user roles"));
|
||||
}
|
||||
|
||||
@ -17,6 +22,10 @@ export class UserRoles extends ValueObject<string[]> {
|
||||
}
|
||||
|
||||
hasRole(role: string): boolean {
|
||||
return this.props.includes(role);
|
||||
return this.props.value.includes(role);
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.props.value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, ValueObject } from "@common/domain";
|
||||
import { ValueObject } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import bcrypt from "bcrypt";
|
||||
import { z } from "zod";
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, ValueObject } from "@common/domain";
|
||||
import { ValueObject } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
|
||||
interface PlainPasswordProps {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, ValueObject } from "@common/domain";
|
||||
import { ValueObject } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
|
||||
interface TokenProps {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, ValueObject } from "@common/domain";
|
||||
import { ValueObject } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { z } from "zod";
|
||||
|
||||
interface UsernameProps {
|
||||
|
||||
@ -1,26 +1,25 @@
|
||||
import { EmailAddress, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@common/infrastructure";
|
||||
import { AuthenticatedUser, HashPassword, Username } from "@contexts/auth/domain";
|
||||
import { AuthUserModel } from "../sequelize";
|
||||
import { AuthUserCreationAttributes, AuthUserModel } from "../sequelize";
|
||||
|
||||
export interface IAuthenticatedUserMapper {
|
||||
toDomain(entity: AuthUserModel): Result<AuthenticatedUser, Error>;
|
||||
toPersistence(aggregate: AuthenticatedUser): AuthUserModel;
|
||||
}
|
||||
|
||||
class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
|
||||
/**
|
||||
* 🔹 Convierte una entidad de la base de datos en un agregado de dominio `AuthenticatedUser`
|
||||
*/
|
||||
toDomain(entity: AuthUserModel): Result<AuthenticatedUser, Error> {
|
||||
if (!entity) {
|
||||
return Result.fail(new Error("Entity not found"));
|
||||
}
|
||||
export interface IAuthenticatedUserMapper
|
||||
extends ISequelizeMapper<AuthUserModel, AuthUserCreationAttributes, AuthenticatedUser> {}
|
||||
|
||||
export class AuthenticatedUserMapper
|
||||
extends SequelizeMapper<AuthUserModel, AuthUserCreationAttributes, AuthenticatedUser>
|
||||
implements IAuthenticatedUserMapper
|
||||
{
|
||||
public mapToDomain(
|
||||
source: AuthUserModel,
|
||||
params?: MapperParamsType
|
||||
): Result<AuthenticatedUser, Error> {
|
||||
// Crear Value Objects asegurando que sean válidos
|
||||
const uniqueIdResult = UniqueID.create(entity.id);
|
||||
const usernameResult = Username.create(entity.username);
|
||||
const passwordHashResult = HashPassword.createFromHash(entity.hash_password);
|
||||
const emailResult = EmailAddress.create(entity.email);
|
||||
const uniqueIdResult = UniqueID.create(source.id);
|
||||
const usernameResult = Username.create(source.username);
|
||||
const passwordHashResult = HashPassword.createFromHash(source.hash_password);
|
||||
const emailResult = EmailAddress.create(source.email);
|
||||
|
||||
// Validar que no haya errores en la creación de los Value Objects
|
||||
const okOrError = Result.combine([
|
||||
@ -39,17 +38,25 @@ class AuthenticatedUserMapper implements IAuthenticatedUserMapper {
|
||||
username: usernameResult.data!,
|
||||
email: emailResult.data!,
|
||||
hashPassword: passwordHashResult.data!,
|
||||
roles: entity.roles || [],
|
||||
roles: source.roles || [],
|
||||
},
|
||||
uniqueIdResult.data!
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Convierte un agregado `AuthenticatedUser` en un objeto listo para persistencia
|
||||
*/
|
||||
toPersistence(authenticatedUser: AuthenticatedUser): AuthUserModel {
|
||||
return authenticatedUser.toPersistenceData();
|
||||
public mapToPersistence(
|
||||
source: AuthenticatedUser,
|
||||
params?: MapperParamsType
|
||||
): Result<AuthUserCreationAttributes, Error> {
|
||||
return Result.ok({
|
||||
id: source.id.toString(),
|
||||
username: source.username.toString(),
|
||||
email: source.email.toString(),
|
||||
hash_password: source.hashPassword.toString(),
|
||||
roles: source.getRoles().map((role) => role.toString()),
|
||||
//access_token: source.accessToken,
|
||||
//refresh_token: source.refreshToken,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,22 +1,24 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { ISequelizeMapper, MapperParamsType, SequelizeMapper } from "@common/infrastructure";
|
||||
import { TabContext } from "@contexts/auth/domain";
|
||||
import { TabContextModel } from "../sequelize";
|
||||
import { TabContextCreationAttributes, TabContextModel } from "../sequelize";
|
||||
|
||||
export interface ITabContextMapper {
|
||||
toDomain(entity: TabContextModel): Result<TabContext, Error>;
|
||||
toPersistence(aggregate: TabContext): TabContextModel;
|
||||
}
|
||||
|
||||
class TabContextMapper implements ITabContextMapper {
|
||||
toDomain(entity: TabContextModel): Result<TabContext, Error> {
|
||||
if (!entity) {
|
||||
return Result.fail(new Error("Entity not found"));
|
||||
}
|
||||
export interface ITabContextMapper
|
||||
extends ISequelizeMapper<TabContextModel, TabContextCreationAttributes, TabContext> {}
|
||||
|
||||
export class TabContextMapper
|
||||
extends SequelizeMapper<TabContextModel, TabContextCreationAttributes, TabContext>
|
||||
implements ITabContextMapper
|
||||
{
|
||||
public mapToDomain(
|
||||
source: TabContextModel,
|
||||
params?: MapperParamsType
|
||||
): Result<TabContext, Error> {
|
||||
// Crear Value Objects asegurando que sean válidos
|
||||
const uniqueIdResult = UniqueID.create(entity.id);
|
||||
const tabIdResult = UniqueID.create(entity.tab_id);
|
||||
const userIdResult = UniqueID.create(entity.user_id);
|
||||
const uniqueIdResult = UniqueID.create(source.id);
|
||||
const tabIdResult = UniqueID.create(source.tab_id);
|
||||
const userIdResult = UniqueID.create(source.user_id);
|
||||
//const companyIdResult = UniqueID.create(entity.company_id, false);
|
||||
//const brachIdResult = UniqueID.create(entity.branch_id, false);
|
||||
|
||||
@ -44,8 +46,15 @@ class TabContextMapper implements ITabContextMapper {
|
||||
);
|
||||
}
|
||||
|
||||
toPersistence(tabContext: TabContext): TabContextModel {
|
||||
return tabContext.toPersistenceData();
|
||||
public mapToPersistence(
|
||||
source: TabContext,
|
||||
params?: MapperParamsType
|
||||
): Result<TabContextCreationAttributes, Error> {
|
||||
return Result.ok({
|
||||
id: source.id.toString(),
|
||||
tab_id: source.tabId.toString(),
|
||||
user_id: source.userId.toString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,28 +1,24 @@
|
||||
import { EmailAddress, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import {
|
||||
ISequelizeMapper,
|
||||
MapperParamsType,
|
||||
SequelizeMapper,
|
||||
} from "@common/infrastructure/sequelize/sequelize-mapper";
|
||||
import { User, Username } from "@contexts/auth/domain";
|
||||
import { UserModel } from "../sequelize";
|
||||
import { UserCreationAttributes, UserModel } from "../sequelize";
|
||||
|
||||
export interface IUserMapper {
|
||||
toDomain(entity: UserModel): Result<User, Error>;
|
||||
toDomainArray(entities: UserModel[]): Result<User[], Error>;
|
||||
|
||||
toPersistence(aggregate: User): UserModel;
|
||||
toPersistenceArray(users: User[]): UserModel[];
|
||||
}
|
||||
|
||||
class UserMapper implements IUserMapper {
|
||||
/**
|
||||
* 🔹 Convierte una entidad de la base de datos en un agregado de dominio `User`
|
||||
*/
|
||||
toDomain(entity: UserModel): Result<User, Error> {
|
||||
if (!entity) {
|
||||
return Result.fail(new Error("Entity not found"));
|
||||
}
|
||||
export interface IUserMapper extends ISequelizeMapper<UserModel, UserCreationAttributes, User> {}
|
||||
|
||||
class UserMapper
|
||||
extends SequelizeMapper<UserModel, UserCreationAttributes, User>
|
||||
implements IUserMapper
|
||||
{
|
||||
public mapToDomain(source: UserModel, params?: MapperParamsType): Result<User, Error> {
|
||||
// Crear Value Objects asegurando que sean válidos
|
||||
const uniqueIdResult = UniqueID.create(entity.id);
|
||||
const usernameResult = Username.create(entity.username);
|
||||
const emailResult = EmailAddress.create(entity.email);
|
||||
const uniqueIdResult = UniqueID.create(source.id);
|
||||
const usernameResult = Username.create(source.username);
|
||||
const emailResult = EmailAddress.create(source.email);
|
||||
|
||||
// Validar que no haya errores en la creación de los Value Objects
|
||||
const okOrError = Result.combine([uniqueIdResult, usernameResult, emailResult]);
|
||||
@ -42,41 +38,16 @@ class UserMapper implements IUserMapper {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Convierte un array de entidades de la base de datos en un array de agregados de dominio `User`
|
||||
*/
|
||||
toDomainArray(entities: UserModel[]): Result<User[], Error> {
|
||||
if (!Array.isArray(entities) || entities.length === 0) {
|
||||
return Result.fail(new Error("Entities array is empty or invalid"));
|
||||
}
|
||||
|
||||
const usersResults = entities.map(this.toDomain);
|
||||
|
||||
const okOrError = Result.combine(usersResults);
|
||||
if (okOrError.isFailure) {
|
||||
return Result.fail(okOrError.error);
|
||||
}
|
||||
|
||||
const result = usersResults.map((result) => result.data!);
|
||||
return Result.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Convierte un agregado `User` en un objeto listo para persistencia
|
||||
*/
|
||||
toPersistence(user: User): UserModel {
|
||||
return user.toPersistenceData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Convierte un array de agregados `User` en un array de objetos listos para persistencia
|
||||
*/
|
||||
toPersistenceArray(users: User[]): UserModel[] {
|
||||
if (!Array.isArray(users) || users.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return users.map(this.toPersistence);
|
||||
public mapToPersistence(
|
||||
source: User,
|
||||
params?: MapperParamsType
|
||||
): Result<UserCreationAttributes, Error> {
|
||||
return Result.ok({
|
||||
id: source.id.toString(),
|
||||
username: source.username.toString(),
|
||||
email: source.email.toString(),
|
||||
//roles: source.getRoles().map((role) => role.toString()),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { NextFunction, Response } from "express";
|
||||
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { ITransactionManager } from "@common/infrastructure/database";
|
||||
import { logger } from "@common/infrastructure/logger";
|
||||
import { EmailAddress, TabContext } from "@contexts/auth/domain";
|
||||
import { TabContext } from "@contexts/auth/domain";
|
||||
import { IAuthService, ITabContextService } from "@contexts/auth/domain/services";
|
||||
import passport from "passport";
|
||||
import { ExtractJwt, Strategy as JwtStrategy } from "passport-jwt";
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
import { Result } from "@common/domain";
|
||||
import { EmailAddress } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { SequelizeRepository } from "@common/infrastructure";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
EmailAddress,
|
||||
IAuthenticatedUserRepository,
|
||||
Username,
|
||||
} from "@contexts/auth/domain";
|
||||
import { AuthenticatedUser, IAuthenticatedUserRepository, Username } from "@contexts/auth/domain";
|
||||
import { Transaction } from "sequelize";
|
||||
import { authenticatedUserMapper, IAuthenticatedUserMapper } from "../mappers";
|
||||
import { AuthUserModel } from "./auth-user.model";
|
||||
@ -75,7 +71,7 @@ class AuthenticatedUserRepository
|
||||
return Result.fail(new Error("User with email not exists"));
|
||||
}
|
||||
|
||||
return this._mapper.toDomain(rawUser);
|
||||
return this._mapper.mapToDomain(rawUser);
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
@ -86,8 +82,8 @@ class AuthenticatedUserRepository
|
||||
transaction?: Transaction
|
||||
): Promise<Result<void, Error>> {
|
||||
try {
|
||||
const persistenceData = this._mapper.toPersistence(user);
|
||||
await AuthUserModel.create(persistenceData, { transaction });
|
||||
const persistenceData = this._mapper.mapToPersistence(user);
|
||||
await AuthUserModel.create(persistenceData.data, { transaction });
|
||||
return Result.ok();
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result } from "@common/helpers";
|
||||
import { SequelizeRepository } from "@common/infrastructure";
|
||||
import { ITabContextRepository, TabContext } from "@contexts/auth/domain/";
|
||||
import { Op, Transaction } from "sequelize";
|
||||
@ -44,7 +45,7 @@ class TabContextRepository
|
||||
return Result.fail(new Error("Tab context not exists"));
|
||||
}
|
||||
|
||||
return this._mapper.toDomain(rawContext);
|
||||
return this._mapper.mapToDomain(rawContext);
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
@ -78,17 +79,17 @@ class TabContextRepository
|
||||
): Promise<Result<void, Error>> {
|
||||
try {
|
||||
const { userId, tabId } = context;
|
||||
const data = this._mapper.toPersistence(context);
|
||||
const persistenceData = this._mapper.mapToPersistence(context);
|
||||
|
||||
// Si existe el contexto de ese tabId, lo actualizo.
|
||||
|
||||
if (await this._exists(TabContextModel, "tab_id", tabId.toString())) {
|
||||
await TabContextModel.update(data, {
|
||||
await TabContextModel.update(persistenceData.data, {
|
||||
where: { [Op.and]: [{ tab_id: tabId.toString() }, { user_id: userId.toString() }] },
|
||||
transaction,
|
||||
});
|
||||
} else {
|
||||
await TabContextModel.create(data, {
|
||||
await TabContextModel.create(persistenceData.data, {
|
||||
include: [{ all: true }],
|
||||
transaction,
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { EmailAddress, Result, UniqueID } from "@common/domain";
|
||||
import { EmailAddress, UniqueID } from "@common/domain";
|
||||
import { Collection, Result } from "@common/helpers";
|
||||
import { SequelizeRepository } from "@common/infrastructure";
|
||||
import { IUserRepository, User } from "@contexts/auth/domain";
|
||||
import { Transaction } from "sequelize";
|
||||
@ -24,7 +25,7 @@ class UserRepository extends SequelizeRepository<User> implements IUserRepositor
|
||||
this._mapper = mapper;
|
||||
}
|
||||
|
||||
async findAll(transaction?: Transaction): Promise<Result<User[], Error>> {
|
||||
async findAll(transaction?: Transaction): Promise<Result<Collection<User>, Error>> {
|
||||
try {
|
||||
const rawUsers: any = await this._findAll(UserModel, {}, transaction);
|
||||
|
||||
@ -32,7 +33,7 @@ class UserRepository extends SequelizeRepository<User> implements IUserRepositor
|
||||
return Result.fail(new Error("User with email not exists"));
|
||||
}
|
||||
|
||||
return this._mapper.toDomainArray(rawUsers);
|
||||
return this._mapper.mapArrayToDomain(rawUsers);
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
@ -46,7 +47,7 @@ class UserRepository extends SequelizeRepository<User> implements IUserRepositor
|
||||
return Result.fail(new Error(`User with id ${id.toString()} not exists`));
|
||||
}
|
||||
|
||||
return this._mapper.toDomain(rawUser);
|
||||
return this._mapper.mapToDomain(rawUser);
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
@ -60,7 +61,7 @@ class UserRepository extends SequelizeRepository<User> implements IUserRepositor
|
||||
return Result.fail(new Error(`User with email ${email.toString()} not exists`));
|
||||
}
|
||||
|
||||
return this._mapper.toDomain(rawUser);
|
||||
return this._mapper.mapToDomain(rawUser);
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { ensureString } from "@common/helpers";
|
||||
import { User } from "@contexts/auth/domain";
|
||||
import { IListUsersResponseDTO } from "../../dto";
|
||||
|
||||
@ -8,8 +9,8 @@ export interface IListUsersPresenter {
|
||||
export const listUsersPresenter: IListUsersPresenter = {
|
||||
toDTO: (users: User[]): IListUsersResponseDTO[] =>
|
||||
users.map((user) => ({
|
||||
id: user.id.toString(),
|
||||
email: user.email.toString(),
|
||||
username: user.username.toString(),
|
||||
id: ensureString(user.id.toString()),
|
||||
email: ensureString(user.email.toString()),
|
||||
username: ensureString(user.username.toString()),
|
||||
})),
|
||||
};
|
||||
|
||||
@ -27,9 +27,18 @@ export const loginPresenter: ILoginPresenter = {
|
||||
tokens: { accessToken, refreshToken },
|
||||
} = data;
|
||||
|
||||
const userData = user.toPersistenceData();
|
||||
const userData = {
|
||||
id: user.id.toString(),
|
||||
username: user.username.toString(),
|
||||
email: user.email.toString(),
|
||||
//roles: user.getRoles().map((role) => role.toString()),
|
||||
};
|
||||
|
||||
const tabContextData = tabContext.toPersistenceData();
|
||||
const tabContextData = {
|
||||
id: tabContext.id.toString(),
|
||||
tab_id: tabContext.tabId.toString(),
|
||||
user_id: tabContext.userId.toString(),
|
||||
};
|
||||
|
||||
return {
|
||||
user: {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { validateRequestDTO } from "@common/presentation";
|
||||
import { checkTabContext, checkUserIsAdmin } from "@contexts/auth/infraestructure";
|
||||
import { checkTabContext } from "@contexts/auth/infraestructure";
|
||||
import { listUsersController, ListUsersSchema } from "@contexts/auth/presentation";
|
||||
import { NextFunction, Request, Response, Router } from "express";
|
||||
|
||||
@ -10,7 +10,7 @@ export const userRouter = (appRouter: Router) => {
|
||||
"/",
|
||||
validateRequestDTO(ListUsersSchema),
|
||||
checkTabContext,
|
||||
checkUserIsAdmin,
|
||||
//checkUserIsAdmin,
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
listUsersController().execute(req, res, next);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user