diff --git a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java index 894cf39..5eb7220 100644 --- a/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java +++ b/src/main/java/ru/ulstu/configuration/SecurityConfiguration.java @@ -13,8 +13,10 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import ru.ulstu.core.model.AuthFailureHandler; import ru.ulstu.user.controller.UserController; import ru.ulstu.user.model.UserRoleConstants; import ru.ulstu.user.service.UserService; @@ -35,17 +37,20 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private final AuthenticationSuccessHandler authenticationSuccessHandler; private final LogoutSuccessHandler logoutSuccessHandler; private final ApplicationProperties applicationProperties; + private final AuthenticationFailureHandler authenticationFailureHandler; public SecurityConfiguration(UserService userService, BCryptPasswordEncoder bCryptPasswordEncoder, AuthenticationSuccessHandler authenticationSuccessHandler, LogoutSuccessHandler logoutSuccessHandler, - ApplicationProperties applicationProperties) { + ApplicationProperties applicationProperties, + AuthFailureHandler authenticationFailureHandler) { this.userService = userService; this.bCryptPasswordEncoder = bCryptPasswordEncoder; this.authenticationSuccessHandler = authenticationSuccessHandler; this.logoutSuccessHandler = logoutSuccessHandler; this.applicationProperties = applicationProperties; + this.authenticationFailureHandler = authenticationFailureHandler; } @Override @@ -66,6 +71,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { .antMatchers(UserController.ACTIVATE_URL).permitAll() .antMatchers(Constants.PASSWORD_RESET_REQUEST_PAGE).permitAll() .antMatchers(Constants.PASSWORD_RESET_PAGE).permitAll() + .antMatchers("/users/block").permitAll() .antMatchers(UserController.URL + UserController.REGISTER_URL).permitAll() .antMatchers(UserController.URL + UserController.ACTIVATE_URL).permitAll() .antMatchers(UserController.URL + UserController.PASSWORD_RESET_REQUEST_URL).permitAll() @@ -76,6 +82,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { .formLogin() .loginPage("/login") .successHandler(authenticationSuccessHandler) + .failureHandler(authenticationFailureHandler) .permitAll() .and() .logout() diff --git a/src/main/java/ru/ulstu/core/model/AuthFailureHandler.java b/src/main/java/ru/ulstu/core/model/AuthFailureHandler.java new file mode 100644 index 0000000..8b6bd9d --- /dev/null +++ b/src/main/java/ru/ulstu/core/model/AuthFailureHandler.java @@ -0,0 +1,21 @@ +package ru.ulstu.core.model; + +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; +import ru.ulstu.user.error.UserBlockedException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class AuthFailureHandler implements AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException ex) throws IOException { + if (ex.getClass() == UserBlockedException.class) { + response.sendRedirect("/users/block"); + } + } +} \ No newline at end of file diff --git a/src/main/java/ru/ulstu/user/controller/UserController.java b/src/main/java/ru/ulstu/user/controller/UserController.java index 3c4556d..d080d54 100644 --- a/src/main/java/ru/ulstu/user/controller/UserController.java +++ b/src/main/java/ru/ulstu/user/controller/UserController.java @@ -175,4 +175,9 @@ public class UserController extends OdinController { @RequestParam(value = "activity", required = false) String activity) { return new Response<>(userService.getActivitiesPings(userId, activity)); } + + @PostMapping("/block") + public void blockUser(@RequestParam("userId") Integer userId) { + userService.blockUser(userId); + } } diff --git a/src/main/java/ru/ulstu/user/controller/UserMvcController.java b/src/main/java/ru/ulstu/user/controller/UserMvcController.java index f0a28d8..bf84176 100644 --- a/src/main/java/ru/ulstu/user/controller/UserMvcController.java +++ b/src/main/java/ru/ulstu/user/controller/UserMvcController.java @@ -74,4 +74,8 @@ public class UserMvcController extends OdinController { @GetMapping("/pings") public void getPings() { } + + @GetMapping("/block") + public void getBlock() { + } } diff --git a/src/main/java/ru/ulstu/user/error/UserBlockedException.java b/src/main/java/ru/ulstu/user/error/UserBlockedException.java new file mode 100644 index 0000000..23b9b3a --- /dev/null +++ b/src/main/java/ru/ulstu/user/error/UserBlockedException.java @@ -0,0 +1,9 @@ +package ru.ulstu.user.error; + +import org.springframework.security.core.AuthenticationException; + +public class UserBlockedException extends AuthenticationException { + public UserBlockedException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/ulstu/user/model/User.java b/src/main/java/ru/ulstu/user/model/User.java index 520b439..bb76618 100644 --- a/src/main/java/ru/ulstu/user/model/User.java +++ b/src/main/java/ru/ulstu/user/model/User.java @@ -12,6 +12,7 @@ import javax.persistence.Enumerated; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; @@ -91,6 +92,10 @@ public class User extends BaseEntity { @Temporal(TemporalType.TIMESTAMP) private Date birthDate; + @ManyToOne() + @JoinColumn(name = "blocker_id") + private User blocker; + public enum UserDegree { CANDIDATE("Кандидат технических наук"), DOCTOR("Доктор технических наук"); @@ -229,6 +234,14 @@ public class User extends BaseEntity { this.degree = degree; } + public User getBlocker() { + return blocker; + } + + public void setBlocker(User blocker) { + this.blocker = blocker; + } + public String getUserAbbreviate() { return String.format(USER_ABBREVIATE_TEMPLATE, lastName == null ? "" : lastName, diff --git a/src/main/java/ru/ulstu/user/service/UserService.java b/src/main/java/ru/ulstu/user/service/UserService.java index b4f8f28..bbac124 100644 --- a/src/main/java/ru/ulstu/user/service/UserService.java +++ b/src/main/java/ru/ulstu/user/service/UserService.java @@ -21,12 +21,10 @@ import ru.ulstu.core.jpa.OffsetablePageRequest; import ru.ulstu.core.model.BaseEntity; import ru.ulstu.core.model.UserActivity; import ru.ulstu.core.model.response.PageableItems; -import ru.ulstu.grant.service.GrantService; -import ru.ulstu.paper.service.PaperService; import ru.ulstu.ping.model.Ping; import ru.ulstu.ping.service.PingService; -import ru.ulstu.project.service.ProjectService; import ru.ulstu.user.error.UserActivationError; +import ru.ulstu.user.error.UserBlockedException; import ru.ulstu.user.error.UserEmailExistsException; import ru.ulstu.user.error.UserIdExistsException; import ru.ulstu.user.error.UserIsUndeadException; @@ -323,6 +321,9 @@ public class UserService implements UserDetailsService { if (!user.getActivated()) { throw new UserNotActivatedException(); } + if (user.getBlocker() != null) { + throw new UserBlockedException(String.format("Вы заблокированы пользователем %s", user.getBlocker().getUserAbbreviate())); + } return new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), Optional.ofNullable(user.getRoles()).orElse(Collections.emptySet()).stream() @@ -424,4 +425,10 @@ public class UserService implements UserDetailsService { } return activitiesPings; } + + public void blockUser(int userId) { + User userToBlock = findById(userId); + userToBlock.setBlocker(getCurrentUser()); + userRepository.save(userToBlock); + } } diff --git a/src/main/resources/db/changelog-20190607_000002-schema.xml b/src/main/resources/db/changelog-20190607_000002-schema.xml new file mode 100644 index 0000000..9531c87 --- /dev/null +++ b/src/main/resources/db/changelog-20190607_000002-schema.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 3c79c6d..afcf8c9 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -53,4 +53,5 @@ + \ No newline at end of file diff --git a/src/main/resources/public/js/users.js b/src/main/resources/public/js/users.js index 0de86d6..0f8d1c0 100644 --- a/src/main/resources/public/js/users.js +++ b/src/main/resources/public/js/users.js @@ -120,6 +120,20 @@ function resetPassword() { }) } +function blockUser() { + userId = $('#userId').val(); + $.ajax({ + url:"/api/1.0/users/block?userId=" + userId, + contentType: "application/json; charset=utf-8", + method: "POST", + success: function() { + showFeedbackMessage("Пользователь заблокирован", MessageTypesEnum.SUCCESS) + }, + error: function(errorData) { + showFeedbackMessage(errorData.responseJSON.error.message, MessageTypesEnum.WARNING) + } + }) +} function isEmailValid(email) { re = /\S+@\S+\.\S+/; diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 32939e7..d3c49dd 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -109,6 +109,7 @@ +