Browse Source

权限管理模块的用户认证页面

reghao 4 years ago
parent
commit
483a72945f

+ 32 - 18
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/UserController.java

@@ -1,16 +1,21 @@
 package cn.reghao.autodop.dmaster.auth.controller;
 
-import cn.reghao.autodop.dmaster.auth.db.UserCrud;
 import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.entity.User;
+import cn.reghao.autodop.dmaster.auth.entity.UserInfo;
+import cn.reghao.autodop.dmaster.auth.service.UserService;
 import cn.reghao.autodop.dmaster.utils.WebBody;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.http.MediaType;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author reghao
@@ -20,46 +25,55 @@ import java.util.List;
 @RequestMapping("/api/auth/user")
 @RestController
 public class UserController {
-    private UserCrud userCrud;
+    private UserService userService;
 
-    public UserController(UserCrud userCrud) {
-        this.userCrud = userCrud;
+    public UserController(UserService userService) {
+        this.userService = userService;
     }
 
-    @ApiOperation(value = "新增/修改用户")
+    @PreAuthorize("hasRole('ROLE_ADMIN')")
+    @ApiOperation(value = "创建用户")
     @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
-    public String addOrUpdateUser(User user) {
-        userCrud.addOrUpdate(user);
+    public String createUser(@Validated User user) {
+        userService.createUser(user);
         return WebBody.success();
     }
 
+    @ApiOperation(value = "修改用户信息")
+    @PostMapping(value = "/modify", produces = MediaType.APPLICATION_JSON_VALUE)
+    public String modifyUserInfo(@Validated UserInfo userInfo) {
+        userService.modifyUserInfo(userInfo);
+        return WebBody.success();
+    }
+
+    @PreAuthorize("hasRole('ROLE_ADMIN')")
     @ApiOperation(value = "删除用户")
     @DeleteMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String deleteUser(@PathVariable("id") User user) {
+    public String deleteUser(@PathVariable("id") Integer userId) {
+        userService.deleteUser(userId);
         return WebBody.success();
     }
 
     @ApiOperation(value = "修改用户密码")
     @PostMapping(value = "/passwd", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String modifyPassword(Integer id, String newPassword) {
+    public String modifyPassword(Integer userId, String newPassword) {
+        userService.modifyUserPassword(userId, newPassword);
         return WebBody.success();
     }
 
-    @ApiOperation(value = "给用户分配角色")
+    @ApiOperation(value = "分配用户角色")
     @PostMapping(value = "/role", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String assignRole(@RequestParam(value = "id") User user,
+    public String assignRole(@RequestParam(value = "id") Integer userId,
                              @RequestParam(value = "roleId", required = false) HashSet<Role> roles) {
-        userCrud.modifyUserRoles(user, roles);
+        userService.setUserRoles(userId, roles);
         return WebBody.success();
     }
 
     @ApiOperation(value = "启用/禁用用户")
-    @PostMapping(value = "/status/{var}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String setUserStatus(@PathVariable("var") String var,
-                                @RequestParam(value = "ids") List<User> users) {
-        if ("disable".equals(var)) {
-        } else {
-        }
+    @PostMapping(value = "/status/{enable}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public String setUserStatus(@PathVariable("enable") Boolean enable,
+                                @RequestParam(value = "ids") List<Integer> userIds) {
+        userIds.forEach(userId -> userService.setUserStatus(userId, enable));
         return WebBody.success();
     }
 }

+ 17 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/UserPageController.java

@@ -1,6 +1,7 @@
 package cn.reghao.autodop.dmaster.auth.controller;
 
 import cn.reghao.autodop.dmaster.auth.db.UserCrud;
+import cn.reghao.autodop.dmaster.auth.db.query.UserQuery;
 import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.entity.User;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
@@ -10,12 +11,12 @@ import cn.reghao.autodop.dmaster.utils.db.PageSort;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -27,18 +28,31 @@ import java.util.List;
 @RequestMapping("/auth/user")
 @Controller
 public class UserPageController {
+    private UserQuery userQuery;
     private UserCrud userCrud;
     private UserRepository userRepository;
     private RoleRepository roleRepository;
 
-    public UserPageController(UserCrud userCrud, RoleRepository roleRepository, UserRepository userRepository) {
+    public UserPageController(UserQuery userQuery, UserCrud userCrud,
+                              RoleRepository roleRepository, UserRepository userRepository) {
+        this.userQuery = userQuery;
         this.userCrud = userCrud;
         this.roleRepository = roleRepository;
         this.userRepository = userRepository;
     }
 
     @GetMapping
-    public String userPage(Model model) {
+    public String userPage(@RequestParam(value = "nickname", required = false) String nickname, Model model) {
+        if (nickname != null) {
+            List<User> list = userQuery.queryByMatchNickname(nickname);
+            Page<User> page = new PageImpl<>(list);
+            PageList<User> pageList = PageList.pageList(page);
+
+            model.addAttribute("page", page);
+            model.addAttribute("list", pageList.getList());
+            return "/auth/user/index";
+        }
+
         PageRequest pageRequest = PageSort.pageRequest();
         Page<User> userPage = userRepository.findAll(pageRequest);
         PageList<User> pageList = PageList.pageList(userPage);

+ 9 - 21
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/db/query/UserQuery.java

@@ -1,17 +1,12 @@
 package cn.reghao.autodop.dmaster.auth.db.query;
 
-import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.entity.User;
-import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
 import cn.reghao.autodop.dmaster.auth.repository.UserRepository;
 import org.springframework.data.jpa.domain.Specification;
-import org.springframework.security.core.GrantedAuthority;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
+import javax.persistence.criteria.Predicate;
 import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
 
 /**
  * @author reghao
@@ -20,24 +15,17 @@ import java.util.stream.Collectors;
 @Service
 public class UserQuery {
     private UserRepository userRepository;
-    private RoleRepository roleRepository;
 
-    public UserQuery(UserRepository userRepository, RoleRepository roleRepository) {
+    public UserQuery(UserRepository userRepository) {
         this.userRepository = userRepository;
-        this.roleRepository = roleRepository;
     }
 
-    public List<Role> getUserRoles(int userId) {
-        Optional<User> userOptional = userRepository.findById(userId);
-        if (userOptional.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        User userEntity = userOptional.get();
-        List<String> roles = userEntity.getAuthorities().stream()
-                .map(GrantedAuthority::getAuthority).collect(Collectors.toList());
-
-        Specification<Role> spec = ((root, query, criteriaBuilder) -> root.get("title").in(roles));
-        return roleRepository.findAll(spec);
+    public List<User> queryByMatchNickname(String nickname) {
+        Specification<User> specification = (root, query, cb) -> {
+            String likeQuery = String.format("%%%s%%", nickname);
+            Predicate predicate = cb.like(root.get("nickname"), likeQuery);
+            return cb.and(predicate);
+        };
+        return userRepository.findAll(specification);
     }
 }

+ 9 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/User.java

@@ -10,6 +10,7 @@ import org.springframework.security.core.userdetails.UserDetails;
 
 import javax.persistence.*;
 import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 import java.util.Collection;
 import java.util.Set;
 
@@ -36,14 +37,17 @@ public class User extends BaseEntity<Integer> implements UserDetails {
     private String salt;
     @ElementCollection(fetch = FetchType.EAGER)
     private Set<GrantedAuthorityImpl> authorities;
-    private int status;
-    private int locked;
+    @Transient
+    @NotNull(message = "用户角色不能为 NULL")
+    private Set<Role> roles;
+    private Boolean isEnabled;
+    private Boolean isLocked;
 
     @NotBlank(message = "标题不能为空白字符串")
     private String nickname;
     private String email;
     private String mobilePhone;
-    private int gender;
+    private Integer gender;
     private String avatarUrl;
 
     public User(String username, Set<GrantedAuthorityImpl> authorities) {
@@ -94,7 +98,7 @@ public class User extends BaseEntity<Integer> implements UserDetails {
      */
     @Override
     public boolean isEnabled() {
-        return status == 0;
+        return isEnabled;
     }
 
     /**
@@ -106,7 +110,7 @@ public class User extends BaseEntity<Integer> implements UserDetails {
      */
     @Override
     public boolean isAccountNonLocked() {
-        return locked == 0;
+        return isLocked;
     }
 
     /**

+ 1 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/UserInfo.java

@@ -8,6 +8,7 @@ import lombok.Data;
  */
 @Data
 public class UserInfo {
+    private Integer userId;
     private String nickname;
     private String email;
     private String mobilePhone;

+ 6 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/UserService.java

@@ -2,8 +2,9 @@ package cn.reghao.autodop.dmaster.auth.service;
 
 import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.entity.User;
+import cn.reghao.autodop.dmaster.auth.entity.UserInfo;
 
-import java.util.List;
+import java.util.Set;
 
 /**
  * @author reghao
@@ -12,7 +13,8 @@ import java.util.List;
 public interface UserService {
     void createUser(User user);
     void modifyUserPassword(Integer userId, String newPassword);
-    void modifyUserInfo(User user);
-    void setUserStatus(Integer userId, Integer status);
-    void setUserRoles(Integer userId, List<Role> roles);
+    void modifyUserInfo(UserInfo userInfo);
+    void setUserRoles(Integer userId, Set<Role> roles);
+    void setUserStatus(Integer userId, Boolean enable);
+    void deleteUser(Integer userId);
 }

+ 47 - 24
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/UserServiceImpl.java

@@ -3,14 +3,11 @@ package cn.reghao.autodop.dmaster.auth.service;
 import cn.reghao.autodop.common.utils.security.Cryptor;
 import cn.reghao.autodop.common.utils.security.Md5Cryptor;
 import cn.reghao.autodop.common.utils.security.Salt;
-import cn.reghao.autodop.dmaster.auth.db.RoleCrud;
-import cn.reghao.autodop.dmaster.auth.db.UserCrud;
 import cn.reghao.autodop.dmaster.auth.db.query.RoleQuery;
-import cn.reghao.autodop.dmaster.auth.db.query.UserQuery;
 import cn.reghao.autodop.dmaster.auth.entity.GrantedAuthorityImpl;
 import cn.reghao.autodop.dmaster.auth.entity.Role;
 import cn.reghao.autodop.dmaster.auth.entity.User;
-import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
+import cn.reghao.autodop.dmaster.auth.entity.UserInfo;
 import cn.reghao.autodop.dmaster.auth.repository.UserRepository;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.core.GrantedAuthority;
@@ -30,17 +27,12 @@ import java.util.stream.Collectors;
 @Service
 public class UserServiceImpl implements UserService {
     private UserRepository userRepository;
-    private RoleRepository roleRepository;
-    private UserQuery userQuery;
     private RoleQuery roleQuery;
     private Cryptor cryptor;
 
-    public UserServiceImpl(UserRepository userRepository, RoleRepository roleRepository,
-                           UserQuery userQuery, RoleQuery roleQuery)
+    public UserServiceImpl(UserRepository userRepository, RoleQuery roleQuery)
             throws NoSuchAlgorithmException {
         this.userRepository = userRepository;
-        this.roleRepository = roleRepository;
-        this.userQuery = userQuery;
         this.roleQuery = roleQuery;
         this.cryptor = new Md5Cryptor();
     }
@@ -54,6 +46,10 @@ public class UserServiceImpl implements UserService {
             return;
         }
 
+        Set<GrantedAuthorityImpl> authorities = user.getRoles().stream()
+                .map(role -> new GrantedAuthorityImpl(role.getTitle()))
+                .collect(Collectors.toSet());
+        user.setAuthorities(authorities);
         setEncryptPassword(user);
         user.setAvatarUrl("/imgs/avatar/default.png");
         userRepository.save(user);
@@ -69,10 +65,8 @@ public class UserServiceImpl implements UserService {
 
     @Override
     public void modifyUserPassword(Integer userId, String newPassword) {
-        Optional<User> userOptional = userRepository.findById(userId);
-        if (userOptional.isPresent()) {
-            User userEntity = userOptional.get();
-            userEntity.setPassword(newPassword);
+        User userEntity = getUser(userId);
+        if (userEntity != null) {
             setEncryptPassword(userEntity);
             userRepository.save(userEntity);
         } else {
@@ -81,23 +75,22 @@ public class UserServiceImpl implements UserService {
     }
 
     @Override
-    public void modifyUserInfo(User user) {
-
-    }
-
-    @Override
-    public void setUserStatus(Integer userId, Integer status) {
+    public void modifyUserInfo(UserInfo userInfo) {
+        User userEntity = getUser(userInfo.getUserId());
+        if (userEntity == null) {
+            log.error("用户不存在...");
+            return;
+        }
     }
 
     @Override
-    public void setUserRoles(Integer userId, List<Role> roles) {
-        Optional<User> userOptional = userRepository.findById(userId);
-        if (userOptional.isEmpty()) {
+    public void setUserRoles(Integer userId, Set<Role> roles) {
+        User userEntity = getUser(userId);
+        if (userEntity == null) {
             log.error("用户不存在...");
             return;
         }
 
-        User userEntity = userOptional.get();
         List<String> roleTitles = userEntity.getAuthorities().stream()
                 .map(GrantedAuthority::getAuthority).collect(Collectors.toList());
         if (roleTitles.isEmpty()) {
@@ -110,5 +103,35 @@ public class UserServiceImpl implements UserService {
         }
 
         List<Role> currentRoles = roleQuery.getUserRoles(roleTitles);
+        System.out.println();
+    }
+
+    @Override
+    public void setUserStatus(Integer userId, Boolean enable) {
+        User userEntity = getUser(userId);
+        if (userEntity == null) {
+            log.error("用户不存在...");
+            return;
+        }
+
+        userEntity.setIsEnabled(enable);
+        userRepository.save(userEntity);
+    }
+
+    @Override
+    public void deleteUser(Integer userId) {
+        User userEntity = getUser(userId);
+        if (userEntity != null) {
+            userRepository.delete(userEntity);
+        }
+    }
+
+    private User getUser(Integer userId) {
+        Optional<User> userOptional = userRepository.findById(userId);
+        if (userOptional.isEmpty()) {
+            return null;
+        }
+
+        return userOptional.get();
     }
 }

+ 1 - 1
dmaster/src/main/resources/templates/auth/menu/index.html

@@ -5,7 +5,7 @@
         <link rel="stylesheet" th:href="@{/lib/zTree_v3/css/zTreeStyle/zTreeStyle.css}" type="text/css">
     </head>
     <body class="timo-layout-page">
-        <div class="layui-card timo-tree" th:attr="data-url=@{'/auth/menu/list/' + ${status}}">
+        <div class="layui-card timo-tree" th:attr="data-url=@{'/api/auth/menu/list/' + ${status}}">
             <div class="layui-card-header timo-card-header">
                 <span>
                     <i class="fa fa-bars"></i>

+ 7 - 18
dmaster/src/main/resources/templates/auth/user/add.html

@@ -47,12 +47,17 @@
                     <i class="layui-anim layui-icon"></i>
                     <div>女</div>
                 </div>
+                <input type="radio" name="gender" value="3" title="未知">
+                <div class="layui-unselect layui-form-radio">
+                    <i class="layui-anim layui-icon"></i>
+                    <div>未知</div>
+                </div>
             </div>
         </div>
         <div class="layui-form-item">
-            <label class="layui-form-label">用户角色</label>
+            <label class="layui-form-label required">用户角色</label>
             <div class="layui-input-block">
-                <input th:each="item:${allRoles}" type="checkbox" name="roleId" th:title="${item.name}"
+                <input th:each="item:${allRoles}" type="checkbox" name="roles" th:title="${item.name}"
                        th:value="${item.id}" th:checked="${#sets.contains(userRoles, item)}" lay-skin="primary">
             </div>
         </div>
@@ -63,21 +68,5 @@
     </form>
 </div>
 <script th:replace="/common/template :: script"></script>
-<script type="text/javascript" th:src="@{/js/plugins/jquery-2.2.4.min.js}"></script>
-<script type="text/javascript">
-    var img = document.getElementById("img");
-    var passwd = document.getElementById("LAY-user-login-password");
-    function hideOrShow() {
-        if (passwd.type == "password") {
-            passwd.type = "text";
-             // 闭眼图片
-            img.src = "../layui/images/icon-invisible.png";
-        } else {
-            passwd.type = "password";
-             // 睁眼图片
-            img.src = "../layui/images/icon-visible.png";
-        }
-    }
-</script>
 </body>
 </html>

+ 4 - 10
dmaster/src/main/resources/templates/auth/user/detail.html

@@ -1,6 +1,5 @@
 <!DOCTYPE html>
-<html xmlns:th="http://www.thymeleaf.org"
-      xmlns:mo="https://gitee.com/aun/Timo">
+<html xmlns:th="http://www.thymeleaf.org">
 <head th:replace="/common/template :: header(~{::title},~{::link},~{::style})">
 </head>
 <body>
@@ -9,13 +8,13 @@
         <table class="layui-table timo-detail-table">
             <tbody>
             <tr>
-                <th width='100px'>用户编号</th>
+                <th width='100px'>用户 ID</th>
                 <td th:text="${user.id}"></td>
-                <th width='100px'>用户账号</th>
+                <th width='100px'>用户登录名</th>
                 <td th:text="${user.username}"></td>
             </tr>
             <tr>
-                <th>用户昵称</th>
+                <th>用户</th>
                 <td th:text="${user.nickname}"></td>
                 <th>用户性别</th>
                 <td th:text="${user.gender}"></td>
@@ -32,13 +31,8 @@
                 <th>最后修改</th>
                 <td th:text="${user.updateTime}"></td>
             </tr>
-            <tr>
-                <th>备注</th>
-                <td th:text="${user.remark}" colspan="4"></td>
-            </tr>
             </tbody>
         </table>
-
         <!--<div th:replace="/common/fragment :: log(${user})"></div>-->
     </div>
 <script th:replace="/common/template :: script"></script>

+ 1 - 1
dmaster/src/main/resources/templates/auth/user/edit.html

@@ -3,7 +3,7 @@
 <head th:replace="/common/template :: header(~{::title},~{::link},~{::style})"></head>
 <body>
 <div class="layui-form timo-compile">
-    <form th:action="@{/api/auth/user}">
+    <form th:action="@{/api/auth/user/modify}">
         <input type="hidden" name="id" th:value="${user.id}"/>
         <div class="layui-form-item">
             <label class="layui-form-label required">登录名</label>

+ 5 - 5
dmaster/src/main/resources/templates/auth/user/index.html

@@ -13,7 +13,7 @@
                 <div class="layui-inline">
                     <label class="layui-form-label">用户名</label>
                     <div class="layui-input-block">
-                        <input type="text" name="username" th:value="${param.username}" placeholder="请输入用户名"
+                        <input type="text" name="nickname" th:value="${param.nickname}" placeholder="请输入用户名"
                                autocomplete="off" class="layui-input">
                     </div>
                 </div>
@@ -32,8 +32,8 @@
                     <div class="btn-group">
                         <button class="layui-btn">启用/禁用<span class="caret"></span></button>
                         <dl class="layui-nav-child layui-anim layui-anim-upbit">
-                            <dd><a class="ajax-status" th:href="@{/api/auth/user/status/enable}">启用</a></dd>
-                            <dd><a class="ajax-status" th:href="@{/api/auth/user/status/disable}">禁用</a></dd>
+                            <dd><a class="ajax-status" th:href="@{/api/auth/user/status/1}">启用</a></dd>
+                            <dd><a class="ajax-status" th:href="@{/api/auth/user/status/0}">禁用</a></dd>
                         </dl>
                     </div>
                 </div>
@@ -85,8 +85,8 @@
                            data-size="640,480" href="#">编辑</a>
                         <a class="open-popup" data-title="详细信息" th:attr="data-url=@{'/auth/user/detail/'+${item.id}}"
                            data-size="640,480" href="#">详细</a>
-                        <a class="ajax-delete" th:attr="data-msg='确定要删除 '+${item.username}+'?'"+
-                           th:href="@{/auth/user/${item.id}}">删除</a>
+                        <a class="ajax-delete" th:attr="data-msg='确定要删除 '+ ${item.username} + '?'"
+                           th:href="@{'/api/auth/user/' + ${item.id}}">删除</a>
                     </td>
                 </tr>
                 </tbody>