diff --git a/src/main/java/ru/ulstu/configuration/Constants.java b/src/main/java/ru/ulstu/configuration/Constants.java index 0a2268a..51806b6 100644 --- a/src/main/java/ru/ulstu/configuration/Constants.java +++ b/src/main/java/ru/ulstu/configuration/Constants.java @@ -5,7 +5,10 @@ public class Constants { public static final String MAIL_ACTIVATE = "Account activation"; public static final String MAIL_RESET = "Password reset"; + public static final String MAIL_INVITE = "Account registration"; + public static final int MIN_PASSWORD_LENGTH = 6; + public static final int MAX_PASSWORD_LENGTH = 32; public static final String LOGIN_REGEX = "^[_'.@A-Za-z0-9-]*$"; diff --git a/src/main/java/ru/ulstu/user/controller/UserController.java b/src/main/java/ru/ulstu/user/controller/UserController.java index d7db909..6806d19 100644 --- a/src/main/java/ru/ulstu/user/controller/UserController.java +++ b/src/main/java/ru/ulstu/user/controller/UserController.java @@ -141,13 +141,6 @@ public class UserController extends OdinController { return new Response<>(userService.activateUser(activationKey)); } - // TODO: add page for user edit (user-profile) - @PostMapping("/change-information") - public Response changeInformation(@Valid @RequestBody UserDto userDto) { - log.debug("REST: UserController.changeInformation( {} )", userDto.getLogin()); - return new Response<>(userService.updateUserInformation(userDto)); - } - // TODO: add page for user password change (user-profile) @PostMapping("/change-password") public Response changePassword(@Valid @RequestBody UserDto userDto) { diff --git a/src/main/java/ru/ulstu/user/controller/UserControllerV2.java b/src/main/java/ru/ulstu/user/controller/UserControllerV2.java new file mode 100644 index 0000000..eee98a1 --- /dev/null +++ b/src/main/java/ru/ulstu/user/controller/UserControllerV2.java @@ -0,0 +1,59 @@ +package ru.ulstu.user.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.ulstu.configuration.Constants; +import ru.ulstu.odin.controller.OdinController; +import ru.ulstu.user.error.UserSendingMailException; +import ru.ulstu.user.model.UserDto; +import ru.ulstu.user.model.User; +import ru.ulstu.user.model.UserListDto; +import ru.ulstu.user.service.UserService; +import ru.ulstu.user.service.UserSessionService; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +@Controller +@RequestMapping(value = "/users") +public class UserControllerV2 extends OdinController { + + private final Logger log = LoggerFactory.getLogger(UserControllerV2.class); + + private final UserService userService; + private final UserSessionService userSessionService; + + public UserControllerV2(UserService userService, + UserSessionService userSessionService) { + super(UserListDto.class, UserDto.class); + this.userService = userService; + this.userSessionService = userSessionService; + } + + @GetMapping("/profile") + public void getUserProfile(ModelMap modelMap, HttpServletRequest request) { + HttpSession session = request.getSession(false); + final String sessionId = session.getAttribute(Constants.SESSION_ID_ATTR).toString(); + modelMap.addAttribute("userDto", new UserDto(userSessionService.getUserBySessionId(sessionId))); + } + + @PostMapping("/profile") + public void updateUserProfile(ModelMap modelMap, HttpServletRequest request, UserDto userDto) { + HttpSession session = request.getSession(false); + final String sessionId = session.getAttribute(Constants.SESSION_ID_ATTR).toString(); + User user = userSessionService.getUserBySessionId(sessionId); + modelMap.addAttribute("userDto", userService.updateUserInformation(user, userDto)); + } + + @PostMapping("/invite") + public String inviteUser(@RequestParam(value = "email") String email) throws UserSendingMailException { + userService.inviteUser(email); + return "redirect:/"; + } +} diff --git a/src/main/java/ru/ulstu/user/error/UserSendingMailException.java b/src/main/java/ru/ulstu/user/error/UserSendingMailException.java new file mode 100644 index 0000000..576e834 --- /dev/null +++ b/src/main/java/ru/ulstu/user/error/UserSendingMailException.java @@ -0,0 +1,7 @@ +package ru.ulstu.user.error; + +public class UserSendingMailException extends RuntimeException { + public UserSendingMailException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/ulstu/user/service/MailService.java b/src/main/java/ru/ulstu/user/service/MailService.java index da1da6d..59d7e51 100644 --- a/src/main/java/ru/ulstu/user/service/MailService.java +++ b/src/main/java/ru/ulstu/user/service/MailService.java @@ -3,6 +3,7 @@ package ru.ulstu.user.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.mail.MailProperties; +import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.scheduling.annotation.Async; @@ -13,6 +14,7 @@ import ru.ulstu.configuration.ApplicationProperties; import ru.ulstu.configuration.Constants; import ru.ulstu.user.model.User; +import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.nio.charset.StandardCharsets; import java.util.Map; @@ -38,44 +40,65 @@ public class MailService { } @Async - public void sendEmail(String to, String subject, String content) { + public void sendEmail(String to, String subject, String content) throws MessagingException { log.debug("Send email to '{}' with subject '{}'", to, subject); MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper message = new MimeMessageHelper(mimeMessage, false, StandardCharsets.UTF_8.name()); + message.setTo(to); + message.setFrom(mailProperties.getUsername()); + message.setSubject(subject); + message.setText(content, true); + javaMailSender.send(mimeMessage); + log.debug("Sent email to User '{}'", to); + } + + @Async + public void sendEmailFromTemplate(User user, String templateName, String subject) { + Context context = new Context(); + context.setVariable(USER, user); + context.setVariable(BASE_URL, applicationProperties.getBaseUrl()); + String content = templateEngine.process(templateName, context); try { - MimeMessageHelper message = new MimeMessageHelper(mimeMessage, false, StandardCharsets.UTF_8.name()); - message.setTo(to); - message.setFrom(mailProperties.getUsername()); - message.setSubject(subject); - message.setText(content, true); - javaMailSender.send(mimeMessage); - log.debug("Sent email to User '{}'", to); - } catch (Exception e) { + sendEmail(user.getEmail(), subject, content); + } catch ( + Exception e) { if (log.isDebugEnabled()) { - log.warn("Email could not be sent to user '{}'", to, e); + log.warn("Email could not be sent to user '{}'", user.getEmail(), e); } else { - log.warn("Email could not be sent to user '{}': {}", to, e.getMessage()); + log.warn("Email could not be sent to user '{}': {}", user.getEmail(), e.getMessage()); } } + } + //Todo: выделить сервис нотификаций @Async - public void sendEmailFromTemplate(User user, String templateName, String subject) { + public void sendEmailFromTemplate(Map variables, User user, String templateName, String subject) { Context context = new Context(); + variables.entrySet().forEach(entry -> context.setVariable(entry.getKey(), entry.getValue())); context.setVariable(USER, user); context.setVariable(BASE_URL, applicationProperties.getBaseUrl()); String content = templateEngine.process(templateName, context); - sendEmail(user.getEmail(), subject, content); + try { + sendEmail(user.getEmail(), subject, content); + } catch ( + Exception e) { + if (log.isDebugEnabled()) { + log.warn("Email could not be sent to user '{}'", user.getEmail(), e); + } else { + log.warn("Email could not be sent to user '{}': {}", user.getEmail(), e.getMessage()); + } + } } - //Todo: выделить сервис нотификаций @Async - public void sendEmailFromTemplate(Map variables, User user, String templateName, String subject) { + public void sendEmailFromTemplate(Map variables, String templateName, String subject, String email) + throws MessagingException { Context context = new Context(); variables.entrySet().forEach(entry -> context.setVariable(entry.getKey(), entry.getValue())); - context.setVariable(USER, user); context.setVariable(BASE_URL, applicationProperties.getBaseUrl()); String content = templateEngine.process(templateName, context); - sendEmail(user.getEmail(), subject, content); + sendEmail(email, subject, content); } @Async @@ -87,4 +110,8 @@ public class MailService { public void sendPasswordResetMail(User user) { sendEmailFromTemplate(user, "passwordResetEmail", Constants.MAIL_RESET); } + + public void sendInviteMail(Map variables, String email) throws MessagingException { + sendEmailFromTemplate(variables, "userInviteEmail", Constants.MAIL_INVITE, email); + } } diff --git a/src/main/java/ru/ulstu/user/service/UserService.java b/src/main/java/ru/ulstu/user/service/UserService.java index c98e4b7..db20868 100644 --- a/src/main/java/ru/ulstu/user/service/UserService.java +++ b/src/main/java/ru/ulstu/user/service/UserService.java @@ -1,5 +1,6 @@ package ru.ulstu.user.service; +import com.google.common.collect.ImmutableMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; @@ -25,6 +26,7 @@ import ru.ulstu.user.error.UserNotActivatedException; import ru.ulstu.user.error.UserNotFoundException; import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException; import ru.ulstu.user.error.UserResetKeyError; +import ru.ulstu.user.error.UserSendingMailException; import ru.ulstu.user.model.User; import ru.ulstu.user.model.UserDto; import ru.ulstu.user.model.UserListDto; @@ -36,10 +38,12 @@ import ru.ulstu.user.repository.UserRepository; import ru.ulstu.user.repository.UserRoleRepository; import ru.ulstu.user.util.UserUtils; +import javax.mail.MessagingException; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -205,23 +209,10 @@ public class UserService implements UserDetailsService { return userMapper.userEntityToUserDto(user); } - public UserDto updateUserInformation(UserDto userDto) { - if (userDto.getId() == null) { - throw new EntityIdIsNullException(); - } - if (!Objects.equals( - Optional.ofNullable(getUserByEmail(userDto.getEmail())) - .map(BaseEntity::getId).orElse(userDto.getId()), - userDto.getId())) { - throw new UserEmailExistsException(userDto.getEmail()); - } - User user = userRepository.findOne(userDto.getId()); - if (user == null) { - throw new UserNotFoundException(userDto.getId().toString()); - } - user.setFirstName(userDto.getFirstName()); - user.setLastName(userDto.getLastName()); - user.setEmail(userDto.getEmail()); + public UserDto updateUserInformation(User user, UserDto updateUser) { + user.setFirstName(updateUser.getFirstName()); + user.setLastName(updateUser.getLastName()); + user.setEmail(updateUser.getEmail()); user = userRepository.save(user); log.debug("Updated Information for User: {}", user.getLogin()); return userMapper.userEntityToUserDto(user); @@ -328,4 +319,28 @@ public class UserService implements UserDetailsService { public List filterByAgeAndDegree(boolean hasDegree, boolean hasAge) { return userRepository.filterByAgeAndDegree(hasDegree, hasAge); } + + public void inviteUser(String email) throws UserSendingMailException { + if (userRepository.findOneByEmailIgnoreCase(email) != null) { + throw new UserEmailExistsException(email); + } + + String password = UserUtils.generatePassword(); + + User user = new User(); + user.setPassword(passwordEncoder.encode(password)); + user.setLogin(email); + user.setEmail(email); + user.setFirstName(""); + user.setLastName(""); + user.setActivated(true); + userRepository.save(user); + + Map variables = ImmutableMap.of("password", password, "email", email); + try { + mailService.sendInviteMail(variables, email); + } catch (MessagingException e) { + throw new UserSendingMailException(email); + } + } } diff --git a/src/main/java/ru/ulstu/user/service/UserSessionService.java b/src/main/java/ru/ulstu/user/service/UserSessionService.java index 0d985cd..ae289d0 100644 --- a/src/main/java/ru/ulstu/user/service/UserSessionService.java +++ b/src/main/java/ru/ulstu/user/service/UserSessionService.java @@ -54,4 +54,8 @@ public class UserSessionService { userSessionRepository.save(userSession); log.debug("User session {} closed", sessionId); } + + public User getUserBySessionId(String sessionId) { + return userSessionRepository.findOneBySessionId(sessionId).getUser(); + } } diff --git a/src/main/java/ru/ulstu/user/util/UserUtils.java b/src/main/java/ru/ulstu/user/util/UserUtils.java index de585a5..ec58dd9 100644 --- a/src/main/java/ru/ulstu/user/util/UserUtils.java +++ b/src/main/java/ru/ulstu/user/util/UserUtils.java @@ -5,6 +5,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; +import ru.ulstu.configuration.Constants; public class UserUtils { private static final int DEF_COUNT = 20; @@ -32,4 +33,8 @@ public class UserUtils { } return null; } + + public static String generatePassword() { + return RandomStringUtils.randomAscii(Constants.MIN_PASSWORD_LENGTH, Constants.MAX_PASSWORD_LENGTH); + } } diff --git a/src/main/resources/mail_templates/userInviteEmail.html b/src/main/resources/mail_templates/userInviteEmail.html new file mode 100644 index 0000000..180f0c5 --- /dev/null +++ b/src/main/resources/mail_templates/userInviteEmail.html @@ -0,0 +1,21 @@ + + + + Account activation + + + + +

+ Аккаунт в системе NG-Tracker был создан. + Данные для входа: + Логин - + Пароль - +

+

+ Regards, +
+ Balance Team. +

+ + diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 65e0be6..0c92865 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -61,13 +61,22 @@ - +