diff --git a/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json b/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json index ea70f674..04ab8534 100644 --- a/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json +++ b/apps/server/.571b27c4f3dcc376d1f0ca8880ce87cfefd2f30d-audit.json @@ -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" diff --git a/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json b/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json index b7866307..5cee37c0 100644 --- a/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json +++ b/apps/server/.e6616b1c93d5e50d48b909cd34375b545b447bc6-audit.json @@ -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" diff --git a/apps/server/src/common/infrastructure/logger/index.ts b/apps/server/src/common/infrastructure/logger/index.ts index bc3f8af5..4a7373da 100644 --- a/apps/server/src/common/infrastructure/logger/index.ts +++ b/apps/server/src/common/infrastructure/logger/index.ts @@ -14,6 +14,7 @@ const initLogger = () => { format.timestamp(), format.align(), format.splat(), + format.errors({ stack: !isProduction }), format.printf((info) => { const rid = rTracer.id(); diff --git a/apps/server/src/contexts/auth/application/auth-provider.interface.ts b/apps/server/src/contexts/auth/application/auth-provider.interface.ts deleted file mode 100644 index 3d903492..00000000 --- a/apps/server/src/contexts/auth/application/auth-provider.interface.ts +++ /dev/null @@ -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; - - /* LocalStrategy */ - //_verifyUser(email: string, password: string): Promise; -} diff --git a/apps/server/src/contexts/auth/application/auth-service.interface.ts b/apps/server/src/contexts/auth/application/auth-service.interface.ts index d1ffb1e7..ab8de8fe 100644 --- a/apps/server/src/contexts/auth/application/auth-service.interface.ts +++ b/apps/server/src/contexts/auth/application/auth-service.interface.ts @@ -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; + registerUser(params: { username: Username; email: EmailAddress; @@ -24,4 +28,11 @@ export interface IAuthService { Error > >; + + logoutUser(params: { email: EmailAddress; tabId: UniqueID }): Promise>; + + verifyUser(params: { + email: EmailAddress; + plainPassword: PlainPassword; + }): Promise>; } diff --git a/apps/server/src/contexts/auth/application/auth.service.ts b/apps/server/src/contexts/auth/application/auth.service.ts index 7b490cdd..3f1bb567 100644 --- a/apps/server/src/contexts/auth/application/auth.service.ts +++ b/apps/server/src/contexts/auth/application/auth.service.ts @@ -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> { + 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> { + 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); + } + } } diff --git a/apps/server/src/contexts/auth/application/index.ts b/apps/server/src/contexts/auth/application/index.ts index e045d336..80d2507c 100644 --- a/apps/server/src/contexts/auth/application/index.ts +++ b/apps/server/src/contexts/auth/application/index.ts @@ -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 => { diff --git a/apps/server/src/contexts/auth/application/tab-context-service.interface.ts b/apps/server/src/contexts/auth/application/tab-context-service.interface.ts index 5bc19d3e..ffc2eb3b 100644 --- a/apps/server/src/contexts/auth/application/tab-context-service.interface.ts +++ b/apps/server/src/contexts/auth/application/tab-context-service.interface.ts @@ -3,12 +3,6 @@ import { TabContext } from "../domain"; export interface ITabContextService { getContextByTabId(tabId: UniqueID): Promise>; - createContext(params: { - tabId: UniqueID; - userId: UniqueID; - companyId: UniqueID; - branchId: UniqueID; - }): Promise>; - assignCompany(tabId: UniqueID, companyId: UniqueID): Promise>; - removeContext(tabId: UniqueID): Promise>; + createContext(params: { tabId: UniqueID; userId: UniqueID }): Promise>; + removeContext(params: { tabId: UniqueID; userId: UniqueID }): Promise>; } diff --git a/apps/server/src/contexts/auth/application/tab-context.service.ts b/apps/server/src/contexts/auth/application/tab-context.service.ts index f04b296b..b2d73cd6 100644 --- a/apps/server/src/contexts/auth/application/tab-context.service.ts +++ b/apps/server/src/contexts/auth/application/tab-context.service.ts @@ -42,10 +42,8 @@ export class TabContextService implements ITabContextService { async createContext(params: { tabId: UniqueID; userId: UniqueID; - companyId: UniqueID; - branchId: UniqueID; }): Promise> { - 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> { - 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> { - if (!tabId) { - return Result.fail(new Error("Tab ID is required")); + async removeContext(params: { tabId: UniqueID; userId: UniqueID }): Promise> { + 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); diff --git a/apps/server/src/contexts/auth/domain/entities/tab-context.ts b/apps/server/src/contexts/auth/domain/entities/tab-context.ts index 796168ef..3fb5074d 100644 --- a/apps/server/src/contexts/auth/domain/entities/tab-context.ts +++ b/apps/server/src/contexts/auth/domain/entities/tab-context.ts @@ -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 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 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(), }; } } diff --git a/apps/server/src/contexts/auth/domain/repositories/tab-context-repository.interface.ts b/apps/server/src/contexts/auth/domain/repositories/tab-context-repository.interface.ts index 13ddaeef..42317187 100644 --- a/apps/server/src/contexts/auth/domain/repositories/tab-context-repository.interface.ts +++ b/apps/server/src/contexts/auth/domain/repositories/tab-context-repository.interface.ts @@ -4,12 +4,16 @@ import { TabContext } from "../entities"; export interface ITabContextRepository { getContextByTabId(tabId: UniqueID, transaction?: any): Promise>; - registerContext(context: TabContext, transaction?: Transaction): Promise>; - contextExists(tabId: UniqueID, transaction?: any): Promise>; - updateCompanyByTabId( - tabId: UniqueID, - companyId: UniqueID, + + contextExistsByTabId(tabId: UniqueID, transaction?: any): Promise>; + + registerContextByTabId( + context: TabContext, + transaction?: Transaction + ): Promise>; + + unregisterContextByTabId( + context: TabContext, transaction?: Transaction ): Promise>; - deleteContextByTabId(tabId: UniqueID, transaction?: any): Promise>; } diff --git a/apps/server/src/contexts/auth/infraestructure/passport/index.ts b/apps/server/src/contexts/auth/infraestructure/passport/index.ts index c4e280b7..ba186208 100644 --- a/apps/server/src/contexts/auth/infraestructure/passport/index.ts +++ b/apps/server/src/contexts/auth/infraestructure/passport/index.ts @@ -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(); diff --git a/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts b/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts index 7a66dc7d..617251fc 100644 --- a/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts +++ b/apps/server/src/contexts/auth/infraestructure/passport/passport-auth-provider.ts @@ -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 { 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(); diff --git a/apps/server/src/contexts/auth/infraestructure/sequelize/tab-context.repository.ts b/apps/server/src/contexts/auth/infraestructure/sequelize/tab-context.repository.ts index baaf32bd..ec537011 100644 --- a/apps/server/src/contexts/auth/infraestructure/sequelize/tab-context.repository.ts +++ b/apps/server/src/contexts/auth/infraestructure/sequelize/tab-context.repository.ts @@ -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> { + async contextExistsByTabId(tabId: UniqueID, transaction?: any): Promise> { 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> { 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> { 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> { - 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) { diff --git a/apps/server/src/contexts/auth/presentation/controllers/logout/login.controller.ts b/apps/server/src/contexts/auth/presentation/controllers/logout/logout.controller.ts similarity index 64% rename from apps/server/src/contexts/auth/presentation/controllers/logout/login.controller.ts rename to apps/server/src/contexts/auth/presentation/controllers/logout/logout.controller.ts index 0d219734..d1d4afcf 100644 --- a/apps/server/src/contexts/auth/presentation/controllers/logout/login.controller.ts +++ b/apps/server/src/contexts/auth/presentation/controllers/logout/logout.controller.ts @@ -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(); } } diff --git a/apps/server/src/routes/auth.routes.ts b/apps/server/src/routes/auth.routes.ts index 1b376d39..9e2bd507 100644 --- a/apps/server/src/routes/auth.routes.ts +++ b/apps/server/src/routes/auth.routes.ts @@ -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); };