diff --git a/src/main/java/com/ydool/common/constant/UrlConstant.java b/src/main/java/com/ydool/common/constant/UrlConstant.java index a380b5c..3770f09 100644 --- a/src/main/java/com/ydool/common/constant/UrlConstant.java +++ b/src/main/java/com/ydool/common/constant/UrlConstant.java @@ -21,6 +21,8 @@ public interface UrlConstant { String DICT_DATA = API + "/dict_data"; + String USER = API + "/user"; + String MENU = API + "/menu"; diff --git a/src/main/java/com/ydool/platform/saToken/config/StpInterfaceImpl.java b/src/main/java/com/ydool/platform/saToken/config/StpInterfaceImpl.java new file mode 100644 index 0000000..9d13f35 --- /dev/null +++ b/src/main/java/com/ydool/platform/saToken/config/StpInterfaceImpl.java @@ -0,0 +1,51 @@ +package com.ydool.platform.saToken.config; + +import cn.dev33.satoken.stp.StpInterface; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.ydool.system.entity.Menu; +import com.ydool.system.entity.Role; +import com.ydool.system.service.impl.UserServiceImpl; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 自定义权限验证接口扩展 + */ +@Component // 保证此类被SpringBoot扫描,完成Sa-Token的自定义权限验证扩展 +public class StpInterfaceImpl implements StpInterface { + + /** + * 返回一个账号所拥有的权限码集合 + */ + @Override + public List getPermissionList(Object loginId, String loginType) { + UserServiceImpl userService = SpringUtil.getBean(UserServiceImpl.class); + List list = new ArrayList(); + List menuList = userService.menusByUser((String) loginId); + if (CollUtil.isNotEmpty(menuList)) { + List perms = menuList.stream().map(Menu::getPerms).collect(Collectors.toList()); + list.addAll(perms); + } + return list; + } + + /** + * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验) + */ + @Override + public List getRoleList(Object loginId, String loginType) { + UserServiceImpl userService = SpringUtil.getBean(UserServiceImpl.class); + List list = new ArrayList(); + List roleList = userService.roleListByUser((String) loginId); + if (CollUtil.isNotEmpty(roleList)) { + List roleCodes = roleList.stream().map(Role::getCode).collect(Collectors.toList()); + list.addAll(roleCodes); + } + return list; + } + +} diff --git a/src/main/java/com/ydool/system/controller/AuthController.java b/src/main/java/com/ydool/system/controller/AuthController.java index 212744a..dfe6032 100644 --- a/src/main/java/com/ydool/system/controller/AuthController.java +++ b/src/main/java/com/ydool/system/controller/AuthController.java @@ -1,12 +1,12 @@ package com.ydool.system.controller; -import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport; import com.ydool.common.constant.UrlConstant; import com.ydool.common.data.dto.AjaxResult; import com.ydool.system.request.AuthRequest; +import com.ydool.system.request.EditPasswordRequest; +import com.ydool.system.request.NewPasswordRequest; import com.ydool.system.service.IAuthService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -23,6 +23,12 @@ public class AuthController { @Autowired private IAuthService authService; + /** + * 登录 + * + * @param authRequest + * @return + */ @PostMapping("login") @ApiOperation("登录") @ApiOperationSupport(order = 1) @@ -30,4 +36,44 @@ public class AuthController { return authService.login(authRequest.getUserName(), authRequest.getPassword()); } + /** + * 退出登录 + * + * @return + */ + @GetMapping("logout") + @ApiOperation("退出登录") + @ApiOperationSupport(order = 2) + public AjaxResult logout() { + return authService.logout(); + } + + + /** + * 修改密码 + * + * @param editPasswordRequest + * @return + */ + @PutMapping("editPassword") + @ApiOperation("修改密码") + @ApiOperationSupport(order = 3) + public AjaxResult editPassword(@RequestBody @Validated EditPasswordRequest editPasswordRequest) { + return authService.editPassword(editPasswordRequest.getOldPassword(), editPasswordRequest.getNewPassword()); + } + + /** + * 修改重置以后的密码 + * + * @param newPasswordRequest + * @return + */ + @PutMapping("newPassword") + @ApiOperation("修改重置以后的密码") + @ApiOperationSupport(order = 4) + public AjaxResult newPassword(@RequestBody @Validated NewPasswordRequest newPasswordRequest) { + return authService.newPassword(newPasswordRequest.getNewPassword()); + } + + } diff --git a/src/main/java/com/ydool/system/controller/ConfigController.java b/src/main/java/com/ydool/system/controller/ConfigController.java index 5dbd379..381dabe 100644 --- a/src/main/java/com/ydool/system/controller/ConfigController.java +++ b/src/main/java/com/ydool/system/controller/ConfigController.java @@ -63,7 +63,7 @@ public class ConfigController extends BaseController { /** * 参数详情 * - * @param id 参数Id + * @param id * @return */ @GetMapping(value = "detail") @@ -109,7 +109,7 @@ public class ConfigController extends BaseController { /** * 单个删除参数 * - * @param id 参数Id + * @param id * @return */ @DeleteMapping(value = "remove") @@ -123,7 +123,7 @@ public class ConfigController extends BaseController { /** * 批量删除参数 * - * @param ids 参数Id集合 + * @param ids * @return */ @PostMapping(value = "removeBatch") diff --git a/src/main/java/com/ydool/system/controller/RoleController.java b/src/main/java/com/ydool/system/controller/RoleController.java index 5d6eea9..e81e7d6 100644 --- a/src/main/java/com/ydool/system/controller/RoleController.java +++ b/src/main/java/com/ydool/system/controller/RoleController.java @@ -7,7 +7,6 @@ import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters; import com.ydool.common.base.BaseController; import com.ydool.common.constant.UrlConstant; import com.ydool.common.data.dto.AjaxResult; -import com.ydool.system.entity.Config; import com.ydool.system.entity.Role; import com.ydool.system.request.IdsRequest; import com.ydool.system.request.RoleMenuRequest; @@ -68,7 +67,7 @@ public class RoleController extends BaseController { /** * 角色详情 * - * @param id 参数Id + * @param id * @return */ @GetMapping(value = "detail") @@ -114,7 +113,7 @@ public class RoleController extends BaseController { /** * 单个删除角色 * - * @param id 角色Id + * @param id * @return */ @DeleteMapping(value = "remove") @@ -128,13 +127,13 @@ public class RoleController extends BaseController { /** * 批量删除角色 * - * @param ids 角色Id集合 + * @param ids * @return */ @PostMapping(value = "removeBatch") @ApiOperation(value = "批量删除角色") @ApiOperationSupport(order = 6) - public AjaxResult removeConfigs(@RequestBody @Validated IdsRequest ids) { + public AjaxResult removeRoles(@RequestBody @Validated IdsRequest ids) { return roleService.removeRoles(ids); } @@ -158,6 +157,7 @@ public class RoleController extends BaseController { /** * 权限分配 + * * @param roleMenuRequest * @return */ @@ -168,4 +168,20 @@ public class RoleController extends BaseController { return roleService.editRoleMenu(roleMenuRequest); } + /** + * 角色列表下拉框 + * + * @return + */ + @GetMapping(value = "roles") + @ApiOperation(value = "角色列表下拉框") + @ApiOperationSupport( + responses = @DynamicResponseParameters(properties = { + @DynamicParameter(name = "data", dataTypeClass = Role.class) + }), order = 9 + ) + public AjaxResult roles() { + return roleService.roles(); + } + } diff --git a/src/main/java/com/ydool/system/controller/UserController.java b/src/main/java/com/ydool/system/controller/UserController.java new file mode 100644 index 0000000..12f898d --- /dev/null +++ b/src/main/java/com/ydool/system/controller/UserController.java @@ -0,0 +1,190 @@ +package com.ydool.system.controller; + +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import com.github.xiaoymin.knife4j.annotations.DynamicParameter; +import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters; +import com.ydool.common.base.BaseController; +import com.ydool.common.constant.UrlConstant; +import com.ydool.common.data.dto.AjaxResult; +import com.ydool.system.dto.UserDto; +import com.ydool.system.request.IdsRequest; +import com.ydool.system.request.UserRequest; +import com.ydool.system.request.UserRolesRequest; +import com.ydool.system.service.IUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +@RestController +@RequestMapping(UrlConstant.USER) +@Api(tags = "用户", value = "用户") +@ApiSupport(order = 9) +public class UserController extends BaseController { + @Autowired + private IUserService userService; + + /** + * 用户列表 + * + * @param value + * @param column + * @param orderBy + * @param status + * @param role + * @param dept + * @return + */ + @GetMapping(value = "list") + @ApiOperation(value = "用户列表") + @ApiImplicitParams({ + @ApiImplicitParam(name = "current", value = "当前页", dataType = "Integer"), + @ApiImplicitParam(name = "size", value = "每页条数", dataType = "Integer"), + @ApiImplicitParam(name = "value", value = "搜索框中的内容(只支持字符串类型)"), + @ApiImplicitParam(name = "column", value = "排序字段 字段名"), + @ApiImplicitParam(name = "orderBy", value = "排序顺序 降序:desc,升序:asc"), + @ApiImplicitParam(name = "status", value = "启用状态", dataType = "Boolean"), + @ApiImplicitParam(name = "role", value = "角色"), + @ApiImplicitParam(name = "dept", value = "部门"), + }) + @ApiOperationSupport( + responses = @DynamicResponseParameters(properties = { + @DynamicParameter(name = "data", dataTypeClass = UserDto.class) + }), + order = 1 + ) + public AjaxResult userList(String value, + String column, + String orderBy, + Boolean status, + String role, + String dept + ) { + return userService.userList(getPage(), value, column, orderBy, status, role, dept); + } + + /** + * 用户详情 + * + * @param id + * @return + */ + @GetMapping(value = "detail") + @ApiOperation(value = "用户详情") + @ApiOperationSupport( + responses = @DynamicResponseParameters(properties = { + @DynamicParameter(name = "data", dataTypeClass = UserDto.class) + }), order = 2 + ) + @ApiImplicitParam(name = "id", value = "用户Id") + public AjaxResult userDetail(String id) { + return userService.userDetail(id); + } + + /** + * 保存用户 + * + * @param userRequest + * @return + */ + @PostMapping(value = "save") + @ApiOperation(value = "保存角色") + @ApiOperationSupport(order = 3) + public AjaxResult saveUser(@RequestBody @Validated UserRequest userRequest) { + return userService.saveUser(userRequest); + } + + /** + * 编辑用户 + * + * @param id + * @param userRequest + * @return + */ + @PutMapping(value = "edit") + @ApiOperation(value = "编辑用户") + @ApiImplicitParam(name = "id", value = "用户Id") + @ApiOperationSupport(order = 4) + public AjaxResult editUser(String id, @RequestBody @Validated UserRequest userRequest) { + return userService.editUser(id, userRequest); + } + + /** + * 单个用户 + * + * @param id + * @return + */ + @DeleteMapping(value = "remove") + @ApiOperation(value = "删除用户") + @ApiImplicitParam(name = "id", value = "用户Id") + @ApiOperationSupport(order = 5) + public AjaxResult removeUser(String id) { + return userService.removeUser(id); + } + + /** + * 批量删除用户 + * + * @param ids 用户Id集合 + * @return + */ + @PostMapping(value = "removeBatch") + @ApiOperation(value = "批量删除用户") + @ApiOperationSupport(order = 6) + public AjaxResult removeUsers(@RequestBody @Validated IdsRequest ids) { + return userService.removeUsers(ids); + } + + /** + * 重置密码 + * + * @param id + * @return + */ + @PutMapping(value = "resetPassword") + @ApiOperation(value = "重置密码") + @ApiImplicitParam(name = "id", value = "用户Id") + @ApiOperationSupport(order = 7) + public AjaxResult resetPassword(String id) { + return userService.resetPassword(id); + } + + /** + * 获取用户所拥有的角色 + * + * @param id + * @return + */ + @GetMapping(value = "rolesByUser") + @ApiOperation(value = "获取用户所拥有的角色") + @ApiImplicitParam(name = "id", value = "用户Id") + @ApiOperationSupport( + responses = @DynamicResponseParameters(properties = { + @DynamicParameter(name = "data", dataTypeClass = List.class) + }), order = 8 + ) + public AjaxResult rolesByUser(String id) { + return userService.rolesByUser(id); + } + + /** + * 分配角色 + * + * @param userRolesRequest + * @return + */ + @PutMapping(value = "editUserRoles") + @ApiOperation(value = "分配角色") + @ApiOperationSupport(order = 9) + public AjaxResult editUserRoles(UserRolesRequest userRolesRequest) { + return userService.editUserRoles(userRolesRequest); + } +} diff --git a/src/main/java/com/ydool/system/dto/UserDto.java b/src/main/java/com/ydool/system/dto/UserDto.java new file mode 100644 index 0000000..14dbf7b --- /dev/null +++ b/src/main/java/com/ydool/system/dto/UserDto.java @@ -0,0 +1,15 @@ +package com.ydool.system.dto; + +import com.ydool.system.entity.User; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class UserDto extends User { + @ApiModelProperty(value = "部门名称") + private String deptName; + + + @ApiModelProperty(value = "角色名称") + private String rolesName; +} diff --git a/src/main/java/com/ydool/system/entity/User.java b/src/main/java/com/ydool/system/entity/User.java index 9d9bc2a..378d3f3 100644 --- a/src/main/java/com/ydool/system/entity/User.java +++ b/src/main/java/com/ydool/system/entity/User.java @@ -36,6 +36,12 @@ public class User extends BaseEntity{ @ApiModelProperty(value = "用户昵称") private String userName; + @ApiModelProperty(value = "部门") + private String dept; + + @ApiModelProperty(value = "角色") + private String roles; + @ApiModelProperty(value = "手机号码") private String phone; diff --git a/src/main/java/com/ydool/system/request/EditPasswordRequest.java b/src/main/java/com/ydool/system/request/EditPasswordRequest.java new file mode 100644 index 0000000..4e7ace2 --- /dev/null +++ b/src/main/java/com/ydool/system/request/EditPasswordRequest.java @@ -0,0 +1,17 @@ +package com.ydool.system.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class EditPasswordRequest { + @ApiModelProperty(value = "旧密码") + @NotBlank(message = "旧密码不能为空") + String oldPassword; + + @ApiModelProperty(value = "新密码") + @NotBlank(message = "新密码不能为空") + String newPassword; +} diff --git a/src/main/java/com/ydool/system/request/NewPasswordRequest.java b/src/main/java/com/ydool/system/request/NewPasswordRequest.java new file mode 100644 index 0000000..ad7b108 --- /dev/null +++ b/src/main/java/com/ydool/system/request/NewPasswordRequest.java @@ -0,0 +1,13 @@ +package com.ydool.system.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class NewPasswordRequest { + @ApiModelProperty(value = "新密码") + @NotBlank(message = "新密码不能为空") + String newPassword; +} diff --git a/src/main/java/com/ydool/system/request/UserRequest.java b/src/main/java/com/ydool/system/request/UserRequest.java new file mode 100644 index 0000000..f2cb8bf --- /dev/null +++ b/src/main/java/com/ydool/system/request/UserRequest.java @@ -0,0 +1,39 @@ +package com.ydool.system.request; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NonNull; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@Data +public class UserRequest { + @ApiModelProperty(value = "登录账号") + @NotBlank(message = "登录账号不能为空") + private String loginName; + + @ApiModelProperty(value = "用户昵称") + @NotBlank(message = "用户昵称不能为空") + private String userName; + + @ApiModelProperty(value = "部门") + @NotBlank(message = "部门不能为空") + private String dept; + + @ApiModelProperty(value = "角色") + @NotBlank(message = "角色不能为空") + private String roles; + + @ApiModelProperty(value = "手机号码") + @NotBlank(message = "手机号码不能为空") + private String phone; + + @ApiModelProperty(value = "帐号状态(0正常 1停用)") + @NotNull(message = "帐号状态不能为空") + private Boolean status; + + @ApiModelProperty(value = "备注") + private String remarks; +} diff --git a/src/main/java/com/ydool/system/request/UserRolesRequest.java b/src/main/java/com/ydool/system/request/UserRolesRequest.java new file mode 100644 index 0000000..748d8ad --- /dev/null +++ b/src/main/java/com/ydool/system/request/UserRolesRequest.java @@ -0,0 +1,15 @@ +package com.ydool.system.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +public class UserRolesRequest { + @ApiModelProperty(value = "用户Id") + @NotBlank(message = "用户Id不能为空") + private String userId; + @ApiModelProperty(value = "角色Id集合字符串") + private String roleIds; +} diff --git a/src/main/java/com/ydool/system/service/IAuthService.java b/src/main/java/com/ydool/system/service/IAuthService.java index bcf9804..1254d02 100644 --- a/src/main/java/com/ydool/system/service/IAuthService.java +++ b/src/main/java/com/ydool/system/service/IAuthService.java @@ -10,4 +10,25 @@ public interface IAuthService { * @return */ AjaxResult login(String userName, String password); + + /** + * 登出 + * @return + */ + AjaxResult logout(); + + /** + * 修改密码 + * @param oldPassword + * @param newPassword + * @return + */ + AjaxResult editPassword(String oldPassword,String newPassword); + + /** + * 修改重置以后的密码 + * @param newPassword + * @return + */ + AjaxResult newPassword(String newPassword); } diff --git a/src/main/java/com/ydool/system/service/IDictDataService.java b/src/main/java/com/ydool/system/service/IDictDataService.java index 5e9389b..e42a461 100644 --- a/src/main/java/com/ydool/system/service/IDictDataService.java +++ b/src/main/java/com/ydool/system/service/IDictDataService.java @@ -73,5 +73,7 @@ public interface IDictDataService { */ AjaxResult dictDataByDictType(String dataType); + + } diff --git a/src/main/java/com/ydool/system/service/IRoleService.java b/src/main/java/com/ydool/system/service/IRoleService.java index ea9fbe0..8d056c9 100644 --- a/src/main/java/com/ydool/system/service/IRoleService.java +++ b/src/main/java/com/ydool/system/service/IRoleService.java @@ -82,6 +82,13 @@ public interface IRoleService { AjaxResult editRoleMenu(RoleMenuRequest roleMenuRequest); + /** + * 角色列表 + * @return + */ + AjaxResult roles(); + + } diff --git a/src/main/java/com/ydool/system/service/IUserService.java b/src/main/java/com/ydool/system/service/IUserService.java index 6349d06..4fa037d 100644 --- a/src/main/java/com/ydool/system/service/IUserService.java +++ b/src/main/java/com/ydool/system/service/IUserService.java @@ -1,5 +1,15 @@ package com.ydool.system.service; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ydool.common.data.dto.AjaxResult; +import com.ydool.system.entity.Menu; +import com.ydool.system.entity.Role; +import com.ydool.system.request.IdsRequest; +import com.ydool.system.request.UserRequest; +import com.ydool.system.request.UserRolesRequest; + +import java.util.List; + /** *

* 系统账号表 服务类 @@ -9,6 +19,105 @@ package com.ydool.system.service; * @since 2023-01-05 */ public interface IUserService { + /** + * 添加用户 + * + * @param userRequest + * @return + */ + AjaxResult saveUser(UserRequest userRequest); + + /** + * 编辑用户 + * + * @param id + * @param userRequest + * @return + */ + AjaxResult editUser(String id, UserRequest userRequest); + + /** + * 删除用户 + * + * @param id + * @return + */ + AjaxResult removeUser(String id); + + + /** + * 批量删除用户 + * + * @param ids + * @return + */ + AjaxResult removeUsers(IdsRequest ids); + + + /** + * 用户详情 + * + * @param id + * @return + */ + AjaxResult userDetail(String id); + + /** + * 用户列表 + * + * @param page + * @param value + * @param column + * @param orderBy + * @param status + * @param role + * @param dept + * @return + */ + AjaxResult userList(Page page, String value, String column, String orderBy, Boolean status, String role, + String dept); + + /** + * 重置密码 + * @param id + * @return + */ + AjaxResult resetPassword(String id); + + /** + * 获取用户所拥有的角色 + * @param id + * @return + */ + AjaxResult rolesByUser(String id); + + /** + * 分配角色 + * @param userRolesRequest + * @return + */ + AjaxResult editUserRoles(UserRolesRequest userRolesRequest); + + /** + * 获取拥有的角色 + * @param id + * @return + */ + List roleListByUser(String id); + + /** + * 获取菜单树 + * @param id + * @return + */ + List

menuTreesByUser(String id); + + /** + * 获取菜单 + * @param id + * @return + */ + List menusByUser(String id); } diff --git a/src/main/java/com/ydool/system/service/impl/AuthServiceImpl.java b/src/main/java/com/ydool/system/service/impl/AuthServiceImpl.java index bde9900..219950d 100644 --- a/src/main/java/com/ydool/system/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/AuthServiceImpl.java @@ -2,31 +2,44 @@ package com.ydool.system.service.impl; import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ydool.common.base.BaseService; -import com.ydool.common.constant.UrlConstant; +import com.ydool.common.cache.ConfigCache; import com.ydool.common.data.dto.AjaxResult; import com.ydool.common.utils.HttpServletUtil; import com.ydool.common.utils.PasswordUtil; -import com.ydool.common.utils.RsaUtil; +import com.ydool.system.entity.Menu; +import com.ydool.system.entity.Role; import com.ydool.system.entity.User; import com.ydool.system.mapper.UserMapper; import com.ydool.system.service.IAuthService; +import com.ydool.system.service.IUserService; import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; @Service public class AuthServiceImpl extends BaseService implements IAuthService { @Value("${sa-token.token-prefix}") private String tokenPrefix; + @Autowired + private IUserService userService; + + /** * 登录接口 * @@ -53,6 +66,13 @@ public class AuthServiceImpl extends BaseService implements IA //判断账号是否停用 if (loginUser.getStatus()) return AjaxResult.fail("当前账号已被停用,请联系管理员"); + //判断账号角色 + if (StrUtil.isBlank(loginUser.getRoles())) return AjaxResult.fail("该用户没有对应的角色,无法登陆系统"); + + List roleList = userService.roleListByUser(loginUser.getId()); + if (CollUtil.isEmpty(roleList)) return AjaxResult.fail("该用户没有对应的角色或角色已被删除或禁用,无法登陆系统"); + + loginUser.setLoginDate(LocalDateTime.now()); loginUser.setLoginIp(HttpServletUtil.getRemoteAddress()); @@ -66,13 +86,84 @@ public class AuthServiceImpl extends BaseService implements IA SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); Dict result = Dict.create(); result.set("tokenName", tokenInfo.getTokenName()); - result.set("tokenPrefix",tokenPrefix); + result.set("tokenPrefix", tokenPrefix); result.set("tokenValue", tokenInfo.getTokenValue()); result.set("name", loginUser.getUserName()); + + //获取菜单和权限标识 + List menus = userService.menuTreesByUser(loginUser.getId()); + result.set("menus", menus); + + + List perms = new ArrayList(); + List menuList = userService.menusByUser(StpUtil.getLoginIdAsString()); + if (CollUtil.isNotEmpty(menuList)) { + perms = menuList.stream().map(Menu::getPerms).collect(Collectors.toList()); + } + result.set("perms", perms); + + //是否需要强制修改密码 + result.set("need_init_password", password.equals(ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD, + "888888")) ? true : false); return AjaxResult.ok().data(result); - }else { + } else { StpUtil.logout(); } - return AjaxResult.fail("登陆失败"); + return AjaxResult.fail("登录失败"); } + + /** + * 登出 + * + * @return + */ + @Override + public AjaxResult logout() { + StpUtil.logout(); + return AjaxResult.ok().msg("退出成功"); + } + + /** + * 修改密码 + * + * @param oldPassword + * @param newPassword + * @return + */ + @Override + public AjaxResult editPassword(String oldPassword, String newPassword) { + if (!PasswordUtil.valid(newPassword)) return AjaxResult.fail("密码需由长度不小于6位的英文、数字及特殊符号组成"); + String loginId = StpUtil.getLoginIdAsString(); + User user = getById(loginId); + if (!user.getPassword().equals(PasswordUtil.password(user.getSalt(), oldPassword))) return AjaxResult.fail( + "旧密码错误"); + if (oldPassword.equals(newPassword)) return AjaxResult.fail("新旧密码不能相同"); + String salt = RandomUtil.randomString(6); + String password = PasswordUtil.password(salt, newPassword); + user.setSalt(salt).setPassword(password); + user.setLastUpdatePwd(LocalDateTime.now()); + boolean flag = updateById(user); + return flag ? AjaxResult.ok().msg("修改密码成功") : AjaxResult.fail("修改密码失败"); + } + + /** + * 修改重置以后的密码 + * + * @param newPassword + * @return + */ + @Override + public AjaxResult newPassword(String newPassword) { + if (!PasswordUtil.valid(newPassword)) return AjaxResult.fail("密码需由长度不小于6位的英文、数字及特殊符号组成"); + String loginId = StpUtil.getLoginIdAsString(); + String salt = RandomUtil.randomString(6); + String password = PasswordUtil.password(salt, newPassword); + User user = getById(loginId); + user.setLastUpdatePwd(LocalDateTime.now()); + user.setSalt(salt).setPassword(password); + boolean flag = updateById(user); + return flag ? AjaxResult.ok().msg("修改密码成功") : AjaxResult.fail("修改密码失败"); + } + + } diff --git a/src/main/java/com/ydool/system/service/impl/DeptServiceImpl.java b/src/main/java/com/ydool/system/service/impl/DeptServiceImpl.java index a1baa00..8fa3196 100644 --- a/src/main/java/com/ydool/system/service/impl/DeptServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/DeptServiceImpl.java @@ -203,6 +203,7 @@ public class DeptServiceImpl extends BaseTreeService implement .last("limit 1") ); if (ObjectUtil.isNotNull(dept)) return "部门编码不能重复"; + if (StrUtil.isNotBlank(id) && id.equals(deptRequest.getPid())) return "上级部门不能选择自己"; return null; } } diff --git a/src/main/java/com/ydool/system/service/impl/MenuServiceImpl.java b/src/main/java/com/ydool/system/service/impl/MenuServiceImpl.java index 5fcbfab..7ff862c 100644 --- a/src/main/java/com/ydool/system/service/impl/MenuServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/MenuServiceImpl.java @@ -236,7 +236,11 @@ public class MenuServiceImpl extends BaseTreeService implement ); if (ObjectUtil.isNotNull(menu)) return "权限字符不能重复"; + + if (StrUtil.isNotBlank(id) && id.equals(menuRequest.getPid())) return "上级菜单不能选择自己"; + return null; } + } diff --git a/src/main/java/com/ydool/system/service/impl/RoleServiceImpl.java b/src/main/java/com/ydool/system/service/impl/RoleServiceImpl.java index 3736251..51eba4f 100644 --- a/src/main/java/com/ydool/system/service/impl/RoleServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/RoleServiceImpl.java @@ -10,13 +10,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ydool.common.base.BaseService; import com.ydool.common.data.dto.AjaxResult; import com.ydool.system.entity.Role; -import com.ydool.system.mapper.MenuMapper; import com.ydool.system.mapper.RoleMapper; import com.ydool.system.request.IdsRequest; import com.ydool.system.request.RoleMenuRequest; import com.ydool.system.request.RoleRequest; import com.ydool.system.service.IRoleService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Arrays; @@ -33,9 +31,6 @@ import java.util.List; @Service public class RoleServiceImpl extends BaseService implements IRoleService { - @Autowired - private MenuMapper menuMapper; - /** * 保存角色 * @@ -183,6 +178,19 @@ public class RoleServiceImpl extends BaseService implements IR return flag ? AjaxResult.ok().msg("权限分配成功") : AjaxResult.fail("权限分配失败"); } + /** + * 角色列表 + * + * @return + */ + @Override + public AjaxResult roles() { + QueryWrapper qw = new QueryWrapper(); + qw.lambda().eq(Role::getStatus, true).orderByAsc(Role::getSortNo); + List roleList = list(qw); + return AjaxResult.ok().data(roleList); + } + /** * 校验角色 * diff --git a/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java b/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java index 6fac183..9e61553 100644 --- a/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java +++ b/src/main/java/com/ydool/system/service/impl/UserServiceImpl.java @@ -1,11 +1,37 @@ package com.ydool.system.service.impl; -import com.ydool.system.entity.User; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ydool.common.base.BaseService; +import com.ydool.common.cache.ConfigCache; +import com.ydool.common.data.dto.AjaxResult; +import com.ydool.common.utils.CodecUtils; +import com.ydool.common.utils.PasswordUtil; +import com.ydool.common.utils.TreeMapUtil; +import com.ydool.system.entity.Menu; +import com.ydool.system.entity.Role; +import com.ydool.system.entity.User; import com.ydool.system.mapper.UserMapper; +import com.ydool.system.request.IdsRequest; +import com.ydool.system.request.UserRequest; +import com.ydool.system.request.UserRolesRequest; import com.ydool.system.service.IUserService; +import com.ydool.system.wrapper.UserWrapper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + /** *

* 系统账号表 服务类 @@ -17,5 +43,330 @@ import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends BaseService implements IUserService { + @Autowired + private RoleServiceImpl roleService; + + @Autowired + private MenuServiceImpl menuService; + + /** + * 添加用户 + * + * @param userRequest + * @return + */ + @Override + public AjaxResult saveUser(UserRequest userRequest) { + String message = checkUser("", userRequest); + if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message); + User user = BeanUtil.copyProperties(userRequest, User.class); + + user.setPhone(CodecUtils.encrypt(user.getPhone())); + + String initPassword = ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD, "888888"); + user.setSalt(RandomUtil.randomString(6)); + user.setPassword(PasswordUtil.password(user.getSalt(), initPassword)); + user.setLastUpdatePwd(LocalDateTime.now()); + + boolean flag = save(user); + return flag ? AjaxResult.ok().msg("保存成功") : AjaxResult.fail("保存失败"); + } + + /** + * 编辑用户 + * + * @param id + * @param userRequest + * @return + */ + @Override + public AjaxResult editUser(String id, UserRequest userRequest) { + if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空"); + String message = checkUser(id, userRequest); + if (StrUtil.isNotBlank(message)) return AjaxResult.fail(message); + User user = getById(id); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在"); + BeanUtil.copyProperties(userRequest, user); + user.setPhone(CodecUtils.encrypt(user.getPhone())); + boolean flag = updateById(user); + return flag ? AjaxResult.ok().msg("编辑成功") : AjaxResult.fail("编辑失败"); + } + + /** + * 删除用户 + * + * @param id + * @return + */ + @Override + public AjaxResult removeUser(String id) { + if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空"); + User user = getById(id); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在"); + return removeById(id) ? AjaxResult.ok().msg("删除成功") : AjaxResult.fail("删除失败"); + } + + /** + * 批量删除用户 + * + * @param ids + * @return + */ + @Override + public AjaxResult removeUsers(IdsRequest ids) { + String[] idList = ids.getIds(); + if (ArrayUtil.isEmpty(idList)) return AjaxResult.fail("用户Id集合不能为空"); + List userList = listByIds(Arrays.asList(idList)); + if (CollUtil.isEmpty(userList)) return AjaxResult.fail("该用户集合全部不存在"); + return removeByIds(Arrays.asList(idList)) ? AjaxResult.ok().msg("批量删除成功") : AjaxResult.fail("批量删除失败"); + } + + /** + * 用户详情 + * + * @param id + * @return + */ + @Override + public AjaxResult userDetail(String id) { + if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空"); + User user = getById(id); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该角色不存在"); + return AjaxResult.ok().data(UserWrapper.INSTANCE.toDto(user)); + } + + /** + * 用户列表 + * + * @param page + * @param value + * @param column + * @param orderBy + * @param status + * @param role + * @param dept + * @return + */ + @Override + public AjaxResult userList(Page page, String value, String column, String orderBy, Boolean status, String role, + String dept) { + QueryWrapper qw = new QueryWrapper(); + if (StrUtil.isNotBlank(value)) { + qw.like("AES_DECRYPT(from_base64 (phone),'" + CodecUtils.KEY + "')", value).lambda() + .or().like(User::getLoginName, value) + .or().like(User::getRemarks, value) + .or().like(User::getUserName, value); + } + + qw.lambda().eq(ObjectUtil.isNotNull(status), User::getStatus, status) + .eq(StrUtil.isNotBlank(dept), User::getDept, dept) + .like(StrUtil.isNotBlank(role), User::getRoles, role); + + if ("desc".equals(orderBy) && StrUtil.isNotBlank(column)) { + qw.orderByDesc(StrUtil.toUnderlineCase(column)); + } + + if ("asc".equals(orderBy) && StrUtil.isNotBlank(column)) { + qw.orderByAsc(StrUtil.toUnderlineCase(column)); + } + + Page pageList = page(page, qw); + + return AjaxResult.ok().data(UserWrapper.INSTANCE.toDto(pageList)); + } + + /** + * 重置密码 + * + * @param id + * @return + */ + @Override + public AjaxResult resetPassword(String id) { + if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空"); + User user = getById(id); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在"); + + String initPassword = ConfigCache.getStr(ConfigCache.USER_INIT_PASSWORD, "888888"); + user.setSalt(RandomUtil.randomString(6)); + user.setPassword(PasswordUtil.password(user.getSalt(), initPassword)); + user.setLastUpdatePwd(LocalDateTime.now()); + + boolean flag = updateById(user); + return flag ? AjaxResult.ok().msg("重置密码成功,新密码为" + initPassword) : AjaxResult.fail("重置密码失败"); + } + + /** + * 获取用户所拥有的角色 + * + * @param id + * @return + */ + @Override + public AjaxResult rolesByUser(String id) { + if (StrUtil.isBlank(id)) return AjaxResult.fail("id不能为空"); + User user = getById(id); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在"); + if (StrUtil.isNotBlank(user.getRoles())) { + List roles = Arrays.asList(user.getRoles().split(",")); + return AjaxResult.ok().data(roles); + } + return AjaxResult.ok(); + } + + /** + * 分配角色 + * + * @param userRolesRequest + * @return + */ + @Override + public AjaxResult editUserRoles(UserRolesRequest userRolesRequest) { + User user = getById(userRolesRequest.getUserId()); + if (ObjectUtil.isNull(user)) return AjaxResult.fail("该用户不存在"); + user.setRoles(userRolesRequest.getRoleIds()); + boolean flag = updateById(user); + return flag ? AjaxResult.ok().msg("分配角色成功") : AjaxResult.fail("分配角色失败"); + } + + /** + * 获取拥有的角色 + * + * @param id + * @return + */ + @Override + public List roleListByUser(String id) { + User user = getById(id); + List roles = new ArrayList(); + if (StrUtil.isNotBlank(user.getRoles())) { + roles = roleService.list(new QueryWrapper().lambda() + .in(Role::getId, Arrays.asList(user.getRoles().split( + ","))) + .eq(Role::getStatus, true) + .orderByAsc(Role::getSortNo) + ); + } + return roles; + } + + /** + * 获取菜单树 + * + * @return + */ + @Override + public List

menuTreesByUser(String id) { + List roles = roleListByUser(id); + if(CollUtil.isNotEmpty(roles)) { + String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(",")); + + List> menuMap = menuService.listMaps(new QueryWrapper().lambda() + .in(Menu::getId, Arrays.asList(menus.split( + ","))) + .eq(Menu::getStatus, true) + .eq(Menu::getVisible, false) + .orderByAsc(Menu::getSortNo) + ); + + //树结构下搜索,如果子级符合条件,就把父级也放进去,确保其能显示 + Iterator> iterator = menuMap.iterator(); + List> parentList = new ArrayList<>(); + + QueryWrapper wrapper = new QueryWrapper(); + wrapper.lambda().eq(Menu::getStatus, true) + .eq(Menu::getVisible, false).orderByAsc(Menu::getSortNo); + + //获取所有菜单 + List> allMenuMap = menuService.listMaps(wrapper); + Map allMap = new HashMap(); + + allMenuMap.forEach(item -> { + HashMap map = (HashMap) item; + allMap.put(map.get("id").toString(), map); + }); + + while (iterator.hasNext()) { + Map map = (HashMap) iterator.next(); + String pid = map.get("pid").toString(); + if (!"0".equals(pid)) { + for (; ; ) { + Map pMap = (HashMap) allMap.get(pid); + if (pMap != null && !menuMap.contains(pMap) && !parentList.contains(pMap)) { + parentList.add(pMap); + pid = pMap.get("pid").toString(); + } else { + break; + } + } + } + } + menuMap.addAll(parentList); + TreeMapUtil treeMapUtil = new TreeMapUtil(); + treeMapUtil.tree(menuMap); + //转换为集合对象 + JSONArray jsonArray = new JSONArray(); + jsonArray.addAll(menuMap); + List menuList = jsonArray.toList(Menu.class); + return menuList; + } + return null; + } + + /** + * 获取菜单 + * + * @return + */ + @Override + public List menusByUser(String id) { + List roles = roleListByUser(id); + if(CollUtil.isNotEmpty(roles)){ + String menus = roles.stream().map(Role::getMenus).collect(Collectors.joining(",")); + List menuList = menuService.list(new QueryWrapper().lambda() + .in(Menu::getId, Arrays.asList(menus.split( + ","))) + .eq(Menu::getStatus, true) + .eq(Menu::getVisible, false) + .orderByAsc(Menu::getSortNo) + ); + return menuList; + } + + + + return null; + + } + + + /** + * 校验用户 + * + * @param id + * @param userRequest + * @return + */ + private String checkUser(String id, UserRequest userRequest) { + if (!Validator.isMobile(userRequest.getPhone())) return "手机号码格式不正确"; + + User user = getOne(new QueryWrapper() + .eq("AES_DECRYPT(from_base64 (phone),'" + CodecUtils.KEY + "')", userRequest.getPhone()) + .lambda() + .ne(StrUtil.isNotBlank(id), User::getId, id) + .last("limit 1") + ); + if (ObjectUtil.isNotNull(user)) return "手机号码不能重复"; + + + user = getOne(new QueryWrapper().lambda() + .eq(User::getLoginName, userRequest.getLoginName()) + .ne(StrUtil.isNotBlank(id), User::getId, id) + .last("limit 1") + ); + if (ObjectUtil.isNotNull(user)) return "登录账号不能重复"; + + return null; + } } diff --git a/src/main/java/com/ydool/system/wrapper/UserWrapper.java b/src/main/java/com/ydool/system/wrapper/UserWrapper.java new file mode 100644 index 0000000..403493b --- /dev/null +++ b/src/main/java/com/ydool/system/wrapper/UserWrapper.java @@ -0,0 +1,44 @@ +package com.ydool.system.wrapper; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.ydool.common.base.BaseWrapper; +import com.ydool.common.utils.CodecUtils; +import com.ydool.system.dto.UserDto; +import com.ydool.system.entity.Dept; +import com.ydool.system.entity.Role; +import com.ydool.system.entity.User; +import com.ydool.system.service.impl.DeptServiceImpl; +import com.ydool.system.service.impl.RoleServiceImpl; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.factory.Mappers; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@Mapper +public interface UserWrapper extends BaseWrapper { + UserWrapper INSTANCE = Mappers.getMapper(UserWrapper.class); + + @AfterMapping + default void setOtherField(User obj, @MappingTarget UserDto dto) { + DeptServiceImpl deptService = SpringUtil.getBean(DeptServiceImpl.class); + RoleServiceImpl roleService = SpringUtil.getBean(RoleServiceImpl.class); + dto.setPhone(CodecUtils.decrypt(obj.getPhone())); + Dept dept = deptService.getById(obj.getDept()); + if (ObjectUtil.isNotNull(dept)) dto.setDeptName(dept.getName()); + List roles = roleService.list(new QueryWrapper().lambda() + .in(Role::getId, Arrays.asList(obj.getRoles().split( + ","))) + .eq(Role::getStatus, true) + .orderByAsc(Role::getSortNo) + ); + if (CollUtil.isNotEmpty(roles)) + dto.setRolesName(roles.stream().map(Role::getName).collect(Collectors.joining(","))); + } +}