Skip to content

feat: implement password reset and update functionality#22

Merged
tarek-gritli merged 1 commit intomainfrom
profile
Jun 8, 2025
Merged

feat: implement password reset and update functionality#22
tarek-gritli merged 1 commit intomainfrom
profile

Conversation

@tarek-gritli
Copy link
Collaborator

@tarek-gritli tarek-gritli commented Jun 8, 2025

PR Type

Enhancement


Description

  • Added user password update and reset logic

    • New endpoint and service for updating password with current password check
    • Refactored password reset to use new service method
  • Enhanced user profile update functionality

    • Unified profile update with image upload in a single endpoint
    • Improved DTOs to separate password and account type updates
  • Added endpoints for updating account type and deleting account

  • Improved API documentation and validation for user-related endpoints


Changes walkthrough 📝

Relevant files
Enhancement
auth.service.ts
Refactor password reset to use new service method               

src/auth/auth.service.ts

  • Refactored password reset logic to use new service method
  • Simplified resetPassword to delegate to UsersService
  • +1/-13   
    update-password.dto.ts
    Add UpdatePasswordDto for password update endpoint             

    src/users/dto/update-password.dto.ts

  • Added new DTO for updating user password
  • Includes validation and Swagger documentation
  • +23/-0   
    update-user.dto.ts
    Refactor user update DTOs and add account type DTO             

    src/users/dto/update-user.dto.ts

  • Updated UpdateUserDto to omit password field
  • Added UpdateAccountType DTO for account type changes
  • +6/-2     
    users.controller.ts
    Add endpoints for profile, password, account type, and deletion

    src/users/users.controller.ts

  • Unified profile update and image upload in PATCH /profile
  • Added PATCH endpoints for password and account type updates
  • Added DELETE endpoint for account deletion
  • Improved Swagger documentation for new endpoints
  • +112/-35
    users.service.ts
    Add and refactor service methods for user management         

    src/users/users.service.ts

  • Added updateProfile, updatePassword, updateAccountType service methods
  • Added resetPasswordWithToken for password reset logic
  • Refactored profile update to exclude password/account type
  • +67/-10 

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • @qodo-code-review
    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 Security concerns

    Password security concerns:
    The password validation in UpdatePasswordDto only enforces a minimum length of 6 characters (line 21), which is considered insufficient by modern security standards. This could allow users to set weak passwords that are vulnerable to brute force attacks. Consider implementing stronger password requirements such as requiring a mix of uppercase, lowercase, numbers, and special characters, and increasing the minimum length to at least 8 characters.

    ⚡ Recommended focus areas for review

    Missing Validation

    The file upload in updateProfile method doesn't validate the file before using it. While there are Multer options for validation, there's no explicit check if the file is valid before assigning to profileImage.

    if (file) {
      updateUserDto.profileImage = file.path;
    }
    Password Security

    The resetPasswordWithToken method doesn't enforce password complexity requirements beyond what's in the DTO. Consider adding additional validation for password strength.

    async resetPasswordWithToken(token: string, newPassword: string) {
      const user = await this.findByResetToken(token);
      if (!user) {
        throw new ForbiddenException('Invalid or expired reset token');
      }
    
      if (
        user.reset_pass_expires &&
        new Date() > new Date(user.reset_pass_expires)
      )
        throw new ForbiddenException('Invalid or expired reset token');
    
      // hash new password
      const password_hash = await this.hashService.hashPassword(newPassword);
    
      return await this.prisma.user.update({
        where: { id: user.id },
        data: {
          password_hash,
          reset_pass_token: null,
          reset_pass_expires: null,
        },
        select: this.userSafeFields,
      });
    }
    Weak Validation

    The password validation only requires a minimum length of 6 characters, which is considered weak by modern security standards. Consider adding more robust validation rules.

    @IsNotEmpty()
    @IsString()
    @MinLength(6)
    newPassword: string;

    @github-actions
    Copy link

    github-actions bot commented Jun 8, 2025

    Failed to generate code suggestions for PR

    @qodo-code-review
    Copy link

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Missing null check

    The code uses non-null assertion (user!) without first checking if the user
    exists. If findBy() returns null, this will cause a runtime error when accessing
    password_hash. Add a null check before proceeding.

    src/users/users.service.ts [90-111]

     async updatePassword(userId: number, updatePasswordDto: UpdatePasswordDto) {
       const user = await this.findBy({ id: userId });
    +  
    +  if (!user) {
    +    throw new NotFoundException('User not found');
    +  }
     
       const { currentPassword, newPassword } = updatePasswordDto;
     
       const isCurrentPasswordValid = await this.hashService.comparePassword(
         currentPassword,
    -    user!.password_hash,
    +    user.password_hash,
       );
       if (!isCurrentPasswordValid) {
         throw new ForbiddenException('Current password is incorrect');
       }
     
       const password_hash = await this.hashService.hashPassword(newPassword);
       await this.prisma.user.update({
         where: { id: userId },
         data: { password_hash },
         select: this.userSafeFields,
       });
     
       return { message: 'Password updated successfully' };
     }
    • Apply / Chat
    Suggestion importance[1-10]: 7

    __

    Why: Valid suggestion to add null check before using user!.password_hash. The non-null assertion could cause runtime errors if findBy() returns null, and adding proper error handling improves code robustness.

    Medium
    • More

    @tarek-gritli tarek-gritli merged commit 9f9aded into main Jun 8, 2025
    1 check passed
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    1 participant