Uecko_ERP/apps/server/src/contexts/auth/application/auth.service.ts

119 lines
3.6 KiB
TypeScript
Raw Normal View History

2025-02-01 21:48:13 +00:00
import { Result, UniqueID } from "@common/domain";
import { ITransactionManager } from "@common/infrastructure/database";
import {
EmailAddress,
IAuthenticatedUserRepository,
PasswordHash,
Username,
} from "@contexts/auth/domain";
import { IAuthService } from "./auth-service.interface";
export class AuthService implements IAuthService {
private _respository!: IAuthenticatedUserRepository;
private readonly _transactionManager!: ITransactionManager;
constructor(repository: IAuthenticatedUserRepository, transactionManager: ITransactionManager) {
this._respository = repository;
this._transactionManager = transactionManager;
}
2025-01-30 10:45:31 +00:00
/**
* 🔹 `registerUser`
* Registra un nuevo usuario en la base de datos bajo transacción.
*/
2025-02-01 21:48:13 +00:00
async registerUser(params: {
username: Username;
email: EmailAddress;
password: PasswordHash;
}): Promise<Result<{ userId: string }, Error>> {
return await this._transactionManager.execute(async (transaction) => {
const { username, email, password } = params;
2025-01-30 10:45:31 +00:00
const userIdResult = UniqueID.generateNewID();
// Verificar si el usuario ya existe
2025-02-01 21:48:13 +00:00
const userExists = await this._respository.userExists(email.toString(), transaction);
2025-01-30 10:45:31 +00:00
if (userExists) {
return Result.fail(new Error("Email is already registered"));
}
2025-02-01 21:48:13 +00:00
const user = await this._respository.createUser(
2025-01-30 10:45:31 +00:00
{
2025-02-01 21:48:13 +00:00
id: userIdResult,
username: username,
email: email,
password: password,
2025-01-30 10:45:31 +00:00
isActive: true,
},
transaction
);
return Result.ok({ userId: user.id });
});
}
/**
* 🔹 `login`
* Autentica un usuario y genera un token JWT bajo transacción.
*/
static async login(
email: string,
password: string
): Promise<Result<{ token: string; userId: string }, Error>> {
return await authUserRepository.executeTransaction(async (transaction) => {
const emailResult = EmailAddress.create(email);
if (emailResult.isError()) {
return Result.fail(emailResult.error);
}
const user = await authUserRepository.findByEmail(emailResult.data.getValue(), transaction);
if (user.isError()) {
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<Result<{ message: string }, Error>> {
return await authUserRepository.executeTransaction(async (transaction) => {
const user = await authUserRepository.findById(userId, transaction);
if (user.isError()) {
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" });
}
}