Files
gridpilot.gg/apps/api/src/domain/auth/AuthService.ts
2025-12-21 19:53:22 +01:00

146 lines
5.0 KiB
TypeScript

import { Inject, Injectable } 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 { AuthenticatedUserDTO, AuthSessionDTO, LoginParams, SignupParams } from './dtos/AuthDto';
import { AuthSessionPresenter } from './presenters/AuthSessionPresenter';
import type { CommandResultDTO } from './presenters/CommandResultPresenter';
import { CommandResultPresenter } from './presenters/CommandResultPresenter';
@Injectable()
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,
private readonly authSessionPresenter: AuthSessionPresenter,
private readonly commandResultPresenter: CommandResultPresenter,
) {}
private mapUserToAuthenticatedUserDTO(user: User): AuthenticatedUserDTO {
return {
userId: user.getId().value,
email: user.getEmail() ?? '',
displayName: user.getDisplayName() ?? '',
};
}
private buildAuthSessionDTO(token: string, user: AuthenticatedUserDTO): AuthSessionDTO {
return {
token,
user: {
userId: user.userId,
email: user.email,
displayName: user.displayName,
},
};
}
async getCurrentSession(): Promise<AuthSessionDTO | null> {
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;
}
const authenticatedUserDTO = this.mapUserToAuthenticatedUserDTO(User.fromStored(user));
const apiSession = this.buildAuthSessionDTO(coreSession.token, authenticatedUserDTO);
return apiSession;
}
async signupWithEmail(params: SignupParams): Promise<AuthSessionDTO> {
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 userDTO = this.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<AuthSessionDTO> {
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 userDTO = this.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<CommandResultDTO> {
this.logger.debug('[AuthService] Attempting logout.');
const result = await this.logoutUseCase.execute();
if (result.isErr()) {
const error = result.unwrapErr();
throw new Error(error.details?.message ?? 'Logout failed');
}
return this.commandResultPresenter.getResponseModel();
}
}