import { Inject } from '@nestjs/common'; // Core Use Cases import { LoginUseCase, type LoginInput } from '@core/identity/application/use-cases/LoginUseCase'; import { LogoutUseCase } from '@core/identity/application/use-cases/LogoutUseCase'; import { SignupUseCase, type SignupInput } from '@core/identity/application/use-cases/SignupUseCase'; // Core Interfaces and Tokens import { IdentitySessionPort } from '@core/identity/application/ports/IdentitySessionPort'; import { User } from '@core/identity/domain/entities/User'; import type { IUserRepository } from '@core/identity/domain/repositories/IUserRepository'; import type { Logger } from '@core/shared/application'; import { IDENTITY_SESSION_PORT_TOKEN, LOGGER_TOKEN, LOGIN_USE_CASE_TOKEN, LOGOUT_USE_CASE_TOKEN, SIGNUP_USE_CASE_TOKEN, USER_REPOSITORY_TOKEN } from './AuthProviders'; import { AuthSessionDTO, LoginParams, SignupParams } from './dtos/AuthDto'; import { AuthSessionPresenter } from './presenters/AuthSessionPresenter'; import { CommandResultPresenter, type CommandResultDTO } from './presenters/CommandResultPresenter'; export class AuthService { constructor( @Inject(LOGGER_TOKEN) private logger: Logger, @Inject(IDENTITY_SESSION_PORT_TOKEN) private identitySessionPort: IdentitySessionPort, @Inject(USER_REPOSITORY_TOKEN) private userRepository: IUserRepository, @Inject(LOGIN_USE_CASE_TOKEN) private readonly loginUseCase: LoginUseCase, @Inject(SIGNUP_USE_CASE_TOKEN) private readonly signupUseCase: SignupUseCase, @Inject(LOGOUT_USE_CASE_TOKEN) private readonly logoutUseCase: LogoutUseCase, ) {} async getCurrentSession(): Promise { // TODO this must call a use case this.logger.debug('[AuthService] Attempting to get current session.'); const coreSession = await this.identitySessionPort.getCurrentSession(); if (!coreSession) { return null; } const user = await this.userRepository.findById(coreSession.user.id); if (!user) { this.logger.warn( `[AuthService] Session found for user ID ${coreSession.user.id}, but user not found in repository.`, ); await this.identitySessionPort.clearSession(); return null; } // TODO no mapping in here, must use presenter const authenticatedUserDTO = this.mapUserToAuthenticatedUserDTO(User.fromStored(user)); const apiSession = this.buildAuthSessionDTO(coreSession.token, authenticatedUserDTO); return apiSession; } async signupWithEmail(params: SignupParams): Promise { this.logger.debug(`[AuthService] Attempting signup for email: ${params.email}`); const input: SignupInput = { email: params.email, password: params.password, displayName: params.displayName, }; const result = await this.signupUseCase.execute(input); if (result.isErr()) { const error = result.unwrapErr(); throw new Error(error.details?.message ?? 'Signup failed'); } const authSessionPresenter = new AuthSessionPresenter(); const userDTO = authSessionPresenter.getResponseModel(); const coreUserDTO = { id: userDTO.userId, displayName: userDTO.displayName, email: userDTO.email, }; const session = await this.identitySessionPort.createSession(coreUserDTO); return { token: session.token, user: userDTO, }; } async loginWithEmail(params: LoginParams): Promise { this.logger.debug(`[AuthService] Attempting login for email: ${params.email}`); const input: LoginInput = { email: params.email, password: params.password, }; const result = await this.loginUseCase.execute(input); if (result.isErr()) { const error = result.unwrapErr(); throw new Error(error.details?.message ?? 'Login failed'); } const authSessionPresenter = new AuthSessionPresenter(); const userDTO = authSessionPresenter.getResponseModel(); const coreUserDTO = { id: userDTO.userId, displayName: userDTO.displayName, email: userDTO.email, }; const session = await this.identitySessionPort.createSession(coreUserDTO); return { token: session.token, user: userDTO, }; } async logout(): Promise { this.logger.debug('[AuthService] Attempting logout.'); const commandResultPresenter = new CommandResultPresenter(); const result = await this.logoutUseCase.execute(); // TODO if (result.isErr()) { const error = result.unwrapErr(); throw new Error(error.details?.message ?? 'Logout failed'); } return commandResultPresenter.getResponseModel(); } }