.
This commit is contained in:
parent
36788f34e8
commit
e8d606714a
@ -9,6 +9,11 @@
|
||||
"date": 1738768744297,
|
||||
"name": "debug-2025-02-05.log",
|
||||
"hash": "35182b14bda063a4b734238473f84cfa66a0362a76d8f12f0c20277df81c7256"
|
||||
},
|
||||
{
|
||||
"date": 1738834648631,
|
||||
"name": "debug-2025-02-06.log",
|
||||
"hash": "fbca91e028d38f5065d0e5bdbbfdbf49aadd06feddd074c6a1419b7c9e6b4fd7"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
|
||||
@ -9,6 +9,11 @@
|
||||
"date": 1738768744292,
|
||||
"name": "error-2025-02-05.log",
|
||||
"hash": "c32d976d68382b2ba2ddec8c907c30547ec9fda2bb31180bfdbeb685964810a8"
|
||||
},
|
||||
{
|
||||
"date": 1738834648629,
|
||||
"name": "error-2025-02-06.log",
|
||||
"hash": "17c45ac8b0d8d1bf22f601247a7f1384f004d06420d39e78eb65cb0a26815e13"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
|
||||
@ -14,6 +14,7 @@ const initLogger = () => {
|
||||
format.timestamp(),
|
||||
format.align(),
|
||||
format.splat(),
|
||||
format.errors({ stack: !isProduction }),
|
||||
format.printf((info) => {
|
||||
const rid = rTracer.id();
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import { AuthenticatedUser } from "../domain";
|
||||
|
||||
export interface IAuthProvider {
|
||||
/* JWT Strategy */
|
||||
generateAccessToken(payload: object): string;
|
||||
generateRefreshToken(payload: object): string;
|
||||
verifyToken(token: string): Promise<AuthenticatedUser | null>;
|
||||
|
||||
/* LocalStrategy */
|
||||
//_verifyUser(email: string, password: string): Promise<AuthenticatedUser | null>;
|
||||
}
|
||||
@ -2,6 +2,10 @@ import { Result, UniqueID } from "@common/domain";
|
||||
import { AuthenticatedUser, EmailAddress, HashPassword, PlainPassword, Username } from "../domain";
|
||||
|
||||
export interface IAuthService {
|
||||
generateAccessToken(payload: object): string;
|
||||
generateRefreshToken(payload: object): string;
|
||||
verifyToken(token: string): Promise<AuthenticatedUser | null>;
|
||||
|
||||
registerUser(params: {
|
||||
username: Username;
|
||||
email: EmailAddress;
|
||||
@ -24,4 +28,11 @@ export interface IAuthService {
|
||||
Error
|
||||
>
|
||||
>;
|
||||
|
||||
logoutUser(params: { email: EmailAddress; tabId: UniqueID }): Promise<Result<void, Error>>;
|
||||
|
||||
verifyUser(params: {
|
||||
email: EmailAddress;
|
||||
plainPassword: PlainPassword;
|
||||
}): Promise<Result<AuthenticatedUser, Error>>;
|
||||
}
|
||||
|
||||
@ -1,33 +1,47 @@
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { ITransactionManager } from "@common/infrastructure/database";
|
||||
import jwt from "jsonwebtoken";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
EmailAddress,
|
||||
HashPassword,
|
||||
IAuthenticatedUserRepository,
|
||||
PlainPassword,
|
||||
TabContext,
|
||||
Username,
|
||||
} from "../domain";
|
||||
import { ITabContextRepository } from "../domain/repositories/tab-context-repository.interface";
|
||||
import { IAuthProvider } from "./auth-provider.interface";
|
||||
import { IAuthService } from "./auth-service.interface";
|
||||
|
||||
const SECRET_KEY = process.env.JWT_SECRET || "supersecretkey";
|
||||
const ACCESS_EXPIRATION = process.env.JWT_ACCESS_EXPIRATION || "1h";
|
||||
const REFRESH_EXPIRATION = process.env.JWT_REFRESH_EXPIRATION || "7d";
|
||||
|
||||
export class AuthService implements IAuthService {
|
||||
private readonly _userRepo!: IAuthenticatedUserRepository;
|
||||
private readonly _tabContactRepo!: ITabContextRepository;
|
||||
private readonly _transactionManager!: ITransactionManager;
|
||||
private readonly _authProvider: IAuthProvider;
|
||||
|
||||
constructor(
|
||||
userRepo: IAuthenticatedUserRepository,
|
||||
tabContextRepo: ITabContextRepository,
|
||||
transactionManager: ITransactionManager,
|
||||
authProvider: IAuthProvider
|
||||
transactionManager: ITransactionManager
|
||||
) {
|
||||
this._userRepo = userRepo;
|
||||
this._tabContactRepo = tabContextRepo;
|
||||
this._transactionManager = transactionManager;
|
||||
this._authProvider = authProvider;
|
||||
}
|
||||
|
||||
generateAccessToken(payload: object): string {
|
||||
return jwt.sign(payload, SECRET_KEY, { expiresIn: ACCESS_EXPIRATION });
|
||||
}
|
||||
|
||||
generateRefreshToken(payload: object): string {
|
||||
return jwt.sign(payload, SECRET_KEY, { expiresIn: REFRESH_EXPIRATION });
|
||||
}
|
||||
|
||||
verifyToken(token: string): any {
|
||||
return jwt.verify(token, SECRET_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,25 +139,23 @@ export class AuthService implements IAuthService {
|
||||
const contextOrError = TabContext.create({
|
||||
userId: user.id,
|
||||
tabId: tabId,
|
||||
companyId: UniqueID.generateUndefinedID().data,
|
||||
branchId: UniqueID.generateUndefinedID().data,
|
||||
});
|
||||
|
||||
if (contextOrError.isFailure) {
|
||||
return Result.fail(new Error("Error creating user context"));
|
||||
}
|
||||
|
||||
await this._tabContactRepo.registerContext(contextOrError.data, transaction);
|
||||
await this._tabContactRepo.registerContextByTabId(contextOrError.data, transaction);
|
||||
|
||||
// 🔹 Generar Access Token y Refresh Token
|
||||
const accessToken = this._authProvider.generateAccessToken({
|
||||
const accessToken = this.generateAccessToken({
|
||||
userId: user.id.toString(),
|
||||
email: email.toString(),
|
||||
tabId: tabId.toString(),
|
||||
roles: ["USER"],
|
||||
});
|
||||
|
||||
const refreshToken = this._authProvider.generateRefreshToken({
|
||||
const refreshToken = this.generateRefreshToken({
|
||||
userId: user.id.toString(),
|
||||
});
|
||||
|
||||
@ -159,4 +171,72 @@ export class AuthService implements IAuthService {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Autentica a un usuario validando su email y contraseña.
|
||||
*/
|
||||
async logoutUser(params: { email: EmailAddress; tabId: UniqueID }): Promise<Result<void, Error>> {
|
||||
try {
|
||||
return await this._transactionManager.complete(async (transaction) => {
|
||||
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._userRepo.getUserByEmail(email, transaction);
|
||||
if (userResult.isFailure) {
|
||||
return Result.fail(new Error("Invalid email or password"));
|
||||
}
|
||||
|
||||
const user = userResult.data;
|
||||
|
||||
const contextOrError = TabContext.create({
|
||||
userId: user.id,
|
||||
tabId: tabId,
|
||||
});
|
||||
|
||||
if (contextOrError.isFailure) {
|
||||
return Result.fail(new Error("Error creating user context"));
|
||||
}
|
||||
|
||||
// Desregistrar el contexto de ese tab ID
|
||||
await this._tabContactRepo.unregisterContextByTabId(contextOrError.data, transaction);
|
||||
|
||||
return Result.ok();
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
async verifyUser(params: {
|
||||
email: EmailAddress;
|
||||
plainPassword: PlainPassword;
|
||||
}): Promise<Result<AuthenticatedUser, Error>> {
|
||||
try {
|
||||
return await this._transactionManager.complete(async (transaction) => {
|
||||
const { email, plainPassword } = params;
|
||||
const userResult = await this._userRepo.getUserByEmail(email, transaction);
|
||||
|
||||
if (userResult.isFailure || !userResult.data) {
|
||||
return Result.fail(new Error("Invalid email or password"));
|
||||
}
|
||||
|
||||
const user = userResult.data;
|
||||
const isValidPassword = await user.verifyPassword(plainPassword);
|
||||
|
||||
if (!isValidPassword) {
|
||||
return Result.fail(new Error("Invalid email or password"));
|
||||
}
|
||||
|
||||
return Result.ok(user);
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import { createSequelizeTransactionManager } from "@common/infrastructure";
|
||||
|
||||
import { createAuthenticatedUserRepository, createTabContextRepository } from "../infraestructure";
|
||||
import { createPassportAuthProvider } from "../infraestructure/passport/passport-auth-provider";
|
||||
import { IAuthProvider } from "./auth-provider.interface";
|
||||
import { IAuthService } from "./auth-service.interface";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { ITabContextService } from "./tab-context-service.interface";
|
||||
import { TabContextService } from "./tab-context.service";
|
||||
|
||||
export * from "./auth-provider.interface";
|
||||
export * from "./auth-service.interface";
|
||||
|
||||
export const createAuthService = (): IAuthService => {
|
||||
@ -16,16 +13,7 @@ export const createAuthService = (): IAuthService => {
|
||||
const authenticatedUserRepository = createAuthenticatedUserRepository();
|
||||
const tabContextRepository = createTabContextRepository();
|
||||
|
||||
const authProvider: IAuthProvider = createPassportAuthProvider(
|
||||
authenticatedUserRepository,
|
||||
transactionManager
|
||||
);
|
||||
return new AuthService(
|
||||
authenticatedUserRepository,
|
||||
tabContextRepository,
|
||||
transactionManager,
|
||||
authProvider
|
||||
);
|
||||
return new AuthService(authenticatedUserRepository, tabContextRepository, transactionManager);
|
||||
};
|
||||
|
||||
export const createTabContextService = (): ITabContextService => {
|
||||
|
||||
@ -3,12 +3,6 @@ import { TabContext } from "../domain";
|
||||
|
||||
export interface ITabContextService {
|
||||
getContextByTabId(tabId: UniqueID): Promise<Result<TabContext, Error>>;
|
||||
createContext(params: {
|
||||
tabId: UniqueID;
|
||||
userId: UniqueID;
|
||||
companyId: UniqueID;
|
||||
branchId: UniqueID;
|
||||
}): Promise<Result<TabContext, Error>>;
|
||||
assignCompany(tabId: UniqueID, companyId: UniqueID): Promise<Result<void, Error>>;
|
||||
removeContext(tabId: UniqueID): Promise<Result<void, Error>>;
|
||||
createContext(params: { tabId: UniqueID; userId: UniqueID }): Promise<Result<TabContext, Error>>;
|
||||
removeContext(params: { tabId: UniqueID; userId: UniqueID }): Promise<Result<void, Error>>;
|
||||
}
|
||||
|
||||
@ -42,10 +42,8 @@ export class TabContextService implements ITabContextService {
|
||||
async createContext(params: {
|
||||
tabId: UniqueID;
|
||||
userId: UniqueID;
|
||||
companyId: UniqueID;
|
||||
branchId: UniqueID;
|
||||
}): Promise<Result<TabContext, Error>> {
|
||||
const { tabId, userId, companyId, branchId } = params;
|
||||
const { tabId, userId } = params;
|
||||
|
||||
if (!userId || !tabId) {
|
||||
return Result.fail(new Error("User ID and Tab ID are required"));
|
||||
@ -57,8 +55,6 @@ export class TabContextService implements ITabContextService {
|
||||
{
|
||||
userId,
|
||||
tabId,
|
||||
companyId,
|
||||
branchId,
|
||||
},
|
||||
UniqueID.generateNewID().data
|
||||
);
|
||||
@ -67,7 +63,7 @@ export class TabContextService implements ITabContextService {
|
||||
return Result.fail(contextOrError.error);
|
||||
}
|
||||
|
||||
await this._respository.registerContext(contextOrError.data, transaction);
|
||||
await this._respository.registerContextByTabId(contextOrError.data, transaction);
|
||||
|
||||
return Result.ok(contextOrError.data);
|
||||
});
|
||||
@ -76,39 +72,31 @@ export class TabContextService implements ITabContextService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asigna una empresa activa a un contexto de pestaña
|
||||
*/
|
||||
async assignCompany(tabId: UniqueID, companyId: UniqueID): Promise<Result<void, Error>> {
|
||||
if (!companyId || !tabId) {
|
||||
return Result.fail(new Error("Tab ID and Company ID are required"));
|
||||
}
|
||||
|
||||
try {
|
||||
return await this._transactionManager.complete(async (transaction) => {
|
||||
// Verificar si la pestaña existe
|
||||
const tabContextOrError = await this._respository.contextExists(tabId, transaction);
|
||||
if (tabContextOrError.isFailure || !tabContextOrError.data) {
|
||||
return Result.fail(new Error("Invalid or expired Tab ID"));
|
||||
}
|
||||
|
||||
return await this._respository.updateCompanyByTabId(tabId, companyId, transaction);
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un contexto de pestaña por su ID
|
||||
*/
|
||||
async removeContext(tabId: UniqueID): Promise<Result<void, Error>> {
|
||||
if (!tabId) {
|
||||
return Result.fail(new Error("Tab ID is required"));
|
||||
async removeContext(params: { tabId: UniqueID; userId: UniqueID }): Promise<Result<void, Error>> {
|
||||
const { tabId, userId } = params;
|
||||
|
||||
if (!userId || !tabId) {
|
||||
return Result.fail(new Error("User ID and Tab ID are required"));
|
||||
}
|
||||
|
||||
try {
|
||||
return await this._transactionManager.complete(async (transaction) => {
|
||||
return await this._respository.deleteContextByTabId(tabId, transaction);
|
||||
const contextOrError = TabContext.create(
|
||||
{
|
||||
userId,
|
||||
tabId,
|
||||
},
|
||||
UniqueID.generateNewID().data
|
||||
);
|
||||
|
||||
if (contextOrError.isFailure) {
|
||||
return Result.fail(contextOrError.error);
|
||||
}
|
||||
|
||||
return await this._respository.unregisterContextByTabId(contextOrError.data, transaction);
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
|
||||
@ -3,18 +3,11 @@ import { DomainEntity, Result, UniqueID } from "@common/domain";
|
||||
export interface ITabContextProps {
|
||||
tabId: UniqueID;
|
||||
userId: UniqueID;
|
||||
companyId: UniqueID;
|
||||
branchId: UniqueID;
|
||||
}
|
||||
|
||||
export interface ITabContext {
|
||||
tabId: UniqueID;
|
||||
userId: UniqueID;
|
||||
companyId: UniqueID;
|
||||
branchId: UniqueID;
|
||||
|
||||
hasCompanyAssigned(): boolean;
|
||||
hasBranchAssigned(): boolean;
|
||||
|
||||
toPersistenceData(): any;
|
||||
}
|
||||
@ -32,22 +25,6 @@ export class TabContext extends DomainEntity<ITabContextProps> implements ITabCo
|
||||
return this._props.userId;
|
||||
}
|
||||
|
||||
get companyId(): UniqueID {
|
||||
return this._props.companyId;
|
||||
}
|
||||
|
||||
get branchId(): UniqueID {
|
||||
return this._props.branchId;
|
||||
}
|
||||
|
||||
hasCompanyAssigned(): boolean {
|
||||
return this._props.companyId.isDefined();
|
||||
}
|
||||
|
||||
hasBranchAssigned(): boolean {
|
||||
return this._props.branchId.isDefined();
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔹 Devuelve una representación lista para persistencia
|
||||
*/
|
||||
@ -56,8 +33,6 @@ export class TabContext extends DomainEntity<ITabContextProps> implements ITabCo
|
||||
id: this._id.toString(),
|
||||
tab_id: this.tabId.toString(),
|
||||
user_id: this.userId.toString(),
|
||||
company_id: this.companyId.toString(),
|
||||
branch_id: this.branchId.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,12 +4,16 @@ import { TabContext } from "../entities";
|
||||
|
||||
export interface ITabContextRepository {
|
||||
getContextByTabId(tabId: UniqueID, transaction?: any): Promise<Result<TabContext, Error>>;
|
||||
registerContext(context: TabContext, transaction?: Transaction): Promise<Result<void, Error>>;
|
||||
contextExists(tabId: UniqueID, transaction?: any): Promise<Result<boolean, Error>>;
|
||||
updateCompanyByTabId(
|
||||
tabId: UniqueID,
|
||||
companyId: UniqueID,
|
||||
|
||||
contextExistsByTabId(tabId: UniqueID, transaction?: any): Promise<Result<boolean, Error>>;
|
||||
|
||||
registerContextByTabId(
|
||||
context: TabContext,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<void, Error>>;
|
||||
|
||||
unregisterContextByTabId(
|
||||
context: TabContext,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<void, Error>>;
|
||||
deleteContextByTabId(tabId: UniqueID, transaction?: any): Promise<Result<void, Error>>;
|
||||
}
|
||||
|
||||
@ -1 +1,9 @@
|
||||
export * from "./passport-auth-provider";
|
||||
import { createAuthService } from "@contexts/auth/application";
|
||||
import { PassportAuthProvider } from "./passport-auth-provider";
|
||||
|
||||
export const createPassportAuthProvider = () => {
|
||||
const _authService = createAuthService();
|
||||
return new PassportAuthProvider(_authService);
|
||||
};
|
||||
|
||||
export const initializePassportAuthProvide = () => createPassportAuthProvider();
|
||||
|
||||
@ -1,38 +1,32 @@
|
||||
import { createSequelizeTransactionManager } from "@common/infrastructure";
|
||||
import { ITransactionManager } from "@common/infrastructure/database";
|
||||
import { IAuthProvider } from "@contexts/auth/application";
|
||||
import {
|
||||
AuthenticatedUser,
|
||||
EmailAddress,
|
||||
IAuthenticatedUserRepository,
|
||||
PlainPassword,
|
||||
} from "@contexts/auth/domain";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { IAuthService } from "@contexts/auth/application";
|
||||
import { AuthenticatedUser, EmailAddress, PlainPassword } from "@contexts/auth/domain";
|
||||
import passport from "passport";
|
||||
import { ExtractJwt, Strategy as JwtStrategy } from "passport-jwt";
|
||||
import { Strategy as LocalStrategy } from "passport-local";
|
||||
import { createAuthenticatedUserRepository } from "../sequelize";
|
||||
|
||||
const SECRET_KEY = process.env.JWT_SECRET || "supersecretkey";
|
||||
const ACCESS_EXPIRATION = process.env.JWT_ACCESS_EXPIRATION || "1h";
|
||||
const REFRESH_EXPIRATION = process.env.JWT_REFRESH_EXPIRATION || "7d";
|
||||
|
||||
export class PassportAuthProvider implements IAuthProvider {
|
||||
private readonly _repository: IAuthenticatedUserRepository;
|
||||
private readonly _transactionManager!: ITransactionManager;
|
||||
export class PassportAuthProvider {
|
||||
private readonly _authService: IAuthService;
|
||||
|
||||
private async _verifyUser(email: string, password: string): Promise<AuthenticatedUser | null> {
|
||||
const emailVO = EmailAddress.create(email);
|
||||
if (emailVO.isFailure) return Promise.resolve(null);
|
||||
|
||||
const passwordVO = PlainPassword.create(password);
|
||||
if (passwordVO.isFailure) return Promise.resolve(null);
|
||||
const plainPasswordVO = PlainPassword.create(password);
|
||||
if (plainPasswordVO.isFailure) return Promise.resolve(null);
|
||||
|
||||
const userResult = await this._repository.getUserByEmail(emailVO.data);
|
||||
if (userResult.isFailure || !userResult.data) return Promise.resolve(null);
|
||||
const userResult = await this._authService.verifyUser({
|
||||
email: emailVO.data,
|
||||
plainPassword: plainPasswordVO.data,
|
||||
});
|
||||
|
||||
if (userResult.isFailure || !userResult.data) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
const user = userResult.data;
|
||||
const isValidPassword = await user.verifyPassword(passwordVO.data);
|
||||
const isValidPassword = await user.verifyPassword(plainPasswordVO.data);
|
||||
|
||||
return !isValidPassword ? Promise.resolve(null) : Promise.resolve(user);
|
||||
}
|
||||
@ -50,6 +44,7 @@ export class PassportAuthProvider implements IAuthProvider {
|
||||
"jwt",
|
||||
new JwtStrategy(jwtOptions, (tokenPayload, done) => {
|
||||
try {
|
||||
console.log(tokenPayload);
|
||||
return done(null, tokenPayload);
|
||||
} catch (error) {
|
||||
return done(error, false);
|
||||
@ -77,32 +72,8 @@ export class PassportAuthProvider implements IAuthProvider {
|
||||
passport.initialize();
|
||||
}
|
||||
|
||||
constructor(repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager) {
|
||||
this._repository = repository;
|
||||
this._transactionManager = transactionManager;
|
||||
constructor(authService: IAuthService) {
|
||||
this._authService = authService;
|
||||
this.initializePassport();
|
||||
}
|
||||
|
||||
generateAccessToken(payload: object): string {
|
||||
return jwt.sign(payload, SECRET_KEY, { expiresIn: String(ACCESS_EXPIRATION) });
|
||||
}
|
||||
|
||||
generateRefreshToken(payload: object): string {
|
||||
return jwt.sign(payload, SECRET_KEY, { expiresIn: REFRESH_EXPIRATION });
|
||||
}
|
||||
|
||||
verifyToken(token: string): any {
|
||||
return jwt.verify(token, SECRET_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
export const createPassportAuthProvider = (
|
||||
repository?: IAuthenticatedUserRepository,
|
||||
transactionManager?: ITransactionManager
|
||||
) => {
|
||||
const _transactionManager = transactionManager || createSequelizeTransactionManager();
|
||||
const _repository = repository || createAuthenticatedUserRepository();
|
||||
return new PassportAuthProvider(_repository, _transactionManager);
|
||||
};
|
||||
|
||||
export const initializePassportAuthProvide = () => createPassportAuthProvider();
|
||||
|
||||
@ -2,7 +2,7 @@ import { Result, UniqueID } from "@common/domain";
|
||||
import { SequelizeRepository } from "@common/infrastructure";
|
||||
import { TabContext } from "@contexts/auth/domain/";
|
||||
import { ITabContextRepository } from "@contexts/auth/domain/repositories/tab-context-repository.interface";
|
||||
import { Transaction } from "sequelize";
|
||||
import { Op, Transaction } from "sequelize";
|
||||
import { createTabContextMapper, ITabContextMapper } from "../mappers";
|
||||
import { TabContextModel } from "./tab-context.model";
|
||||
|
||||
@ -51,7 +51,7 @@ export class TabContextRepository
|
||||
}
|
||||
}
|
||||
|
||||
async contextExists(tabId: UniqueID, transaction?: any): Promise<Result<boolean, Error>> {
|
||||
async contextExistsByTabId(tabId: UniqueID, transaction?: any): Promise<Result<boolean, Error>> {
|
||||
try {
|
||||
const result: any = await this._exists(
|
||||
TabContextModel,
|
||||
@ -67,57 +67,57 @@ export class TabContextRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un contexto para un tab id o actualiza si ya existe
|
||||
* Registra un contexto para un tab id o actualiza si ya existe
|
||||
* @param context
|
||||
* @param transaction
|
||||
* @returns
|
||||
*/
|
||||
|
||||
async registerContext(
|
||||
async registerContextByTabId(
|
||||
context: TabContext,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<void, Error>> {
|
||||
try {
|
||||
const { id } = context;
|
||||
const persistenceData = this._mapper.toPersistence(context);
|
||||
const { userId, tabId } = context;
|
||||
const data = this._mapper.toPersistence(context);
|
||||
|
||||
// Si existe el contexto de ese tabId, lo actualizo.
|
||||
|
||||
if (await this._exists(TabContextModel, "tab_id", tabId.toString())) {
|
||||
await TabContextModel.update(data, {
|
||||
where: { [Op.and]: [{ tab_id: tabId.toString() }, { user_id: userId.toString() }] },
|
||||
transaction,
|
||||
});
|
||||
} else {
|
||||
await TabContextModel.create(data, {
|
||||
include: [{ all: true }],
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
|
||||
await this._save(TabContextModel, id, persistenceData, {}, transaction);
|
||||
return Result.ok();
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
}
|
||||
|
||||
async updateCompanyByTabId(
|
||||
tabId: UniqueID,
|
||||
companyId: UniqueID,
|
||||
/**
|
||||
* Desregistra un contexto para un tab id o actualiza si ya existe
|
||||
* @param context
|
||||
* @param transaction
|
||||
* @returns
|
||||
*/
|
||||
|
||||
async unregisterContextByTabId(
|
||||
context: TabContext,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<void, Error>> {
|
||||
try {
|
||||
await TabContextModel.update(
|
||||
{ company_id: companyId.toString() },
|
||||
{
|
||||
where: {
|
||||
tab_id: tabId.toString(),
|
||||
},
|
||||
transaction,
|
||||
}
|
||||
);
|
||||
const { userId, tabId } = context;
|
||||
|
||||
return Result.ok();
|
||||
} catch (error: any) {
|
||||
return this._handleDatabaseError(error, this._customErrorMapper);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteContextByTabId(tabId: UniqueID, transaction?: any): Promise<Result<void, Error>> {
|
||||
try {
|
||||
await TabContextModel.destroy({
|
||||
where: {
|
||||
tab_id: tabId.toString(),
|
||||
},
|
||||
where: { [Op.and]: [{ tab_id: tabId.toString() }, { user_id: userId.toString() }] },
|
||||
transaction,
|
||||
force: false,
|
||||
});
|
||||
return Result.ok();
|
||||
} catch (error: any) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { UniqueID } from "@common/domain";
|
||||
import { Result, UniqueID } from "@common/domain";
|
||||
import { ExpressController } from "@common/presentation";
|
||||
import { createAuthService, IAuthService } from "@contexts/auth/application";
|
||||
import { EmailAddress } from "@contexts/auth/domain";
|
||||
|
||||
class LogoutController extends ExpressController {
|
||||
private readonly _authService!: IAuthService;
|
||||
@ -12,22 +13,21 @@ class LogoutController extends ExpressController {
|
||||
|
||||
async executeImpl() {
|
||||
const tabId = this.req.headers["x-tab-id"];
|
||||
|
||||
const emailVO = EmailAddress.create(this.req.body.email);
|
||||
const tabIdVO = UniqueID.create(String(tabId));
|
||||
|
||||
if (tabIdVO.isFailure) {
|
||||
return this.clientError("Invalid tab id", [tabIdVO.error]);
|
||||
const resultValidation = Result.combine([emailVO, tabIdVO]);
|
||||
|
||||
if (resultValidation.isFailure) {
|
||||
return this.clientError("Invalid input data", resultValidation.error);
|
||||
}
|
||||
|
||||
const userOrError = await this._authService.logoutUser({
|
||||
await this._authService.logoutUser({
|
||||
email: emailVO.data,
|
||||
plainPassword: plainPasswordVO.data,
|
||||
tabId: tabIdVO.data,
|
||||
});
|
||||
|
||||
if (userOrError.isFailure) {
|
||||
return this.unauthorizedError(userOrError.error.message);
|
||||
}
|
||||
|
||||
return this.ok();
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
import { validateRequest } from "@common/presentation";
|
||||
import { validateTabContextHeader, validateUser } from "@contexts/auth/presentation";
|
||||
import { createLoginController } from "@contexts/auth/presentation/controllers";
|
||||
import { createLogoutController } from "@contexts/auth/presentation/controllers/logout/logout.controller";
|
||||
import { createRegisterController } from "@contexts/auth/presentation/controllers/register/register.controller";
|
||||
import { LoginUserSchema, RegisterUserSchema } from "@contexts/auth/presentation/dto";
|
||||
import { Router } from "express";
|
||||
import { NextFunction, Request, Response, Router } from "express";
|
||||
|
||||
export const authRouter = (appRouter: Router) => {
|
||||
const authRoutes: Router = Router({ mergeParams: true });
|
||||
@ -45,7 +46,7 @@ export const authRouter = (appRouter: Router) => {
|
||||
"/login",
|
||||
validateRequest(LoginUserSchema),
|
||||
validateTabContextHeader,
|
||||
(req, res, next) => {
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
createLoginController().execute(req, res, next);
|
||||
}
|
||||
);
|
||||
@ -61,10 +62,14 @@ export const authRouter = (appRouter: Router) => {
|
||||
*
|
||||
* @apiSuccess (200) {String} message Success message.
|
||||
*/
|
||||
authRoutes.post("/logout", validateUser, validateTabContextHeader, (req, res, next) => {
|
||||
res.sendStatus(200);
|
||||
//createLogoutController().execute(req, res, next);
|
||||
});
|
||||
authRoutes.post(
|
||||
"/logout",
|
||||
validateUser,
|
||||
validateTabContextHeader,
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
createLogoutController().execute(req, res, next);
|
||||
}
|
||||
);
|
||||
|
||||
appRouter.use("/auth", authRoutes);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user