import { Result, UniqueID } from "@common/domain"; import { ITransactionManager } from "@common/infrastructure/database"; import { AuthenticatedUser, EmailAddress, IAuthenticatedUserRepository, PasswordHash, Username, } from "@contexts/auth/domain"; import { IAuthProvider } from "./auth-provider.interface"; import { IAuthService } from "./auth-service.interface"; export class AuthService implements IAuthService { private readonly _respository!: IAuthenticatedUserRepository; private readonly _transactionManager!: ITransactionManager; private readonly _authProvider: IAuthProvider; constructor( repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager, authProvider: IAuthProvider ) { this._respository = repository; this._transactionManager = transactionManager; this._authProvider = authProvider; } /** * 馃敼 `registerUser` * Registra un nuevo usuario en la base de datos bajo transacci贸n. */ async registerUser(params: { username: Username; email: EmailAddress; passwordHash: PasswordHash; }): Promise> { try { return await this._transactionManager.complete(async (transaction) => { const { username, email, passwordHash } = params; // Verificar si el usuario ya existe const userExists = await this._respository.findUserByEmail(email, transaction); if (userExists.isSuccess && userExists.data) { return Result.fail(new Error("Email is already registered")); } if (userExists.isFailure) { return Result.fail(userExists.error); } const newUserId = UniqueID.generateNewID().data; // 馃敼 Generar Access Token y Refresh Token const accessToken = this._authProvider.generateAccessToken({ userId: newUserId.toString(), email: email.toString(), roles: ["USER"], }); const refreshToken = this._authProvider.generateRefreshToken({ userId: newUserId.toString(), }); const userOrError = AuthenticatedUser.create( { username, email, passwordHash, roles: ["USER"], token: accessToken, }, newUserId ); if (userOrError.isFailure) { return Result.fail(userOrError.error); } const createdResult = await this._respository.createUser(userOrError.data, transaction); if (createdResult.isFailure) { return Result.fail(createdResult.error); } return Result.ok(userOrError.data); }); } catch (error: unknown) { return Result.fail(error as Error); } } /** * 馃敼 `login` * Autentica un usuario y genera un token JWT bajo transacci贸n. */ /*static async login( email: string, password: string ): Promise> { return await authUserRepository.executeTransaction(async (transaction) => { const emailResult = EmailAddress.create(email); if (emailResult.isFailure) { return Result.fail(emailResult.error); } const user = await authUserRepository.findByEmail(emailResult.data.getValue(), transaction); if (user.isFailure) { return Result.fail(new Error("Invalid email or password")); } const isValidPassword = await user.data.validatePassword(password); if (!isValidPassword) { return Result.fail(new Error("Invalid email or password")); } const token = JwtHelper.generateToken({ userId: user.data.getUserID() }); return Result.ok({ token, userId: user.data.getUserID() }); }); }*/ /** * 馃敼 `selectCompany` * Permite a un usuario seleccionar una empresa activa en la sesi贸n bajo transacci贸n. */ /*static async selectCompany( userId: string, companyId: string ): Promise> { return await authUserRepository.executeTransaction(async (transaction) => { const user = await authUserRepository.findById(userId, transaction); if (user.isFailure) { return Result.fail(new Error("User not found")); } const isAssociated = await authUserRepository.isUserAssociatedWithCompany( userId, companyId, transaction ); if (!isAssociated) { return Result.fail(new Error("User does not have access to this company")); } return Result.ok({ message: "Company selected successfully" }); }); }*/ /** * 馃敼 `logout` * Simula el cierre de sesi贸n de un usuario. No requiere transacci贸n. */ /*static logout(): Result<{ message: string }, never> { return Result.ok({ message: "Logged out successfully" }); }*/ }