diff --git a/users_microservice/src/main/java/com/users/application/controllers/VerifyCustomerController.java b/users_microservice/src/main/java/com/users/application/controllers/VerifyCustomerController.java index ebfc351..78fa887 100644 --- a/users_microservice/src/main/java/com/users/application/controllers/VerifyCustomerController.java +++ b/users_microservice/src/main/java/com/users/application/controllers/VerifyCustomerController.java @@ -39,4 +39,21 @@ public String verifyCustomer(@RequestParam String qTokq1) { } + @GetMapping("/verify-password-update") + public String verifyPasswordUpdate(@RequestParam String qTokq1) { + FindByTokenRequest request = new FindByTokenRequest(qTokq1); + UsersService.setFindByTokenRequest(request); + UsersService.setServiceHandler("verifyUser"); + var response = serviceConcurrentExecutor.buildServiceExecutor(service); +/* +I need to create update + */ + if(response.size() == 1){ + return "redirect:https://www.example.com"; + }else{ + return null; + } + } + + } diff --git a/users_microservice/src/main/java/com/users/application/dtos/FindByEmailRequest.java b/users_microservice/src/main/java/com/users/application/dtos/FindByEmailRequest.java new file mode 100644 index 0000000..7cd244e --- /dev/null +++ b/users_microservice/src/main/java/com/users/application/dtos/FindByEmailRequest.java @@ -0,0 +1,12 @@ +package com.users.application.dtos; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@AllArgsConstructor +public class FindByEmailRequest { + private String emailAddress; +} diff --git a/users_microservice/src/main/java/com/users/application/entities/Users.java b/users_microservice/src/main/java/com/users/application/entities/Users.java index dea3677..4710554 100644 --- a/users_microservice/src/main/java/com/users/application/entities/Users.java +++ b/users_microservice/src/main/java/com/users/application/entities/Users.java @@ -31,9 +31,9 @@ public class Users implements UserDetails { private String userEmailAddress; @Column(columnDefinition = "TEXT",nullable = false) - private String userPassword; + private String userPassword,previousPassword; @Column(nullable = false) - private Short userStatus, userAge; + private Short userStatus, userAge,passwordUpdateStatus; @Column(nullable = false, unique = true) private String userFullName; @Column(nullable = false) diff --git a/users_microservice/src/main/java/com/users/application/services/UsersService.java b/users_microservice/src/main/java/com/users/application/services/UsersService.java index e57446d..81650cf 100644 --- a/users_microservice/src/main/java/com/users/application/services/UsersService.java +++ b/users_microservice/src/main/java/com/users/application/services/UsersService.java @@ -13,6 +13,7 @@ import com.utils.application.globalExceptions.ServiceHandlerException; import com.utils.application.mailing.VerifyCustomerEmail; import com.utils.application.mailing.dto.VerifyCustomerEvent; +import com.utils.application.mailing.dto.VerifyUpdatePasswordEvent; import jakarta.transaction.Transactional; import lombok.Getter; import lombok.Setter; @@ -69,7 +70,7 @@ public class UsersService implements Execute> { @Autowired public UsersService(@Autowired ApplicationEventPublisher publisher, @Autowired RedisTemplate redisTemplate, PasswordEncoder passwordEncoder, @Autowired JwtService jwtService, @Autowired AuthenticationManager authenticationManager, @Autowired UsersRepository usersRepository, @Autowired UsersMapper usersMapper) { setUsersRepository(usersRepository); - this.publisher= publisher; + this.publisher = publisher; UsersService.passwordEncoder = passwordEncoder; UsersService.usersMapper = usersMapper; UsersService.jwtService = jwtService; @@ -165,6 +166,7 @@ private List registerUsers() { Users users = Users.builder() .userIdentityNo(getInstance().validateIdentityNo(request.getUserIdentityNo())) .userPassword(passwordEncoder.encode(getInstance().checkPasswordValidity(usersRegisterRequest().getUserPassword().trim()))) + .previousPassword(passwordEncoder.encode(getInstance().checkPasswordValidity(usersRegisterRequest().getUserPassword().trim()))) .userRegistrationDate(getInstance().formatDateTime(LocalDateTime.now())) .userModifiedDate(getInstance().formatDateTime(LocalDateTime.now())) .fk_privilege_id(request.getPrivileges()) @@ -173,12 +175,13 @@ private List registerUsers() { .userFullName(request.getUserFullName().trim()) .userEmailAddress(request.getUserEmailAddress().trim()) .userAge(getInstance().getValidatedAge()) + .passwordUpdateStatus((short) 0) .build(); try { logger.info("users was successfully registered : data : {}", usersRepository.save(users)); - var responseList =mapToResponse(List.of(users)); + var responseList = mapToResponse(List.of(users)); if (redisService.get("ALL_USERS", UsersResponse.class) != null) { logger.info("Cached data for all users deleted : {}", redisService.delete("ALL_USERS")); @@ -260,7 +263,8 @@ private List updateUsersPassword() { throw throwExceptionAndReport(new NullRequestException(errorMessage), errorMessage, resolveIssue); } } -private List mapToResponse(List list){ + + private List mapToResponse(List list) { return list.parallelStream().map(s -> UsersResponse .builder() .usersAge(s.getUserAge()) @@ -276,7 +280,8 @@ private List mapToResponse(List list){ .token(s.getToken()) .build()).toList(); -} + } + private List findUserById() { String encrypt; try { @@ -294,7 +299,7 @@ private List findUserById() { if (responseList.isPresent()) { var users = responseList.get(); - var jpaUserResponse =mapToResponse(List.of(users)); + var jpaUserResponse = mapToResponse(List.of(users)); redisService.set(encrypt, jpaUserResponse.get(0), 1L, TimeUnit.HOURS); logger.info("cached data : {}", redisService.get(encrypt, UsersResponse.class)); @@ -318,15 +323,15 @@ private List findUserById() { private List findAllUsers() { var redisResponse = redisService.get("ALL_USERS", List.class); if (redisResponse != null) { - var returnRedisResponse = redisService.safeCastList(redisResponse,UsersResponse.class); + var returnRedisResponse = redisService.safeCastList(redisResponse, UsersResponse.class); logger.info("get all users from cache, data from redis : {}", returnRedisResponse); return returnRedisResponse; } else { - var jpaResponse= mapToResponse(usersRepository.findAll()); + var jpaResponse = mapToResponse(usersRepository.findAll()); - redisService.set("ALL_USERS",jpaResponse,1L,TimeUnit.HOURS); + redisService.set("ALL_USERS", jpaResponse, 1L, TimeUnit.HOURS); var redisResponseChecker = redisService.get("ALL_USERS", List.class); - logger.info("cached data for all users from jpa : {}", redisService.safeCastList(redisResponseChecker,UsersResponse.class)); + logger.info("cached data for all users from jpa : {}", redisService.safeCastList(redisResponseChecker, UsersResponse.class)); return jpaResponse; } } @@ -366,7 +371,7 @@ private List findAllUsersByName() { } - private boolean passwordStatus,sendMail; + private boolean passwordStatus, sendMail; @Transactional @@ -380,11 +385,11 @@ private List login() { if (redisUserResponse != null) { logger.info("redis executing..."); jpaUserResponse = null; - if (redisUserResponse.getUsersStatus() == 0){ - var errorMessage = "User already got email to verify account"; - var resolveIssue = "check emails and click the link from email : verify@aa.com. New link will be generated after Hour"; - throw throwExceptionAndReport(new VerifyEmailAddressException(errorMessage), errorMessage, resolveIssue); - } + if (redisUserResponse.getUsersStatus() == 0) { + var errorMessage = "User already got email to verify account"; + var resolveIssue = "check emails and click the link from email : verify@aa.com. New link will be generated after Hour"; + throw throwExceptionAndReport(new VerifyEmailAddressException(errorMessage), errorMessage, resolveIssue); + } redisStatus = true; @@ -401,7 +406,6 @@ private List login() { logger.info("email address {} found", loginRequest().getUsersEmailAddress()); - var users = optionalEntity.get(); var jwt = jwtService.generateToken(optionalEntity.get()); users.setToken(jwt); @@ -409,30 +413,40 @@ private List login() { logger.info("User with set token : {}", users); - var userWithToken= usersRepository.save(users); + var userWithToken = usersRepository.save(users); logger.info("User with set token from db : {}", userWithToken); jpaUserResponse = mapToResponse(List.of(userWithToken)).get(0); // send mail when status is 0, pub sub pattern will be used - if (optionalEntity.get().getUserStatus() == 0){ + if (optionalEntity.get().getUserStatus() == 0) { publisher.publishEvent(VerifyCustomerEvent .builder() - .emailFrom("softwareaa65@gmail.com") - .emailTo(jpaUserResponse.getUsersEmailAddress()) - .name(jpaUserResponse.getUsersFullName()) - .token(jpaUserResponse.getToken()) + .emailFrom("softwareaa65@gmail.com") + .emailTo(jpaUserResponse.getUsersEmailAddress()) + .name(jpaUserResponse.getUsersFullName()) + .token(jpaUserResponse.getToken()) .privilegeId(optionalEntity.get().getFk_privilege_id()) .build() ); - logger.info("user : {} has not been verified, email sent to verify customer",jpaUserResponse.getUsersFullName()); + logger.info("user : {} has not been verified, email sent to verify customer", jpaUserResponse.getUsersFullName()); sendMail = true; - } else if(optionalEntity.get().getUserStatus() == 1){ + } else if (optionalEntity.get().getUserStatus() == 1) { passwordStatus = true; - logger.info("user : {} has been verified,trying to login...",jpaUserResponse.getUsersFullName()); + logger.info("user : {} has been verified,trying to login...", jpaUserResponse.getUsersFullName()); sendMail = false; - }else { + if (optionalEntity.get().getPasswordUpdateStatus() == 0) { + publisher.publishEvent(VerifyUpdatePasswordEvent + .builder() + .emailFrom("softwareaa65@gmail.com") + .emailTo(jpaUserResponse.getUsersEmailAddress()) + .name(jpaUserResponse.getUsersFullName()) + .token(jpaUserResponse.getToken()) + .build() + ); + } + } else { var errorMessage = "log in failed due to invalid user status "; var resolveIssue = "Contact AA Administrator"; @@ -456,10 +470,9 @@ private List login() { logger.info("user with email {} successfully logged in using jpa data : {}", loginRequest().getUsersEmailAddress(), jpaUserResponse); - redisService.set(encrypt, jpaUserResponse, 1L, TimeUnit.HOURS); - - logger.info("cached login data : {}", redisService.get(encrypt, UsersResponse.class)); + redisService.set(encrypt, jpaUserResponse, 1L, TimeUnit.HOURS); + logger.info("cached login data : {}", redisService.get(encrypt, UsersResponse.class)); return List.of(jpaUserResponse); @@ -507,30 +520,73 @@ public List call() { case "getUsersById" -> this.findUserById(); case "userLogin" -> this.login(); case "userUpdatePassword" -> this.updateUsersPassword(); - case "verifyUser"-> this.verifyCustomer(); + case "verifyUser" -> this.verifyCustomer(); + case "passwordRollBack" -> this.passwordRollBack(); + case "verifyPasswordUpdate" -> this.verifyPasswordUpdate(); default -> throw new ServiceHandlerException("Failed execute service due to incorrect service string"); }; else return null; } + private FindByEmailRequest findByEmailRequest; + + private List passwordRollBack() { + Optional user = usersRepository.findByUserEmailAddress(findByEmailRequest.getEmailAddress()); + + if (user.isPresent()) { + var foundUser = user.get(); + + foundUser.setUserPassword(foundUser.getPreviousPassword()); + return mapToResponse(List.of(usersRepository.save(foundUser))); + } else { + var errorMessage = "user with email:" +findByEmailRequest.getEmailAddress() + " not found"; + var resolveIssue = "Please provide correct email"; + throw throwExceptionAndReport(new UserNotFoundException(errorMessage), errorMessage, resolveIssue); + + } + + + } + + private List verifyPasswordUpdate() { + Optional user = usersRepository.findByToken(findByTokenRequest.getToken()); + if (user.isPresent()) { + var verifiedUser = user.get(); + verifiedUser.setPasswordUpdateStatus((short) 1); + verifiedUser.setPreviousPassword(verifiedUser.getPassword()); + verifiedUser.setUserModifiedDate(getInstance().formatDateTime(LocalDateTime.now())); + + logger.info("User : {} has been successfully verified", verifiedUser.getUserFullName()); + redisService.delete(verifiedUser.getUserEmailAddress()); + + return mapToResponse(List.of(usersRepository.save(verifiedUser))); + + } else { + var errorMessage = UsersControllerAdvice.setMessage("User token to verify customer has expired"); + var resolveIssue = "Please log in again to get new token in your mail"; + throw throwExceptionAndReport(new VerificationTokenIncorrectException(errorMessage), errorMessage, resolveIssue); + } + } + @Transactional private List verifyCustomer() { - Optional user = usersRepository.findByToken(findByTokenRequest.getToken()); - - if(user.isPresent()){ - var verifiedUser = user.get(); - verifiedUser.setUserStatus((short)1); - verifiedUser.setUserModifiedDate(getInstance().formatDateTime(LocalDateTime.now())); -logger.info("User : {} has been successfully verified", verifiedUser.getUserFullName()); - redisService.delete(verifiedUser.getUserEmailAddress()); - - return mapToResponse(List.of(usersRepository.save(verifiedUser))); - }else{ - var errorMessage = UsersControllerAdvice.setMessage("User token to verify customer has expired"); - var resolveIssue = "Please log in again to get new token in your mail"; - throw throwExceptionAndReport(new VerificationTokenIncorrectException(errorMessage), errorMessage, resolveIssue); - } + Optional user = usersRepository.findByToken(findByTokenRequest.getToken()); + + if (user.isPresent()) { + var verifiedUser = user.get(); + verifiedUser.setUserStatus((short) 1); + verifiedUser.setPasswordUpdateStatus((short) 1); + verifiedUser.setUserModifiedDate(getInstance().formatDateTime(LocalDateTime.now())); + logger.info("User : {} has been successfully verified", verifiedUser.getUserFullName()); + redisService.delete(verifiedUser.getUserEmailAddress()); + + return mapToResponse(List.of(usersRepository.save(verifiedUser))); + } else { + var errorMessage = UsersControllerAdvice.setMessage("User token to verify customer has expired"); + var resolveIssue = "Please log in again to get new token in your mail"; + throw throwExceptionAndReport(new VerificationTokenIncorrectException(errorMessage), errorMessage, resolveIssue); + } } diff --git a/users_microservice/src/main/resources/templates/verify-alcohol-agent-artists.html b/users_microservice/src/main/resources/templates/verify-alcohol-agent-artists.html index e1f47bb..8d9e16c 100644 --- a/users_microservice/src/main/resources/templates/verify-alcohol-agent-artists.html +++ b/users_microservice/src/main/resources/templates/verify-alcohol-agent-artists.html @@ -41,12 +41,12 @@

To activate your account and complete registration, please - click here + click here or use the button below:

- Verify Me diff --git a/users_microservice/src/main/resources/templates/verify-alcohol-agents-password-update.html b/users_microservice/src/main/resources/templates/verify-alcohol-agents-password-update.html new file mode 100644 index 0000000..ea70089 --- /dev/null +++ b/users_microservice/src/main/resources/templates/verify-alcohol-agents-password-update.html @@ -0,0 +1,63 @@ + + + + + Verify E-mail + + + + + + + + + + + + + +
+ Alcohol Agent Logo +

Alcohol Agent Password Update Mail

+
+

Hi User,

+

You have updated your Alcohol Agentpassword please confirm below

+ +

+ Your registered email: example@example.com. + Please use this email to log in after confirming to updating your password. +

+ +

+ To update confirm password for Alcohol Agent account, please + click here + or use the button below: +

+
+ +

If you have not requested to update password, please click the rollback button below or got to update

+

+ + Confirm Update Password + +

+ + + +

+ This is a no-reply email. Please do not reply. +

+
+ +

Kind regards,

+ The Alcohol Agent Team +
+ Need help? Visit Support | © 2025 Alcohol Agent +
+ + diff --git a/utils_microservice/src/main/java/com/utils/application/mailing/VerifyCustomerPasswordUpdateEmail.java b/utils_microservice/src/main/java/com/utils/application/mailing/VerifyCustomerPasswordUpdateEmail.java new file mode 100644 index 0000000..b566f46 --- /dev/null +++ b/utils_microservice/src/main/java/com/utils/application/mailing/VerifyCustomerPasswordUpdateEmail.java @@ -0,0 +1,37 @@ +package com.utils.application.mailing; + +import com.utils.application.mailing.dto.VerifyCustomerEvent; +import com.utils.application.mailing.dto.VerifyUpdatePasswordEvent; +import jakarta.mail.MessagingException; +import lombok.NoArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@NoArgsConstructor +@Component +public class VerifyCustomerPasswordUpdateEmail { + private static final Logger logger = LoggerFactory.getLogger(VerifyCustomerPasswordUpdateEmail.class); + private MailService mailService; + + @Autowired + public VerifyCustomerPasswordUpdateEmail(MailService mailService) { + this.mailService = mailService; + } + + @Async + @EventListener + public void sendVerifyPasswordUpdateEmail(VerifyUpdatePasswordEvent event) { + try { + logger.info("preparing to sent email to {} for verify password updating", event.getEmailTo()); + event.setSubject("Verify Alcohol Agent Password Update!"); + mailService.sendVerifyCustomerEmail(event.getEmailTo(), event.getSubject(), event.getEmailFrom(), "verify-alcohol-agents-password-update", event.getName(), event.getToken()); + + } catch (MessagingException e) { + throw new RuntimeException(e); + } + } +} diff --git a/utils_microservice/src/main/java/com/utils/application/mailing/dto/VerifyUpdatePasswordEvent.java b/utils_microservice/src/main/java/com/utils/application/mailing/dto/VerifyUpdatePasswordEvent.java new file mode 100644 index 0000000..77920fc --- /dev/null +++ b/utils_microservice/src/main/java/com/utils/application/mailing/dto/VerifyUpdatePasswordEvent.java @@ -0,0 +1,14 @@ +package com.utils.application.mailing.dto; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@AllArgsConstructor +public class VerifyUpdatePasswordEvent { + private String emailFrom,emailTo,Subject,name,token; + +}