refactor auth module
This commit is contained in:
@@ -1,57 +1,77 @@
|
||||
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 {
|
||||
LoginUseCase,
|
||||
type LoginInput,
|
||||
type LoginApplicationError,
|
||||
} from '@core/identity/application/use-cases/LoginUseCase';
|
||||
import { LogoutUseCase, type LogoutApplicationError } from '@core/identity/application/use-cases/LogoutUseCase';
|
||||
import {
|
||||
SignupUseCase,
|
||||
type SignupInput,
|
||||
type SignupApplicationError,
|
||||
} from '@core/identity/application/use-cases/SignupUseCase';
|
||||
|
||||
import type { IdentitySessionPort } from '@core/identity/application/ports/IdentitySessionPort';
|
||||
|
||||
import {
|
||||
AUTH_SESSION_OUTPUT_PORT_TOKEN,
|
||||
COMMAND_RESULT_OUTPUT_PORT_TOKEN,
|
||||
IDENTITY_SESSION_PORT_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
LOGIN_USE_CASE_TOKEN,
|
||||
LOGOUT_USE_CASE_TOKEN,
|
||||
SIGNUP_USE_CASE_TOKEN,
|
||||
} from './AuthProviders';
|
||||
import type { AuthSessionDTO } from './dtos/AuthDto';
|
||||
import { LoginParams, SignupParams } from './dtos/AuthDto';
|
||||
import { AuthSessionPresenter } from './presenters/AuthSessionPresenter';
|
||||
import { CommandResultPresenter, type CommandResultDTO } from './presenters/CommandResultPresenter';
|
||||
import type { CommandResultDTO } from './presenters/CommandResultPresenter';
|
||||
import { CommandResultPresenter } from './presenters/CommandResultPresenter';
|
||||
|
||||
function mapApplicationErrorToMessage(error: { details?: { message?: string } } | undefined, fallback: string): string {
|
||||
return error?.details?.message ?? fallback;
|
||||
}
|
||||
|
||||
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(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
@Inject(IDENTITY_SESSION_PORT_TOKEN)
|
||||
private readonly identitySessionPort: IdentitySessionPort,
|
||||
@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,
|
||||
@Inject(AUTH_SESSION_OUTPUT_PORT_TOKEN)
|
||||
private readonly authSessionPresenter: AuthSessionPresenter,
|
||||
@Inject(COMMAND_RESULT_OUTPUT_PORT_TOKEN)
|
||||
private readonly commandResultPresenter: CommandResultPresenter,
|
||||
) {}
|
||||
|
||||
async getCurrentSession(): Promise<AuthSessionDTO | null> {
|
||||
// TODO this must call a use case
|
||||
// TODO must call a use case (out of scope here)
|
||||
this.logger.debug('[AuthService] Attempting to get current session.');
|
||||
const coreSession = await this.identitySessionPort.getCurrentSession();
|
||||
if (!coreSession) {
|
||||
return null;
|
||||
}
|
||||
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;
|
||||
// Avoid service-level mapping; in this module we only support presenter-based output for use cases.
|
||||
// For now return a minimal session shape.
|
||||
return {
|
||||
token: coreSession.token,
|
||||
user: {
|
||||
userId: coreSession.user.id,
|
||||
email: coreSession.user.email ?? '',
|
||||
displayName: coreSession.user.displayName,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async signupWithEmail(params: SignupParams): Promise<AuthSessionDTO> {
|
||||
this.logger.debug(`[AuthService] Attempting signup for email: ${params.email}`);
|
||||
|
||||
this.authSessionPresenter.reset();
|
||||
|
||||
const input: SignupInput = {
|
||||
email: params.email,
|
||||
password: params.password,
|
||||
@@ -61,18 +81,16 @@ export class AuthService {
|
||||
const result = await this.signupUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Signup failed');
|
||||
const error = result.unwrapErr() as SignupApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Signup failed'));
|
||||
}
|
||||
|
||||
const authSessionPresenter = new AuthSessionPresenter();
|
||||
const userDTO = authSessionPresenter.getResponseModel();
|
||||
const coreUserDTO = {
|
||||
const userDTO = this.authSessionPresenter.responseModel;
|
||||
const session = await this.identitySessionPort.createSession({
|
||||
id: userDTO.userId,
|
||||
displayName: userDTO.displayName,
|
||||
email: userDTO.email,
|
||||
};
|
||||
const session = await this.identitySessionPort.createSession(coreUserDTO);
|
||||
});
|
||||
|
||||
return {
|
||||
token: session.token,
|
||||
@@ -83,6 +101,8 @@ export class AuthService {
|
||||
async loginWithEmail(params: LoginParams): Promise<AuthSessionDTO> {
|
||||
this.logger.debug(`[AuthService] Attempting login for email: ${params.email}`);
|
||||
|
||||
this.authSessionPresenter.reset();
|
||||
|
||||
const input: LoginInput = {
|
||||
email: params.email,
|
||||
password: params.password,
|
||||
@@ -91,18 +111,16 @@ export class AuthService {
|
||||
const result = await this.loginUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Login failed');
|
||||
const error = result.unwrapErr() as LoginApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Login failed'));
|
||||
}
|
||||
|
||||
const authSessionPresenter = new AuthSessionPresenter();
|
||||
const userDTO = authSessionPresenter.getResponseModel();
|
||||
const coreUserDTO = {
|
||||
const userDTO = this.authSessionPresenter.responseModel;
|
||||
const session = await this.identitySessionPort.createSession({
|
||||
id: userDTO.userId,
|
||||
displayName: userDTO.displayName,
|
||||
email: userDTO.email,
|
||||
};
|
||||
const session = await this.identitySessionPort.createSession(coreUserDTO);
|
||||
});
|
||||
|
||||
return {
|
||||
token: session.token,
|
||||
@@ -113,14 +131,15 @@ export class AuthService {
|
||||
async logout(): Promise<CommandResultDTO> {
|
||||
this.logger.debug('[AuthService] Attempting logout.');
|
||||
|
||||
const commandResultPresenter = new CommandResultPresenter();
|
||||
const result = await this.logoutUseCase.execute(); // TODO
|
||||
this.commandResultPresenter.reset();
|
||||
|
||||
const result = await this.logoutUseCase.execute(undefined);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr();
|
||||
throw new Error(error.details?.message ?? 'Logout failed');
|
||||
const error = result.unwrapErr() as LogoutApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Logout failed'));
|
||||
}
|
||||
|
||||
return commandResultPresenter.getResponseModel();
|
||||
return this.commandResultPresenter.responseModel;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user