auth
This commit is contained in:
@@ -13,23 +13,47 @@ import {
|
||||
type SignupApplicationError,
|
||||
type SignupInput,
|
||||
} from '@core/identity/application/use-cases/SignupUseCase';
|
||||
import {
|
||||
ForgotPasswordUseCase,
|
||||
type ForgotPasswordApplicationError,
|
||||
type ForgotPasswordInput,
|
||||
} from '@core/identity/application/use-cases/ForgotPasswordUseCase';
|
||||
import {
|
||||
ResetPasswordUseCase,
|
||||
type ResetPasswordApplicationError,
|
||||
type ResetPasswordInput,
|
||||
} from '@core/identity/application/use-cases/ResetPasswordUseCase';
|
||||
import {
|
||||
DemoLoginUseCase,
|
||||
type DemoLoginApplicationError,
|
||||
type DemoLoginInput,
|
||||
} from '../../development/use-cases/DemoLoginUseCase';
|
||||
|
||||
import type { IdentitySessionPort } from '@core/identity/application/ports/IdentitySessionPort';
|
||||
|
||||
import {
|
||||
AUTH_SESSION_OUTPUT_PORT_TOKEN,
|
||||
COMMAND_RESULT_OUTPUT_PORT_TOKEN,
|
||||
FORGOT_PASSWORD_OUTPUT_PORT_TOKEN,
|
||||
RESET_PASSWORD_OUTPUT_PORT_TOKEN,
|
||||
DEMO_LOGIN_OUTPUT_PORT_TOKEN,
|
||||
IDENTITY_SESSION_PORT_TOKEN,
|
||||
LOGGER_TOKEN,
|
||||
LOGIN_USE_CASE_TOKEN,
|
||||
LOGOUT_USE_CASE_TOKEN,
|
||||
SIGNUP_USE_CASE_TOKEN,
|
||||
FORGOT_PASSWORD_USE_CASE_TOKEN,
|
||||
RESET_PASSWORD_USE_CASE_TOKEN,
|
||||
DEMO_LOGIN_USE_CASE_TOKEN,
|
||||
} from './AuthProviders';
|
||||
import type { AuthSessionDTO } from './dtos/AuthDto';
|
||||
import type { AuthSessionDTO, AuthenticatedUserDTO } from './dtos/AuthDto';
|
||||
import { LoginParamsDTO, SignupParamsDTO } from './dtos/AuthDto';
|
||||
import { AuthSessionPresenter } from './presenters/AuthSessionPresenter';
|
||||
import type { CommandResultDTO } from './presenters/CommandResultPresenter';
|
||||
import { CommandResultPresenter } from './presenters/CommandResultPresenter';
|
||||
import { ForgotPasswordPresenter } from './presenters/ForgotPasswordPresenter';
|
||||
import { ResetPasswordPresenter } from './presenters/ResetPasswordPresenter';
|
||||
import { DemoLoginPresenter } from './presenters/DemoLoginPresenter';
|
||||
|
||||
function mapApplicationErrorToMessage(error: { details?: { message?: string } } | undefined, fallback: string): string {
|
||||
return error?.details?.message ?? fallback;
|
||||
@@ -43,11 +67,20 @@ export class AuthService {
|
||||
@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(FORGOT_PASSWORD_USE_CASE_TOKEN) private readonly forgotPasswordUseCase: ForgotPasswordUseCase,
|
||||
@Inject(RESET_PASSWORD_USE_CASE_TOKEN) private readonly resetPasswordUseCase: ResetPasswordUseCase,
|
||||
@Inject(DEMO_LOGIN_USE_CASE_TOKEN) private readonly demoLoginUseCase: DemoLoginUseCase,
|
||||
// TODO presenters must not be injected
|
||||
@Inject(AUTH_SESSION_OUTPUT_PORT_TOKEN)
|
||||
private readonly authSessionPresenter: AuthSessionPresenter,
|
||||
@Inject(COMMAND_RESULT_OUTPUT_PORT_TOKEN)
|
||||
private readonly commandResultPresenter: CommandResultPresenter,
|
||||
@Inject(FORGOT_PASSWORD_OUTPUT_PORT_TOKEN)
|
||||
private readonly forgotPasswordPresenter: ForgotPasswordPresenter,
|
||||
@Inject(RESET_PASSWORD_OUTPUT_PORT_TOKEN)
|
||||
private readonly resetPasswordPresenter: ResetPasswordPresenter,
|
||||
@Inject(DEMO_LOGIN_OUTPUT_PORT_TOKEN)
|
||||
private readonly demoLoginPresenter: DemoLoginPresenter,
|
||||
) {}
|
||||
|
||||
async getCurrentSession(): Promise<AuthSessionDTO | null> {
|
||||
@@ -189,4 +222,94 @@ export class AuthService {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async forgotPassword(params: { email: string }): Promise<{ message: string; magicLink?: string }> {
|
||||
this.logger.debug(`[AuthService] Attempting forgot password for email: ${params.email}`);
|
||||
|
||||
this.forgotPasswordPresenter.reset();
|
||||
|
||||
const input: ForgotPasswordInput = {
|
||||
email: params.email,
|
||||
};
|
||||
|
||||
const executeResult = await this.forgotPasswordUseCase.execute(input);
|
||||
|
||||
if (executeResult.isErr()) {
|
||||
const error = executeResult.unwrapErr() as ForgotPasswordApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Forgot password failed'));
|
||||
}
|
||||
|
||||
const response = this.forgotPasswordPresenter.responseModel;
|
||||
const result: { message: string; magicLink?: string } = {
|
||||
message: response.message,
|
||||
};
|
||||
if (response.magicLink) {
|
||||
result.magicLink = response.magicLink;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async resetPassword(params: { token: string; newPassword: string }): Promise<{ message: string }> {
|
||||
this.logger.debug('[AuthService] Attempting reset password');
|
||||
|
||||
this.resetPasswordPresenter.reset();
|
||||
|
||||
const input: ResetPasswordInput = {
|
||||
token: params.token,
|
||||
newPassword: params.newPassword,
|
||||
};
|
||||
|
||||
const result = await this.resetPasswordUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr() as ResetPasswordApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Reset password failed'));
|
||||
}
|
||||
|
||||
return this.resetPasswordPresenter.responseModel;
|
||||
}
|
||||
|
||||
async demoLogin(params: { role: 'driver' | 'sponsor' | 'league-owner' | 'league-steward' | 'league-admin' | 'system-owner' | 'super-admin' }): Promise<AuthSessionDTO> {
|
||||
this.logger.debug(`[AuthService] Attempting demo login for role: ${params.role}`);
|
||||
|
||||
this.demoLoginPresenter.reset();
|
||||
|
||||
const input: DemoLoginInput = {
|
||||
role: params.role,
|
||||
};
|
||||
|
||||
const result = await this.demoLoginUseCase.execute(input);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.unwrapErr() as DemoLoginApplicationError;
|
||||
throw new Error(mapApplicationErrorToMessage(error, 'Demo login failed'));
|
||||
}
|
||||
|
||||
const user = this.demoLoginPresenter.responseModel.user;
|
||||
const primaryDriverId = user.getPrimaryDriverId();
|
||||
|
||||
// Use primaryDriverId for session if available, otherwise fall back to userId
|
||||
const sessionId = primaryDriverId ?? user.getId().value;
|
||||
|
||||
const session = await this.identitySessionPort.createSession({
|
||||
id: sessionId,
|
||||
displayName: user.getDisplayName(),
|
||||
email: user.getEmail() ?? '',
|
||||
});
|
||||
|
||||
const userDTO: AuthenticatedUserDTO = {
|
||||
userId: user.getId().value,
|
||||
email: user.getEmail() ?? '',
|
||||
displayName: user.getDisplayName(),
|
||||
};
|
||||
|
||||
if (primaryDriverId !== undefined) {
|
||||
userDTO.primaryDriverId = primaryDriverId;
|
||||
}
|
||||
|
||||
return {
|
||||
token: session.token,
|
||||
user: userDTO,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user