diff --git a/src/main/java/ru/ulstu/configuration/Constants.java b/src/main/java/ru/ulstu/configuration/Constants.java index f910108..77a9a4d 100644 --- a/src/main/java/ru/ulstu/configuration/Constants.java +++ b/src/main/java/ru/ulstu/configuration/Constants.java @@ -21,4 +21,5 @@ public class Constants { public static final String PASSWORD_RESET_REQUEST_PAGE = "/resetRequest"; public static final String PASSWORD_RESET_PAGE = "/reset"; + public static final int RESET_KEY_LENGTH = 6; } \ No newline at end of file diff --git a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java index 591fa0c..894cf39 100644 --- a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java @@ -104,7 +104,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { .antMatchers("/css/**") .antMatchers("/js/**") .antMatchers("/templates/**") - .antMatchers("/webjars/**"); + .antMatchers("/webjars/**") + .antMatchers("/img/**"); } @Autowired diff --git a/src/main/java/ru/ulstu/core/controller/AdviceController.java b/src/main/java/ru/ulstu/core/controller/AdviceController.java index 27c9d5b..37078b9 100644 --- a/src/main/java/ru/ulstu/core/controller/AdviceController.java +++ b/src/main/java/ru/ulstu/core/controller/AdviceController.java @@ -34,11 +34,11 @@ public class AdviceController { public AdviceController(UserService userService) { this.userService = userService; } - - @ModelAttribute("currentUser") - public String getCurrentUser() { - return userService.getCurrentUser().getUserAbbreviate(); - } +// +// @ModelAttribute("currentUser") +// public String getCurrentUser() { +// return userService.getCurrentUser().getUserAbbreviate(); +// } @ModelAttribute("flashMessage") public String getFlashMessage() { diff --git a/src/main/java/ru/ulstu/core/model/ErrorConstants.java b/src/main/java/ru/ulstu/core/model/ErrorConstants.java index 55832f3..017725a 100644 --- a/src/main/java/ru/ulstu/core/model/ErrorConstants.java +++ b/src/main/java/ru/ulstu/core/model/ErrorConstants.java @@ -9,9 +9,9 @@ public enum ErrorConstants { USER_EMAIL_EXISTS(102, "Пользователь с таким почтовым ящиком уже существует"), USER_LOGIN_EXISTS(103, "Пользователь с таким логином уже существует"), USER_PASSWORDS_NOT_VALID_OR_NOT_MATCH(104, "Пароли введены неверно"), - USER_NOT_FOUND(105, "User is not found"), + USER_NOT_FOUND(105, "Аккаунт не найден"), USER_NOT_ACTIVATED(106, "User is not activated"), - USER_RESET_ERROR(107, "Invalid reset key"), + USER_RESET_ERROR(107, "Некорректный ключ подтверждения"), USER_UNDEAD_ERROR(108, "Can't edit/delete that user"), FILE_UPLOAD_ERROR(110, "File upload error"), USER_SENDING_MAIL_EXCEPTION(111, "Во время отправки приглашения пользователю произошла ошибка"); diff --git a/src/main/java/ru/ulstu/user/controller/UserController.java b/src/main/java/ru/ulstu/user/controller/UserController.java index 59e023b..c40ed8f 100644 --- a/src/main/java/ru/ulstu/user/controller/UserController.java +++ b/src/main/java/ru/ulstu/user/controller/UserController.java @@ -148,16 +148,15 @@ public class UserController extends OdinController { } @PostMapping(PASSWORD_RESET_REQUEST_URL) - public Response requestPasswordReset(@RequestParam("email") String email) { + public void requestPasswordReset(@RequestParam("email") String email) { log.debug("REST: UserController.requestPasswordReset( {} )", email); - return new Response<>(userService.requestUserPasswordReset(email)); + userService.requestUserPasswordReset(email); } @PostMapping(PASSWORD_RESET_URL) - public Response finishPasswordReset(@RequestParam("key") String key, - @RequestBody UserResetPasswordDto userResetPasswordDto) { - log.debug("REST: UserController.requestPasswordReset( {} )", key); - return new Response<>(userService.completeUserPasswordReset(key, userResetPasswordDto)); + public Response finishPasswordReset(@RequestBody UserResetPasswordDto userResetPasswordDto) { + log.debug("REST: UserController.requestPasswordReset( {} )", userResetPasswordDto.getResetKey()); + return new Response<>(userService.completeUserPasswordReset(userResetPasswordDto)); } @PostMapping("/changePassword") diff --git a/src/main/java/ru/ulstu/user/model/UserResetPasswordDto.java b/src/main/java/ru/ulstu/user/model/UserResetPasswordDto.java index 33d84bc..58e7462 100644 --- a/src/main/java/ru/ulstu/user/model/UserResetPasswordDto.java +++ b/src/main/java/ru/ulstu/user/model/UserResetPasswordDto.java @@ -14,6 +14,10 @@ public class UserResetPasswordDto { @Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50) private String passwordConfirm; + @NotEmpty + @Size(min = Constants.RESET_KEY_LENGTH) + private String resetKey; + public String getPassword() { return password; } @@ -25,4 +29,8 @@ public class UserResetPasswordDto { public boolean isPasswordsValid() { return Objects.equals(password, passwordConfirm); } + + public String getResetKey() { + return resetKey; + } } diff --git a/src/main/java/ru/ulstu/user/service/MailService.java b/src/main/java/ru/ulstu/user/service/MailService.java index ec91739..864b749 100644 --- a/src/main/java/ru/ulstu/user/service/MailService.java +++ b/src/main/java/ru/ulstu/user/service/MailService.java @@ -106,8 +106,7 @@ public class MailService { sendEmailFromTemplate(user, "activationEmail", Constants.MAIL_ACTIVATE); } - @Async - public void sendPasswordResetMail(User user) { + public void sendPasswordResetMail(User user) throws MessagingException, MailException { sendEmailFromTemplate(user, "passwordResetEmail", Constants.MAIL_RESET); } @@ -118,6 +117,5 @@ public class MailService { @Async public void sendChangePasswordMail(User user) { sendEmailFromTemplate(user, "passwordChangeEmail", Constants.MAIL_CHANGE_PASSWORD); - } } diff --git a/src/main/java/ru/ulstu/user/service/UserService.java b/src/main/java/ru/ulstu/user/service/UserService.java index c889caa..8089a8e 100644 --- a/src/main/java/ru/ulstu/user/service/UserService.java +++ b/src/main/java/ru/ulstu/user/service/UserService.java @@ -236,7 +236,7 @@ public class UserService implements UserDetailsService { mailService.sendChangePasswordMail(user); } - public boolean requestUserPasswordReset(String email) { + public boolean requestUserPasswordReset(String email) { User user = userRepository.findOneByEmailIgnoreCase(email); if (user == null) { throw new UserNotFoundException(email); @@ -247,23 +247,30 @@ public class UserService implements UserDetailsService { user.setResetKey(UserUtils.generateResetKey()); user.setResetDate(new Date()); user = userRepository.save(user); - mailService.sendPasswordResetMail(user); + try { + mailService.sendPasswordResetMail(user); + } catch (MessagingException | MailException e) { + throw new UserSendingMailException(email); + } log.debug("Created Reset Password Request for User: {}", user.getLogin()); return true; } - public boolean completeUserPasswordReset(String key, UserResetPasswordDto userResetPasswordDto) { + public boolean completeUserPasswordReset(UserResetPasswordDto userResetPasswordDto) { if (!userResetPasswordDto.isPasswordsValid()) { - throw new UserPasswordsNotValidOrNotMatchException(""); + throw new UserPasswordsNotValidOrNotMatchException("Пароли не совпадают"); } - User user = userRepository.findOneByResetKey(key); + User user = userRepository.findOneByResetKey(userResetPasswordDto.getResetKey()); if (user == null) { - throw new UserResetKeyError(key); + throw new UserResetKeyError(userResetPasswordDto.getResetKey()); } user.setPassword(passwordEncoder.encode(userResetPasswordDto.getPassword())); user.setResetKey(null); user.setResetDate(null); user = userRepository.save(user); + + mailService.sendChangePasswordMail(user); + log.debug("Reset Password for User: {}", user.getLogin()); return true; } diff --git a/src/main/resources/mail_templates/passwordResetEmail.html b/src/main/resources/mail_templates/passwordResetEmail.html index a1034d4..99e4f77 100644 --- a/src/main/resources/mail_templates/passwordResetEmail.html +++ b/src/main/resources/mail_templates/passwordResetEmail.html @@ -1,23 +1,19 @@ - Password reset + Восстановление пароля

- Dear Ivan Ivanov + Дорогой Ivan Ivanov

- For your account a password reset was requested, please click on the URL below to + Ваш ключ для восстановления пароля

- Reset Link -

-

- Regards, + С уважением,
Balance Team.

diff --git a/src/main/resources/public/css/base.css b/src/main/resources/public/css/base.css new file mode 100644 index 0000000..0c69e7c --- /dev/null +++ b/src/main/resources/public/css/base.css @@ -0,0 +1,3 @@ +.loader { + padding-left:50% +} \ No newline at end of file diff --git a/src/main/resources/public/img/main/ajax-loader.gif b/src/main/resources/public/img/main/ajax-loader.gif new file mode 100644 index 0000000..f2a1bc0 Binary files /dev/null and b/src/main/resources/public/img/main/ajax-loader.gif differ diff --git a/src/main/resources/public/js/users.js b/src/main/resources/public/js/users.js index 76bd41d..a49bdc6 100644 --- a/src/main/resources/public/js/users.js +++ b/src/main/resources/public/js/users.js @@ -35,10 +35,7 @@ function changePassword() { function inviteUser() { email = document.getElementById("email").value; - re = /\S+@\S+\.\S+/; - - - if (!re.test(email)) { + if (!isEmailValid(email)) { showFeedbackMessage("Некорректный почтовый ящик", MessageTypesEnum.WARNING); return; } @@ -55,4 +52,77 @@ function inviteUser() { showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING) } }) +} + +function requestResetPassword() { + email = document.getElementById("emailReset").value + + if (!isEmailValid(email)) { + showFeedbackMessage("Некорректный почтовый ящик", MessageTypesEnum.WARNING); + return; + } + document.getElementById("dvloader").hidden = false; + + $.ajax({ + url:"/api/1.0/users/password-reset-request?email=" + email, + contentType: "application/json; charset=utf-8", + method: "POST", + success: function() { + showFeedbackMessage("Проверочный код был отправлен на указанный почтовый ящик", MessageTypesEnum.SUCCESS) + document.getElementById("passwordNew").hidden = false + document.getElementById("passwordConfirm").hidden = false + document.getElementById("btnReset").hidden = false + document.getElementById("resetKey").hidden = false + document.getElementById("emailReset").hidden = true + document.getElementById("btnSend").hidden = true + document.getElementById("dvloader").hidden = true; + + }, + error: function(errorData) { + showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING) + document.getElementById("dvloader").hidden = true; + + } + }) + +} + +function resetPassword() { + passwordNew = document.getElementById("passwordNew").value; + passwordConfirm = document.getElementById("passwordConfirm").value; + resetKey = document.getElementById("resetKey").value; + + if ([passwordNew, passwordConfirm, resetKey].includes("")) { + showFeedbackMessage("Заполните все поля", MessageTypesEnum.WARNING); + return; + } + + if (passwordNew != passwordConfirm) { + showFeedbackMessage("Пароли не совпадают", MessageTypesEnum.WARNING); + return; + } + + $.ajax({ + url:"/api/1.0/users/password-reset", + contentType: "application/json; charset=utf-8", + method: "POST", + data: JSON.stringify({ + "password": passwordNew, + "passwordConfirm": passwordConfirm, + "resetKey": resetKey, + }), + success: function() { + showFeedbackMessage("Пользователь был успешно приглашен", MessageTypesEnum.SUCCESS) + window.location.href = "/login" + }, + error: function(errorData) { + showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING) + } + }) +} + + +function isEmailValid(email) { + re = /\S+@\S+\.\S+/; + return re.test(email) } \ No newline at end of file diff --git a/src/main/resources/templates/resetRequest.html b/src/main/resources/templates/resetRequest.html index 2adab37..73bff76 100644 --- a/src/main/resources/templates/resetRequest.html +++ b/src/main/resources/templates/resetRequest.html @@ -1,9 +1,10 @@ + layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml"> + + -
-
-
-
- -
- - -
-
-
- - - +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ + + + +
+
+
+ + \ No newline at end of file