Changeset ae83647 for petify-backend/src


Ignore:
Timestamp:
06/26/26 16:32:12 (2 days ago)
Author:
veronika-ils <ilioskaveronika@…>
Branches:
master
Parents:
fa32d0f
Message:

add functionality so that users can change passwords

Location:
petify-backend/src/main
Files:
4 added
5 edited

Legend:

Unmodified
Added
Removed
  • petify-backend/src/main/java/com/petify/petify/api/AdminClinicApplicationsController.java

    rfa32d0f rae83647  
    11package com.petify.petify.api;
    22
    3 import com.petify.petify.domain.VetClinic;
    43import com.petify.petify.domain.VetClinicApplication;
    54import com.petify.petify.dto.VetClinicApplicationDTO;
    65import com.petify.petify.repo.AdminRepository;
    76import com.petify.petify.repo.VetClinicApplicationRepository;
    8 import com.petify.petify.repo.VetClinicRepository;
     7import com.petify.petify.service.ClinicApprovalService;
    98import org.springframework.http.HttpStatus;
    109import org.springframework.http.ResponseEntity;
     
    2019
    2120    private final VetClinicApplicationRepository applicationRepository;
    22     private final VetClinicRepository clinicRepository;
    2321    private final AdminRepository adminRepository;
     22    private final ClinicApprovalService clinicApprovalService;
    2423
    2524    public AdminClinicApplicationsController(VetClinicApplicationRepository applicationRepository,
    26                                              VetClinicRepository clinicRepository,
    27                                              AdminRepository adminRepository) {
     25                                             AdminRepository adminRepository,
     26                                             ClinicApprovalService clinicApprovalService) {
    2827        this.applicationRepository = applicationRepository;
    29         this.clinicRepository = clinicRepository;
    3028        this.adminRepository = adminRepository;
     29        this.clinicApprovalService = clinicApprovalService;
    3130    }
    3231
     
    5655                        .body(Map.of("error", "Admin access required"));
    5756            }
    58             VetClinicApplication application = applicationRepository.findById(applicationId)
    59                 .orElseThrow(() -> new RuntimeException("Application not found"));
    60 
    61             application.setStatus("APPROVED");
    62             application.setReviewedAt(LocalDateTime.now());
    63             application.setReviewedBy(adminUserId);
    64             application.setDenialReason(null);
    65             VetClinicApplication saved = applicationRepository.save(application);
    66 
    67             boolean clinicExists = clinicRepository.findAll().stream()
    68                 .anyMatch(clinic -> applicationId.equals(clinic.getApplicationId()));
    69             if (!clinicExists) {
    70                 VetClinic clinic = new VetClinic();
    71                 clinic.setApplicationId(application.getApplicationId());
    72                 clinic.setName(application.getName());
    73                 clinic.setEmail(application.getEmail());
    74                 clinic.setPhone(application.getPhone());
    75                 clinic.setCity(application.getCity());
    76                 clinic.setAddress(application.getAddress());
    77                 clinicRepository.save(clinic);
    78             }
     57            VetClinicApplication saved = clinicApprovalService.approveApplication(applicationId, adminUserId);
    7958
    8059            return ResponseEntity.ok(new VetClinicApplicationDTO(saved));
  • petify-backend/src/main/java/com/petify/petify/api/AuthController.java

    rfa32d0f rae83647  
    22
    33import com.petify.petify.dto.AuthResponse;
     4import com.petify.petify.dto.ChangePasswordRequest;
     5import com.petify.petify.dto.ForgotPasswordRequest;
    46import com.petify.petify.dto.LoginRequest;
    57import com.petify.petify.dto.SignUpRequest;
     
    4749    }
    4850
     51    @PostMapping("/change-password")
     52    public ResponseEntity<?> changePassword(@RequestBody ChangePasswordRequest request) {
     53        try {
     54            authService.changePassword(request.getUserId(), request.getCurrentPassword(), request.getNewPassword());
     55            return ResponseEntity.ok(Map.of("message", "Password changed successfully"));
     56        } catch (RuntimeException e) {
     57            return ResponseEntity.badRequest()
     58                    .body(Map.of("message", e.getMessage()));
     59        }
     60    }
     61
     62    @PostMapping("/forgot-password")
     63    public ResponseEntity<?> forgotPassword(@RequestBody ForgotPasswordRequest request) {
     64        try {
     65            authService.sendForgotPasswordEmail(request.getIdentifier());
     66            return ResponseEntity.ok(Map.of("message", "If an account matches that username or email, a temporary password has been sent."));
     67        } catch (RuntimeException e) {
     68            return ResponseEntity.badRequest()
     69                    .body(Map.of("message", e.getMessage()));
     70        }
     71    }
     72
    4973
    5074    @GetMapping("/users")
  • petify-backend/src/main/java/com/petify/petify/repo/VetClinicRepository.java

    rfa32d0f rae83647  
    1010public interface VetClinicRepository extends JpaRepository<VetClinic, Long> {
    1111    java.util.List<VetClinic> findAllByOrderByNameAsc();
     12    Optional<VetClinic> findByApplicationId(Long applicationId);
    1213    Optional<VetClinic> findByUserId(Long userId);
    1314    boolean existsByUserId(Long userId);
  • petify-backend/src/main/java/com/petify/petify/service/AuthService.java

    rfa32d0f rae83647  
    2222import org.springframework.transaction.annotation.Transactional;
    2323
     24import java.security.SecureRandom;
    2425import java.time.LocalDateTime;
    2526import java.util.List;
     
    3132
    3233    private static final Logger logger = LoggerFactory.getLogger(AuthService.class);
     34    private static final String PASSWORD_CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%";
     35    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    3336
    3437    private final UserRepository userRepository;
     
    3942    private final AnalyticsRepository analyticsRepository;
    4043    private final VetClinicRepository vetClinicRepository;
     44    private final ClinicCredentialsEmailService credentialsEmailService;
    4145
    4246    public AuthService(UserRepository userRepository, ClientRepository clientRepository,
    4347                      OwnerRepository ownerRepository, AdminRepository adminRepository,
    4448                      PasswordEncoder passwordEncoder, AnalyticsRepository analyticsRepository,
    45                       VetClinicRepository vetClinicRepository) {
     49                      VetClinicRepository vetClinicRepository,
     50                      ClinicCredentialsEmailService credentialsEmailService) {
    4651        this.userRepository = userRepository;
    4752        this.clientRepository = clientRepository;
     
    5156        this.analyticsRepository = analyticsRepository;
    5257        this.vetClinicRepository = vetClinicRepository;
     58        this.credentialsEmailService = credentialsEmailService;
    5359    }
    5460
     
    177183            isVerified
    178184        );
     185    }
     186
     187    @Transactional
     188    public void changePassword(Long userId, String currentPassword, String newPassword) {
     189        if (userId == null) {
     190            throw new RuntimeException("User is required");
     191        }
     192        if (currentPassword == null || currentPassword.isBlank()) {
     193            throw new RuntimeException("Current password is required");
     194        }
     195        if (newPassword == null || newPassword.isBlank()) {
     196            throw new RuntimeException("New password is required");
     197        }
     198        if (newPassword.length() < 8) {
     199            throw new RuntimeException("New password must be at least 8 characters long");
     200        }
     201        if (newPassword.equals(currentPassword)) {
     202            throw new RuntimeException("New password must be different from the current password");
     203        }
     204
     205        User user = userRepository.findById(userId)
     206            .orElseThrow(() -> new RuntimeException("User not found"));
     207
     208        boolean passwordMatches = passwordEncoder.matches(currentPassword, user.getPassword());
     209        if (!passwordMatches && !currentPassword.equals(user.getPassword())) {
     210            throw new RuntimeException("Current password is incorrect");
     211        }
     212
     213        user.setPassword(passwordEncoder.encode(newPassword));
     214        userRepository.save(user);
     215        logger.info("Password changed successfully for user: {}", user.getUsername());
     216    }
     217
     218    @Transactional
     219    public void sendForgotPasswordEmail(String identifier) {
     220        if (identifier == null || identifier.isBlank()) {
     221            throw new RuntimeException("Username or email is required");
     222        }
     223
     224        Optional<User> user = userRepository.findByUsernameOrEmail(identifier.trim(), identifier.trim());
     225        if (user.isEmpty()) {
     226            logger.info("Password reset requested for unknown identifier: {}", identifier);
     227            return;
     228        }
     229
     230        User foundUser = user.get();
     231        String temporaryPassword = generateTemporaryPassword();
     232        foundUser.setPassword(passwordEncoder.encode(temporaryPassword));
     233        userRepository.save(foundUser);
     234
     235        credentialsEmailService.sendTemporaryPassword(
     236            foundUser.getEmail(),
     237            foundUser.getFirstName(),
     238            foundUser.getUsername(),
     239            temporaryPassword
     240        );
     241        logger.info("Temporary password sent for user: {}", foundUser.getUsername());
     242    }
     243
     244    private String generateTemporaryPassword() {
     245        StringBuilder password = new StringBuilder();
     246        for (int i = 0; i < 14; i++) {
     247            password.append(PASSWORD_CHARS.charAt(SECURE_RANDOM.nextInt(PASSWORD_CHARS.length())));
     248        }
     249        return password.toString();
    179250    }
    180251
  • petify-backend/src/main/resources/application.properties

    rfa32d0f rae83647  
    3333spring.flyway.baseline-version=0
    3434
     35# Mail
     36spring.mail.host=${MAIL_HOST:smtp.gmail.com}
     37spring.mail.port=${MAIL_PORT:587}
     38spring.mail.username=${MAIL_USERNAME:}
     39spring.mail.password=${MAIL_PASSWORD:}
     40spring.mail.properties.mail.smtp.auth=true
     41spring.mail.properties.mail.smtp.starttls.enable=true
     42spring.mail.properties.mail.smtp.starttls.required=true
     43management.health.mail.enabled=false
     44
    3545spring.profiles.active=local
    36 spring.config.import=optional:file:.env.properties
     46spring.config.import=optional:file:.env.properties,optional:file:petify-backend/.env.properties
    3747
    3848
Note: See TracChangeset for help on using the changeset viewer.