From 2dfc5cb2d6d20cecb85a56cd611b8d6cd170c7a9 Mon Sep 17 00:00:00 2001 From: Hai Nguyen Date: Sat, 4 Jan 2025 12:28:16 -0800 Subject: [PATCH] Create user email sender (#51) --- .../modules/collab/service/MailService.java | 2 +- .../modules/usermanagement/domain/User.java | 8 ++++++ .../usermanagement/service/UserService.java | 26 +++++-------------- .../service/event/CreatedUserEvent.java | 15 +++++++++++ .../listener/CreatedUserEventListener.java | 25 ++++++++++++++++++ .../web/rest/PublicUserController.java | 9 +------ .../tenant/changelog/000_initial_schema.xml | 3 ++- 7 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 commons/src/main/java/io/flowinquiry/modules/usermanagement/service/event/CreatedUserEvent.java create mode 100644 commons/src/main/java/io/flowinquiry/modules/usermanagement/service/listener/CreatedUserEventListener.java diff --git a/commons/src/main/java/io/flowinquiry/modules/collab/service/MailService.java b/commons/src/main/java/io/flowinquiry/modules/collab/service/MailService.java index f5b1917..b80fcd3 100644 --- a/commons/src/main/java/io/flowinquiry/modules/collab/service/MailService.java +++ b/commons/src/main/java/io/flowinquiry/modules/collab/service/MailService.java @@ -96,7 +96,7 @@ public void sendEmailFromTemplate(UserDTO user, String templateName, String titl LOG.debug("Email doesn't exist for user '{}'", user); return; } - Locale locale = Locale.forLanguageTag(user.getLangKey()); + Locale locale = Locale.forLanguageTag(user.getLangKey() != null ? user.getLangKey() : "en"); Context context = new Context(locale); context.setVariable(USER, user); context.setVariable(BASE_URL, flowInquiryProperties.getMail().getBaseUrl()); diff --git a/commons/src/main/java/io/flowinquiry/modules/usermanagement/domain/User.java b/commons/src/main/java/io/flowinquiry/modules/usermanagement/domain/User.java index 7e4b1f0..985a705 100644 --- a/commons/src/main/java/io/flowinquiry/modules/usermanagement/domain/User.java +++ b/commons/src/main/java/io/flowinquiry/modules/usermanagement/domain/User.java @@ -16,6 +16,7 @@ import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import jakarta.persistence.PrePersist; import jakarta.persistence.Table; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotNull; @@ -165,4 +166,11 @@ public LocalDateTime getLastLoginTime() { (timezone != null) ? ZoneId.of(timezone) : ZoneId.of("America/Los_Angeles"); return lastLoginTime.atZone(ZoneOffset.UTC).withZoneSameInstant(userZone).toLocalDateTime(); } + + @PrePersist + public void prePersist() { + if (isDeleted == null) { + isDeleted = Boolean.FALSE; + } + } } diff --git a/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/UserService.java b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/UserService.java index 02dfb23..f58c8fd 100644 --- a/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/UserService.java +++ b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/UserService.java @@ -15,10 +15,10 @@ import io.flowinquiry.modules.usermanagement.service.dto.UserDTO; import io.flowinquiry.modules.usermanagement.service.dto.UserHierarchyDTO; import io.flowinquiry.modules.usermanagement.service.dto.UserKey; +import io.flowinquiry.modules.usermanagement.service.event.CreatedUserEvent; import io.flowinquiry.modules.usermanagement.service.event.DeleteUserEvent; import io.flowinquiry.modules.usermanagement.service.mapper.UserMapper; import io.flowinquiry.query.QueryDTO; -import io.flowinquiry.security.Constants; import io.flowinquiry.security.SecurityUtils; import io.flowinquiry.utils.Random; import jakarta.persistence.EntityNotFoundException; @@ -95,6 +95,7 @@ public Optional completePasswordReset(String newPassword, String key) { .map( user -> { user.setPassword(passwordEncoder.encode(newPassword)); + user.setStatus(UserStatus.ACTIVE); user.setResetKey(null); user.setResetDate(null); return user; @@ -157,21 +158,7 @@ private boolean removeNonActivatedUser(User existingUser) { } public UserDTO createUser(UserDTO userDTO) { - User user = new User(); - user.setFirstName(userDTO.getFirstName()); - user.setLastName(userDTO.getLastName()); - if (userDTO.getManagerId() != null) { - user.setManager(User.builder().id(userDTO.getManagerId()).build()); - } - if (userDTO.getEmail() != null) { - user.setEmail(userDTO.getEmail().toLowerCase()); - } - user.setImageUrl(userDTO.getImageUrl()); - if (userDTO.getLangKey() == null) { - user.setLangKey(Constants.DEFAULT_LANGUAGE); // default language - } else { - user.setLangKey(userDTO.getLangKey()); - } + User user = userMapper.toEntity(userDTO); String encryptedPassword = passwordEncoder.encode(Random.generatePassword()); user.setPassword(encryptedPassword); user.setResetKey(Random.generateResetKey()); @@ -193,7 +180,9 @@ public UserDTO createUser(UserDTO userDTO) { } userRepository.save(user); LOG.debug("Created Information for User: {}", user); - return userMapper.toDto(user); + UserDTO savedUser = userMapper.toDto(user); + eventPublisher.publishEvent(new CreatedUserEvent(this, savedUser)); + return savedUser; } /** @@ -364,7 +353,6 @@ public UserHierarchyDTO getOrgChart() { return rootUser; } - // Handle case with no users return null; } @@ -380,9 +368,7 @@ public UserHierarchyDTO getUserHierarchyWithSubordinates(Long userId) { // Fetch subordinates List subordinates = userRepository.findAllSubordinates(userId); - userHierarchy.setSubordinates(subordinates); - return userHierarchy; } } diff --git a/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/event/CreatedUserEvent.java b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/event/CreatedUserEvent.java new file mode 100644 index 0000000..cae7a05 --- /dev/null +++ b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/event/CreatedUserEvent.java @@ -0,0 +1,15 @@ +package io.flowinquiry.modules.usermanagement.service.event; + +import io.flowinquiry.modules.usermanagement.service.dto.UserDTO; +import lombok.Getter; +import org.springframework.context.ApplicationEvent; + +@Getter +public class CreatedUserEvent extends ApplicationEvent { + private UserDTO user; + + public CreatedUserEvent(Object source, UserDTO user) { + super(source); + this.user = user; + } +} diff --git a/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/listener/CreatedUserEventListener.java b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/listener/CreatedUserEventListener.java new file mode 100644 index 0000000..cd58624 --- /dev/null +++ b/commons/src/main/java/io/flowinquiry/modules/usermanagement/service/listener/CreatedUserEventListener.java @@ -0,0 +1,25 @@ +package io.flowinquiry.modules.usermanagement.service.listener; + +import io.flowinquiry.modules.collab.service.MailService; +import io.flowinquiry.modules.usermanagement.service.event.CreatedUserEvent; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class CreatedUserEventListener { + + private final MailService mailService; + + public CreatedUserEventListener(MailService mailService) { + this.mailService = mailService; + } + + @Async("auditLogExecutor") + @Transactional + @EventListener + public void onCreatedUserEvent(CreatedUserEvent event) { + mailService.sendCreationEmail(event.getUser()); + } +} diff --git a/commons/src/main/java/io/flowinquiry/modules/usermanagement/web/rest/PublicUserController.java b/commons/src/main/java/io/flowinquiry/modules/usermanagement/web/rest/PublicUserController.java index 2281a72..6e8a0d4 100644 --- a/commons/src/main/java/io/flowinquiry/modules/usermanagement/web/rest/PublicUserController.java +++ b/commons/src/main/java/io/flowinquiry/modules/usermanagement/web/rest/PublicUserController.java @@ -1,6 +1,5 @@ package io.flowinquiry.modules.usermanagement.web.rest; -import io.flowinquiry.modules.collab.service.MailService; import io.flowinquiry.modules.fss.service.StorageService; import io.flowinquiry.modules.usermanagement.AuthoritiesConstants; import io.flowinquiry.modules.usermanagement.domain.User; @@ -57,17 +56,12 @@ public class PublicUserController { private final UserRepository userRepository; private final UserService userService; private final StorageService storageService; - private final MailService mailService; public PublicUserController( - UserService userService, - UserRepository userRepository, - StorageService storageService, - MailService mailService) { + UserService userService, UserRepository userRepository, StorageService storageService) { this.userService = userService; this.userRepository = userRepository; this.storageService = storageService; - this.mailService = mailService; } /** @@ -196,7 +190,6 @@ public ResponseEntity createUser(@Valid @RequestBody UserDTO userDTO) throw new EmailAlreadyUsedException(); } else { UserDTO newUser = userService.createUser(userDTO); - mailService.sendCreationEmail(newUser); return ResponseEntity.created(new URI("/api/users/" + newUser.getEmail())) .body(newUser); } diff --git a/tools/liquibase/src/main/resources/config/liquibase/tenant/changelog/000_initial_schema.xml b/tools/liquibase/src/main/resources/config/liquibase/tenant/changelog/000_initial_schema.xml index c1ec54f..c980337 100644 --- a/tools/liquibase/src/main/resources/config/liquibase/tenant/changelog/000_initial_schema.xml +++ b/tools/liquibase/src/main/resources/config/liquibase/tenant/changelog/000_initial_schema.xml @@ -60,7 +60,8 @@ defaultValue="PENDING"> - +