Backend Complete: Interface Refactoring & Service Container Enhancements
Repository Interface Optimization: - Created IBaseRepository.ts and IPaginatedRepository.ts - Refactored all 7 repository interfaces to extend base interfaces - Eliminated ~200 lines of redundant code (70% reduction) - Improved type safety and maintainability Dependency Injection Improvements: - Added EmailService and GameTokenService to DIContainer - Updated CreateUserCommandHandler constructor for DI - Updated RequestPasswordResetCommandHandler constructor for DI - Enhanced testability and service consistency Environment Configuration: - Created comprehensive .env.example with 40+ variables - Organized into 12 logical sections (Database, Security, Email, etc.) - Added security guidelines and best practices - Documented all backend environment requirements Documentation: - Added comprehensive codebase review - Created refactoring summary report - Added frontend implementation guide Impact: Improved code quality, reduced maintenance overhead, enhanced developer experience
This commit is contained in:
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
import { RequestPasswordResetCommand } from './RequestPasswordResetCommand';
|
||||
import { IUserRepository } from '../../../Domain/IRepository/IUserRepository';
|
||||
import { EmailService } from '../../Services/EmailService';
|
||||
import { TokenService } from '../../Services/TokenService';
|
||||
import { logAuth, logWarning, logError } from '../../Services/Logger';
|
||||
|
||||
export class RequestPasswordResetCommandHandler {
|
||||
constructor(
|
||||
private userRepo: IUserRepository,
|
||||
private emailService: EmailService
|
||||
) {}
|
||||
|
||||
async execute(cmd: RequestPasswordResetCommand): Promise<boolean> {
|
||||
try {
|
||||
if (!cmd.email) {
|
||||
throw new Error('Email is required');
|
||||
}
|
||||
|
||||
// Find user by email
|
||||
const user = await this.userRepo.findByEmail(cmd.email);
|
||||
|
||||
if (!user) {
|
||||
// Don't reveal if user exists or not for security reasons
|
||||
// Still return true but don't send email
|
||||
logAuth(`Password reset requested for non-existent email: ${cmd.email}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Generate password reset token
|
||||
const resetTokenData = TokenService.generatePasswordResetToken();
|
||||
|
||||
// Update user with reset token
|
||||
user.token = await TokenService.hashToken(resetTokenData.token);
|
||||
user.TokenExpires = resetTokenData.expiresAt;
|
||||
|
||||
await this.userRepo.update(user.id, user);
|
||||
|
||||
// Send password reset email
|
||||
try {
|
||||
const baseUrl = process.env.APP_BASE_URL || 'http://localhost:3000';
|
||||
const resetUrl = TokenService.generatePasswordResetUrl(baseUrl, resetTokenData.token);
|
||||
|
||||
const emailSent = await this.emailService.sendPasswordResetEmail(
|
||||
user.email,
|
||||
`${user.fname} ${user.lname}`,
|
||||
resetTokenData.token,
|
||||
resetUrl
|
||||
);
|
||||
|
||||
if (!emailSent) {
|
||||
logWarning(`Failed to send password reset email to ${user.email}`);
|
||||
// Don't throw error - request should still succeed even if email fails
|
||||
} else {
|
||||
logAuth(`Password reset email sent successfully to ${user.email}`);
|
||||
}
|
||||
} catch (emailError) {
|
||||
logError('Error sending password reset email', emailError instanceof Error ? emailError : new Error(String(emailError)));
|
||||
// Don't throw error - request should still succeed even if email fails
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
logError('Password reset request error', error instanceof Error ? error : new Error(String(error)));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user