Commit 162bebf5fbf69cb1034b3b21d6c193de60e77468

Authored by YunaiV
1 parent 0a607861

增加 get-info 接口的相关方法

Showing 32 changed files with 1153 additions and 39 deletions
src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.redis.core;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.time.Duration;
  6 +
  7 +/**
  8 + * Redis Key 定义类
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Data
  13 +public class RedisKeyDefine {
  14 +
  15 + public enum KeyTypeEnum {
  16 +
  17 + STRING,
  18 + LIST,
  19 + HASH,
  20 + SET,
  21 + ZSET,
  22 + STREAM,
  23 + PUBSUB;
  24 +
  25 + }
  26 +
  27 + /**
  28 + * 过期时间 - 永不过期
  29 + */
  30 + public static final Duration TIMEOUT_FOREVER = null;
  31 +
  32 + /**
  33 + * 过期时间 - 动态,通过参数传入
  34 + */
  35 + public static final Duration TIMEOUT_DYNAMIC = null;
  36 +
  37 + /**
  38 + * Key 模板
  39 + */
  40 + private final String keyTemplate;
  41 + /**
  42 + * Key 类型的枚举
  43 + */
  44 + private final KeyTypeEnum keyType;
  45 + /**
  46 + * Value 类型
  47 + *
  48 + * 如果是使用分布式锁,设置为 {@link java.util.concurrent.locks.Lock} 类型
  49 + */
  50 + private final Class<?> valueType;
  51 + /**
  52 + * 过期时间
  53 + *
  54 + * 为空时,表示永不过期 {@link #TIMEOUT_FOREVER}
  55 + */
  56 + private final Duration timeout;
  57 +
  58 + public RedisKeyDefine(String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, Duration timeout) {
  59 + this.keyTemplate = keyTemplate;
  60 + this.keyType = keyType;
  61 + this.valueType = valueType;
  62 + this.timeout = timeout;
  63 + }
  64 +
  65 +}
... ...
src/main/java/cn/iocoder/dashboard/framework/security/core/LoginUser.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.dashboard.framework.security.core;
3 3 import cn.iocoder.dashboard.modules.system.enums.user.UserStatus;
4 4 import com.alibaba.fastjson.annotation.JSONField;
5 5 import lombok.Data;
6   -import org.springframework.data.annotation.Transient;
7 6 import org.springframework.security.core.GrantedAuthority;
8 7 import org.springframework.security.core.userdetails.UserDetails;
9 8  
... ... @@ -24,9 +23,13 @@ public class LoginUser implements UserDetails {
24 23 */
25 24 private Long userId;
26 25 /**
  26 + * 科室编号
  27 + */
  28 + private Long deptId;
  29 + /**
27 30 * 角色编号数组
28 31 */
29   - private Set<Integer> roleIds;
  32 + private Set<Long> roleIds;
30 33 /**
31 34 * 最后更新时间
32 35 */
... ...
src/main/java/cn/iocoder/dashboard/framework/security/core/util/SecurityUtils.java
... ... @@ -7,6 +7,7 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS
7 7 import org.springframework.util.StringUtils;
8 8  
9 9 import javax.servlet.http.HttpServletRequest;
  10 +import java.util.Set;
10 11  
11 12 /**
12 13 * 安全服务工具类
... ... @@ -15,6 +16,8 @@ import javax.servlet.http.HttpServletRequest;
15 16 */
16 17 public class SecurityUtils {
17 18  
  19 + private SecurityUtils() {}
  20 +
18 21 /**
19 22 * 从请求中,获得认证 Token
20 23 *
... ... @@ -42,6 +45,19 @@ public class SecurityUtils {
42 45 }
43 46  
44 47 /**
  48 + * 获得当前用户的编号
  49 + *
  50 + * @return 用户编号
  51 + */
  52 + public static Long getLoginUserId() {
  53 + return getLoginUser().getUserId();
  54 + }
  55 +
  56 + public static Set<Long> getLoginUserRoleIds() {
  57 + return getLoginUser().getRoleIds();
  58 + }
  59 +
  60 + /**
45 61 * 设置当前用户
46 62 *
47 63 * @param loginUser 登陆用户
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.http 0 → 100644
  1 +### 请求 /login 接口 => 成功
  2 +POST {{baseUrl}}/login
  3 +Content-Type: application/json
  4 +
  5 +{
  6 + "username": "admin",
  7 + "password": "admin123",
  8 + "uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62",
  9 + "code": "1024"
  10 +}
  11 +
  12 +### 请求 /get-info 接口 => 成功
  13 +GET {{baseUrl}}/get-info
  14 +Authorization: Bearer {{token}}
  15 +
  16 +### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
  17 +GET http://127.0.0.1:8080/druid/123
  18 +Authorization: Bearer {{token}}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.auth;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.CommonResult;
  4 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO;
  6 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO;
  7 +import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import org.springframework.web.bind.annotation.*;
  11 +
  12 +import javax.annotation.Resource;
  13 +import javax.validation.Valid;
  14 +
  15 +import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
  16 +import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId;
  17 +import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds;
  18 +
  19 +@Api(tags = "认证 API")
  20 +@RestController
  21 +@RequestMapping("/")
  22 +public class SysAuthController {
  23 +
  24 + @Resource
  25 + private SysAuthService authService;
  26 +
  27 + @ApiOperation("使用账号密码登录")
  28 + @PostMapping("/login")
  29 + public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
  30 + String token = authService.login(reqVO.getUsername(), reqVO.getPassword(), reqVO.getUuid(), reqVO.getCode());
  31 + // 返回结果
  32 + return success(SysAuthLoginRespVO.builder().token(token).build());
  33 + }
  34 +
  35 + @ApiOperation("获取登陆用户的信息")
  36 + @GetMapping("/get-info")
  37 + public CommonResult<SysAuthGetInfoRespVO> getInfo() {
  38 + SysAuthGetInfoRespVO respVO = authService.getInfo(getLoginUserId(), getLoginUserRoleIds());
  39 + return success(respVO);
  40 + }
  41 +
  42 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthGetInfoRespVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.auth.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +import java.util.Set;
  8 +
  9 +@ApiModel("获得用户信息 Resp VO")
  10 +@Data
  11 +public class SysAuthGetInfoRespVO {
  12 +
  13 + @ApiModelProperty(value = "角色权限数组", required = true)
  14 + private Set<String> roles;
  15 +
  16 + @ApiModelProperty(value = "菜单权限数组", required = true)
  17 + private Set<String> permissions;
  18 +
  19 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthLoginReqVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.auth.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Builder;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +import org.hibernate.validator.constraints.Length;
  10 +import org.springframework.validation.annotation.Validated;
  11 +
  12 +import javax.validation.Valid;
  13 +import javax.validation.constraints.NotEmpty;
  14 +import javax.validation.constraints.Pattern;
  15 +
  16 +@ApiModel("账号密码登陆 Request VO")
  17 +@Data
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
  20 +@Builder
  21 +public class SysAuthLoginReqVO {
  22 +
  23 + @ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
  24 + @NotEmpty(message = "登陆账号不能为空")
  25 + @Length(min = 5, max = 16, message = "账号长度为 5-16 位")
  26 + @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母")
  27 + private String username;
  28 +
  29 + @ApiModelProperty(value = "密码", required = true, example = "buzhidao")
  30 + @NotEmpty(message = "密码不能为空")
  31 + @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
  32 + private String password;
  33 +
  34 + @ApiModelProperty(value = "验证码", required = true, example = "1024")
  35 + @NotEmpty(message = "验证码不能为空")
  36 + private String code;
  37 +
  38 + @ApiModelProperty(value = "验证码的唯一标识", required = true, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
  39 + @NotEmpty(message = "唯一标识不能为空")
  40 + private String uuid;
  41 +
  42 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/vo/SysAuthLoginRespVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.auth.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Builder;
  7 +import lombok.Data;
  8 +import lombok.NoArgsConstructor;
  9 +
  10 +@ApiModel("账号密码登陆 Response VO")
  11 +@Data
  12 +@NoArgsConstructor
  13 +@AllArgsConstructor
  14 +@Builder
  15 +public class SysAuthLoginRespVO {
  16 +
  17 + @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
  18 + private String token;
  19 +
  20 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java
1 1 package cn.iocoder.dashboard.modules.system.convert.auth;
2 2  
3 3 import cn.iocoder.dashboard.framework.security.core.LoginUser;
  4 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  6 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
4 7 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
  8 +import cn.iocoder.dashboard.util.collection.CollectionUtils;
5 9 import org.mapstruct.Mapper;
6 10 import org.mapstruct.Mapping;
7 11 import org.mapstruct.factory.Mappers;
8 12  
  13 +import java.util.List;
  14 +
9 15 @Mapper
10 16 public interface SysAuthConvert {
11 17  
... ... @@ -14,4 +20,11 @@ public interface SysAuthConvert {
14 20 @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略
15 21 LoginUser convert(SysUserDO bean);
16 22  
  23 + default SysAuthGetInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) {
  24 + SysAuthGetInfoRespVO respVO = new SysAuthGetInfoRespVO();
  25 + respVO.setRoles(CollectionUtils.convertSet(roleList, SysRoleDO::getRoleKey));
  26 + respVO.setPermissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPerms));
  27 + return respVO;
  28 + }
  29 +
17 30 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/package-info.java deleted
1   -package cn.iocoder.dashboard.modules.system.dal.mysql.dao;
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysMenuMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysMenuMapper extends BaseMapper<SysMenuDO> {
  9 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysRoleDeptMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDeptDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysRoleDeptMapper extends BaseMapper<SysRoleDeptDO> {
  9 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysRoleMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysRoleMapper extends BaseMapper<SysRoleDO> {
  9 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysRoleMenuMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleMenuDO;
  4 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenuDO> {
  9 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/permission/SysUserRoleMapper.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysUserRoleDO;
  4 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.List;
  9 +
  10 +@Mapper
  11 +public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
  12 +
  13 + default List<SysUserRoleDO> selectListByUserId(Long userId) {
  14 + return selectList(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
  15 + }
  16 +
  17 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/dept/SysDept.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  4 +
  5 +import javax.validation.constraints.Email;
  6 +import javax.validation.constraints.NotBlank;
  7 +import javax.validation.constraints.Size;
  8 +import java.util.ArrayList;
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * 部门表 sys_dept
  13 + *
  14 + * @author ruoyi
  15 + */
  16 +public class SysDept extends BaseDO {
  17 +
  18 + /**
  19 + * 部门ID
  20 + */
  21 + private Long deptId;
  22 +
  23 + /**
  24 + * 父部门ID
  25 + */
  26 + private Long parentId;
  27 +
  28 + /**
  29 + * 祖级列表
  30 + */
  31 + private String ancestors;
  32 +
  33 + /**
  34 + * 部门名称
  35 + */
  36 + private String deptName;
  37 +
  38 + /**
  39 + * 显示顺序
  40 + */
  41 + private String orderNum;
  42 +
  43 + /**
  44 + * 负责人
  45 + */
  46 + private String leader;
  47 +
  48 + /**
  49 + * 联系电话
  50 + */
  51 + private String phone;
  52 +
  53 + /**
  54 + * 邮箱
  55 + */
  56 + private String email;
  57 +
  58 + /**
  59 + * 部门状态:0正常,1停用
  60 + */
  61 + private String status;
  62 +
  63 + /**
  64 + * 删除标志(0代表存在 2代表删除)
  65 + */
  66 + private String delFlag;
  67 +
  68 + /**
  69 + * 父部门名称
  70 + */
  71 + private String parentName;
  72 +
  73 + /**
  74 + * 子部门
  75 + */
  76 + private List<SysDept> children = new ArrayList<SysDept>();
  77 +
  78 + @NotBlank(message = "部门名称不能为空")
  79 + @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
  80 + public String getDeptName() {
  81 + return deptName;
  82 + }
  83 +
  84 + @NotBlank(message = "显示顺序不能为空")
  85 + public String getOrderNum() {
  86 + return orderNum;
  87 + }
  88 +
  89 + @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
  90 + public String getPhone() {
  91 + return phone;
  92 + }
  93 +
  94 + @Email(message = "邮箱格式不正确")
  95 + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
  96 + public String getEmail() {
  97 + return email;
  98 + }
  99 +
  100 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/package-info.java deleted
1   -package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject;
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysMenuDO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +
  10 +import javax.validation.constraints.NotBlank;
  11 +import javax.validation.constraints.Size;
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * 菜单权限表
  17 + *
  18 + * @author ruoyi
  19 + */
  20 +@TableName("sys_menu")
  21 +@Data
  22 +@EqualsAndHashCode(callSuper = true)
  23 +public class SysMenuDO extends BaseDO {
  24 +
  25 + /**
  26 + * 菜单ID
  27 + */
  28 + @TableId
  29 + private Long menuId;
  30 +
  31 + /**
  32 + * 菜单名称
  33 + */
  34 + @NotBlank(message = "菜单名称不能为空")
  35 + @Size(max = 50, message = "菜单名称长度不能超过50个字符")
  36 + private String menuName;
  37 +
  38 + /**
  39 + * 父菜单ID
  40 + */
  41 + private Long parentId;
  42 +
  43 + /**
  44 + * 显示顺序
  45 + */
  46 + @NotBlank(message = "显示顺序不能为空")
  47 + private String orderNum;
  48 +
  49 + /**
  50 + * 路由地址
  51 + */
  52 + @Size(max = 200, message = "路由地址不能超过200个字符")
  53 + private String path;
  54 +
  55 + /**
  56 + * 组件路径
  57 + */
  58 + @Size(max = 200, message = "组件路径不能超过255个字符")
  59 + private String component;
  60 +
  61 + /**
  62 + * 是否为外链(0是 1否)
  63 + */
  64 + private String isFrame;
  65 +
  66 + /**
  67 + * 是否缓存(0缓存 1不缓存)
  68 + */
  69 + private String isCache;
  70 +
  71 + /**
  72 + * 类型(M目录 C菜单 F按钮)
  73 + */
  74 + @NotBlank(message = "菜单类型不能为空")
  75 + private String menuType;
  76 +
  77 + /**
  78 + * 显示状态(0显示 1隐藏)
  79 + */
  80 + private String visible;
  81 +
  82 + /**
  83 + * 菜单状态(0显示 1隐藏)
  84 + */
  85 + private String status;
  86 +
  87 + /**
  88 + * 权限字符串
  89 + */
  90 + @Size(max = 100, message = "权限标识长度不能超过100个字符")
  91 + private String perms;
  92 +
  93 + /**
  94 + * 菜单图标
  95 + */
  96 + private String icon;
  97 +
  98 + // TODO 芋艿:非存储字段,需要提出
  99 +
  100 + /**
  101 + * 父菜单名称
  102 + */
  103 + @TableField(exist = false)
  104 + private String parentName;
  105 +
  106 + /**
  107 + * 子菜单
  108 + */
  109 + @TableField(exist = false)
  110 + private List<SysMenuDO> children = new ArrayList<SysMenuDO>();
  111 +
  112 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
  2 +
  3 +import cn.iocoder.dashboard.framework.excel.Excel;
  4 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.Data;
  9 +import lombok.EqualsAndHashCode;
  10 +
  11 +import javax.validation.constraints.NotBlank;
  12 +import javax.validation.constraints.Size;
  13 +
  14 +/**
  15 + * 角色 DO
  16 + *
  17 + * @author ruoyi
  18 + */
  19 +@TableName("sys_role")
  20 +@Data
  21 +@EqualsAndHashCode(callSuper = true)
  22 +// TODO 芋艿:数据库的字段默认值
  23 +public class SysRoleDO extends BaseDO {
  24 +
  25 + /**
  26 + * 角色ID
  27 + */
  28 + @TableId
  29 + @Excel(name = "角色序号", cellType = Excel.ColumnType.NUMERIC)
  30 + private Long roleId;
  31 +
  32 + /**
  33 + * 角色名称
  34 + */
  35 + @Excel(name = "角色名称")
  36 + @NotBlank(message = "角色名称不能为空")
  37 + @Size(max = 30, message = "角色名称长度不能超过30个字符")
  38 + private String roleName;
  39 +
  40 + /**
  41 + * 角色权限
  42 + */
  43 + @Excel(name = "角色权限")
  44 + @NotBlank(message = "权限字符不能为空")
  45 + @Size(max = 100, message = "权限字符长度不能超过100个字符")
  46 + private String roleKey;
  47 +
  48 + /**
  49 + * 角色排序
  50 + */
  51 + @Excel(name = "角色排序")
  52 + @NotBlank(message = "显示顺序不能为空")
  53 + private Integer roleSort;
  54 +
  55 + /**
  56 + * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限)
  57 + */
  58 + @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限")
  59 + private String dataScope;
  60 +
  61 + /**
  62 + * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)
  63 + */
  64 + private boolean menuCheckStrictly;
  65 +
  66 + /**
  67 + * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )
  68 + */
  69 + private boolean deptCheckStrictly;
  70 +
  71 + /**
  72 + * 角色状态(0正常 1停用)
  73 + */
  74 + @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
  75 + private String status;
  76 +
  77 + // TODO FROM 芋艿:下面的字段,需要忽略
  78 +
  79 + /**
  80 + * 用户是否存在此角色标识 默认不存在
  81 + */
  82 + @TableField(exist = false)
  83 + private boolean flag = false;
  84 +
  85 + /**
  86 + * 菜单组
  87 + */
  88 + @TableField(exist = false)
  89 + private Long[] menuIds;
  90 +
  91 + /**
  92 + * 部门组(数据权限)
  93 + */
  94 + @TableField(exist = false)
  95 + private Long[] deptIds;
  96 +
  97 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleDeptDO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +
  9 +/**
  10 + * 部门和角色关联 DO
  11 + *
  12 + * @author ruoyi
  13 + */
  14 +@TableName("sys_role_dept")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +public class SysRoleDeptDO extends BaseDO {
  18 +
  19 + /**
  20 + * 自增主键
  21 + */
  22 + @TableId
  23 + private Long id;
  24 + /**
  25 + * 部门 ID
  26 + */
  27 + private Long deptId;
  28 + /**
  29 + * 角色 ID
  30 + */
  31 + private Long roleId;
  32 +
  33 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysRoleMenuDO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +
  9 +/**
  10 + * 角色和菜单关联
  11 + *
  12 + * @author ruoyi
  13 + */
  14 +@TableName("sys_role_menu")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +public class SysRoleMenuDO extends BaseDO {
  18 +
  19 + /**
  20 + * 自增主键
  21 + */
  22 + @TableId
  23 + private Long id;
  24 + /**
  25 + * 角色ID
  26 + */
  27 + private Long roleId;
  28 + /**
  29 + * 菜单ID
  30 + */
  31 + private Long menuId;
  32 +
  33 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/permission/SysUserRoleDO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission;
  2 +
  3 +import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableId;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +
  9 +/**
  10 + * 用户和角色关联
  11 + *
  12 + * @author ruoyi
  13 + */
  14 +@TableName("sys_user_role")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +public class SysUserRoleDO extends BaseDO {
  18 +
  19 + /**
  20 + * 自增主键
  21 + */
  22 + @TableId
  23 + private Long id;
  24 + /**
  25 + * 用户 ID
  26 + */
  27 + private Long userId;
  28 + /**
  29 + * 角色 ID
  30 + */
  31 + private Long roleId;
  32 +
  33 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/user/SysUserDO.java
1 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user;
2 2  
3   -import java.util.Date;
4   -import java.util.List;
5   -import javax.validation.constraints.Email;
6   -import javax.validation.constraints.NotBlank;
7   -import javax.validation.constraints.Size;
8   -
9 3 import cn.iocoder.dashboard.framework.excel.Excel;
10 4 import cn.iocoder.dashboard.framework.excel.Excels;
11 5 import cn.iocoder.dashboard.framework.mybatis.core.BaseDO;
12 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDept;
13   -import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRole;
  7 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
14 8 import com.baomidou.mybatisplus.annotation.TableField;
15 9 import com.baomidou.mybatisplus.annotation.TableId;
16 10 import com.baomidou.mybatisplus.annotation.TableName;
17   -import com.fasterxml.jackson.annotation.JsonIgnore;
18   -import com.fasterxml.jackson.annotation.JsonProperty;
19 11 import lombok.Data;
20 12 import lombok.EqualsAndHashCode;
21 13 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
22 14  
  15 +import javax.validation.constraints.Email;
  16 +import javax.validation.constraints.NotBlank;
  17 +import javax.validation.constraints.Size;
  18 +import java.util.Date;
  19 +import java.util.List;
  20 +
23 21 /**
24 22 * 用户 DO
25 23 *
... ... @@ -128,7 +126,7 @@ public class SysUserDO extends BaseDO {
128 126 * 角色对象
129 127 */
130 128 @TableField(exist = false)
131   - private List<SysRole> roles;
  129 + private List<SysRoleDO> roles;
132 130  
133 131 /**
134 132 * 角色组
... ... @@ -142,13 +140,4 @@ public class SysUserDO extends BaseDO {
142 140 @TableField(exist = false)
143 141 private Long[] postIds;
144 142  
145   - // TODO 芋艿:后续清理掉
146   - public boolean isAdmin() {
147   - return isAdmin(this.userId);
148   - }
149   -
150   - public static boolean isAdmin(Long userId) {
151   - return userId != null && 1L == userId;
152   - }
153   -
154 143 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/enums/permission/RoleKeyEnum.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.enums.permission;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * 角色标识枚举
  8 + */
  9 +@Getter
  10 +@AllArgsConstructor
  11 +public enum RoleKeyEnum {
  12 +
  13 + ADMIN("admin"), // 超级管理员
  14 + ;
  15 +
  16 + /**
  17 + * 角色编码
  18 + */
  19 + private final String key;
  20 +
  21 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthService.java
1 1 package cn.iocoder.dashboard.modules.system.service.auth;
2 2  
3 3 import cn.iocoder.dashboard.framework.security.core.service.SecurityFrameworkService;
  4 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  5 +
  6 +import java.util.Set;
4 7  
5 8 /**
6 9 * 认证 Service 接口
... ... @@ -13,4 +16,16 @@ public interface SysAuthService extends SecurityFrameworkService {
13 16  
14 17 String login(String username, String password, String captchaUUID, String captchaCode);
15 18  
  19 + /**
  20 + * 获得用户的基本信息
  21 + *
  22 + * 这里传输 roleIds 参数的原因,是该参数是从 LoginUser 缓存中获取到的,而我们校验权限时也是从 LoginUser 缓存中获取 roleIds
  23 + * 通过这样的方式,保持一致
  24 + *
  25 + * @param userId 用户编号
  26 + * @param roleIds 用户拥有的角色编号数组
  27 + * @return 用户的信息,包括角色权限和菜单权限
  28 + */
  29 + SysAuthGetInfoRespVO getInfo(Long userId, Set<Long> roleIds);
  30 +
16 31 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
... ... @@ -4,13 +4,19 @@ import cn.hutool.core.util.IdUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
6 6 import cn.iocoder.dashboard.framework.security.core.LoginUser;
  7 +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthGetInfoRespVO;
  8 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  9 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
7 10 import cn.iocoder.dashboard.modules.system.enums.user.UserStatus;
8 11 import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
9 12 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
10 13 import cn.iocoder.dashboard.modules.system.dal.redis.dao.auth.SysLoginUserRedisDAO;
11 14 import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
12 15 import cn.iocoder.dashboard.modules.system.service.auth.SysTokenService;
  16 +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
  17 +import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
13 18 import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
  19 +import cn.iocoder.dashboard.util.collection.CollectionUtils;
14 20 import cn.iocoder.dashboard.util.date.DateUtils;
15 21 import io.jsonwebtoken.Claims;
16 22 import io.jsonwebtoken.JwtException;
... ... @@ -27,9 +33,7 @@ import org.springframework.stereotype.Service;
27 33 import org.springframework.util.Assert;
28 34  
29 35 import javax.annotation.Resource;
30   -import java.util.Collections;
31   -import java.util.Date;
32   -import java.util.Set;
  36 +import java.util.*;
33 37  
34 38 import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
35 39 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
... ... @@ -53,6 +57,11 @@ public class SysAuthServiceImpl implements SysAuthService {
53 57 @Resource
54 58 private SysUserService userService;
55 59 @Resource
  60 + private SysRoleService roleService;
  61 + @Resource
  62 + private SysPermissionService permissionService;
  63 +
  64 + @Resource
56 65 private SysLoginUserRedisDAO loginUserRedisDAO;
57 66  
58 67 @Override
... ... @@ -62,7 +71,6 @@ public class SysAuthServiceImpl implements SysAuthService {
62 71 if (user == null) {
63 72 throw new UsernameNotFoundException(username);
64 73 }
65   -
66 74 // 创建 LoginUser 对象
67 75 return SysAuthConvert.INSTANCE.convert(user);
68 76 }
... ... @@ -74,11 +82,10 @@ public class SysAuthServiceImpl implements SysAuthService {
74 82 if (user == null) {
75 83 throw new UsernameNotFoundException(String.valueOf(userId));
76 84 }
77   -
78 85 // 创建 LoginUser 对象
79 86 LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
80 87 loginUser.setUpdateTime(new Date());
81   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId()));
  88 + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId(), loginUser.getDeptId()));
82 89 return loginUser;
83 90 }
84 91  
... ... @@ -89,11 +96,10 @@ public class SysAuthServiceImpl implements SysAuthService {
89 96  
90 97 // 使用账号密码,进行登陆。
91 98 LoginUser loginUser = this.login0(username, password);
92   -
93 99 // 缓存登陆用户到 Redis 中
94 100 String sessionId = IdUtil.fastSimpleUUID();
95 101 loginUser.setUpdateTime(new Date());
96   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId()));
  102 + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId(), loginUser.getDeptId()));
97 103 loginUserRedisDAO.set(sessionId, loginUser);
98 104  
99 105 // 创建 Token
... ... @@ -143,11 +149,15 @@ public class SysAuthServiceImpl implements SysAuthService {
143 149 * 获得 User 拥有的角色编号数组
144 150 *
145 151 * @param userId 用户编号
  152 + * @param deptId 科室编号
146 153 * @return 角色编号数组
147 154 */
148   - private Set<Integer> getUserRoleIds(Long userId) {
149   - // TODO 芋艿:读取角色编号
150   - return Collections.emptySet();
  155 + private Set<Long> getUserRoleIds(Long userId, Long deptId) {
  156 + // 用户拥有的角色
  157 + Set<Long> roleIds = new HashSet<>(permissionService.listUserRoleIds(userId));
  158 + // 部门拥有的角色
  159 + CollectionUtils.addIfNotNull(roleIds, permissionService.getDeptRoleId(deptId));
  160 + return roleIds;
151 161 }
152 162  
153 163 @Override
... ... @@ -162,7 +172,6 @@ public class SysAuthServiceImpl implements SysAuthService {
162 172 // 获得 LoginUser
163 173 LoginUser loginUser = loginUserRedisDAO.get(sessionId);
164 174 if (loginUser == null) {
165   -// throw exception(AUTH_SESSION_TIMEOUT);
166 175 return null;
167 176 }
168 177 // 刷新 LoginUser 缓存
... ... @@ -176,18 +185,15 @@ public class SysAuthServiceImpl implements SysAuthService {
176 185 claims = tokenService.parseToken(token);
177 186 } catch (JwtException jwtException) {
178 187 log.warn("[verifyToken][token({}) 解析发生异常]", token);
179   -// throw exception(TOKEN_PARSE_FAIL);
180 188 return null;
181 189 }
182 190 // token 已经过期
183 191 if (DateUtils.isExpired(claims.getExpiration())) {
184   -// throw exception(TOKEN_EXPIRED);
185 192 return null;
186 193 }
187 194 // 判断 sessionId 是否存在
188 195 String sessionId = claims.getSubject();
189 196 if (StrUtil.isBlank(sessionId)) {
190   -// throw exception(AUTH_SESSION_ID_NOT_FOUND);
191 197 return null;
192 198 }
193 199 return sessionId;
... ... @@ -207,9 +213,25 @@ public class SysAuthServiceImpl implements SysAuthService {
207 213 }
208 214  
209 215 // 刷新 LoginUser 缓存
  216 + loginUser.setDeptId(user.getDeptId());
210 217 loginUser.setUpdateTime(new Date());
211   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId()));
  218 + loginUser.setRoleIds(this.getUserRoleIds(loginUser.getUserId(), loginUser.getDeptId()));
212 219 loginUserRedisDAO.set(sessionId, loginUser);
213 220 }
214 221  
  222 + @Override
  223 + public SysAuthGetInfoRespVO getInfo(Long userId, Set<Long> roleIds) {
  224 + // 获得用户信息
  225 + SysUserDO user = userService.getUser(userId);
  226 + if (user == null) {
  227 + return null;
  228 + }
  229 + // 获得角色列表
  230 + List<SysRoleDO> roleList = roleService.listRolesFromCache(roleIds);
  231 + // 获得菜单列表
  232 + List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(roleIds);
  233 + // 拼接结果返回
  234 + return SysAuthConvert.INSTANCE.convert(user, roleList, menuList);
  235 + }
  236 +
215 237 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysMenuService.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 菜单 Service 接口
  10 + */
  11 +public interface SysMenuService {
  12 +
  13 + /**
  14 + *
  15 + */
  16 + void init();
  17 +
  18 + /**
  19 + * 获得所有菜单,从缓存中
  20 + *
  21 + * @return 菜单列表
  22 + */
  23 + List<SysMenuDO> listMenusFromCache();
  24 +
  25 + /**
  26 + * 获得指定编号的菜单数组,从缓存中
  27 + *
  28 + * @param menuIds 菜单编号数组
  29 + * @return 菜单数组
  30 + */
  31 + List<SysMenuDO> listMenusFromCache(Collection<Long> menuIds);
  32 +
  33 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 权限 Service 接口
  10 + *
  11 + * 提供用户-角色、角色-菜单、角色-部门的关联权限处理
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +public interface SysPermissionService {
  16 +
  17 + /**
  18 + * 初始化
  19 + */
  20 + void init();
  21 +
  22 + /**
  23 + * 获得角色们拥有的菜单列表,从缓存中获取
  24 + *
  25 + * @param roleIds 角色编号素组
  26 + * @return 菜单列表
  27 + */
  28 + List<SysMenuDO> listRoleMenusFromCache(Collection<Long> roleIds);
  29 +
  30 + /**
  31 + * 获得用户拥有的角色编号数组
  32 + *
  33 + * @param userId 用户编号
  34 + * @return 角色编号数组
  35 + */
  36 + List<Long> listUserRoleIds(Long userId);
  37 +
  38 + /**
  39 + * 获得部门拥有的角色编号
  40 + *
  41 + * @param deptId 部门编号
  42 + * @return 角色编号
  43 + */
  44 + Long getDeptRoleId(Long deptId);
  45 +
  46 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysRoleService.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 角色 Service 接口
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +public interface SysRoleService {
  14 +
  15 + /**
  16 + * 初始化
  17 + */
  18 + void init();
  19 +
  20 + /**
  21 + * 获得角色数组,从缓存中
  22 + *
  23 + * @param roleIds 角色编号数组
  24 + * @return 角色数组
  25 + */
  26 + List<SysRoleDO> listRolesFromCache(Collection<Long> roleIds);
  27 +
  28 + /**
  29 + * 判断角色数组中,是否有管理员
  30 + *
  31 + * @param roleList 角色数组
  32 + * @return 是否有管理员
  33 + */
  34 + boolean hasAnyAdmin(Collection<SysRoleDO> roleList);
  35 +
  36 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission.impl;
  2 +
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysMenuMapper;
  5 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
  6 +import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
  7 +import com.google.common.collect.ImmutableList;
  8 +import com.google.common.collect.ImmutableMap;
  9 +import com.google.common.collect.ImmutableMultimap;
  10 +import com.google.common.collect.Multimap;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +import javax.annotation.PostConstruct;
  15 +import javax.annotation.Resource;
  16 +import java.util.Collection;
  17 +import java.util.Collections;
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +import java.util.stream.Collectors;
  21 +
  22 +/**
  23 + * 菜单 Service 实现
  24 + */
  25 +@Service
  26 +@Slf4j
  27 +public class SysMenuServiceImpl implements SysMenuService {
  28 +
  29 + /**
  30 + * 菜单缓存
  31 + * key:菜单编号
  32 + *
  33 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  34 + */
  35 + private volatile Map<Long, SysMenuDO> menuCache;
  36 + /**
  37 + * 权限与菜单缓存
  38 + * key:权限 {@link SysMenuDO#getPerms()}
  39 + * value:SysMenuDO 数组,因为一个权限可能对应多个 SysMenuDO 对象
  40 + *
  41 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  42 + */
  43 + private volatile Multimap<String, SysMenuDO> permMenuCache;
  44 +
  45 + @Resource
  46 + private SysMenuMapper menuMapper;
  47 +
  48 + /**
  49 + * 初始化 {@link #menuCache} 和 {@link #permMenuCache} 缓存
  50 + */
  51 + @Override
  52 + @PostConstruct
  53 + public void init() {
  54 + List<SysMenuDO> menuList = menuMapper.selectList(null);
  55 + ImmutableMap.Builder<Long, SysMenuDO> menuCacheBuilder = ImmutableMap.builder();
  56 + ImmutableMultimap.Builder<String, SysMenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
  57 + menuList.forEach(menuDO -> {
  58 + menuCacheBuilder.put(menuDO.getMenuId(), menuDO);
  59 + permMenuCacheBuilder.put(menuDO.getPerms(), menuDO);
  60 + });
  61 + menuCache = menuCacheBuilder.build();
  62 + permMenuCache = permMenuCacheBuilder.build();
  63 + log.info("[init][初始化菜单数量为 {}]", menuList.size());
  64 + }
  65 +
  66 + @Override
  67 + public List<SysMenuDO> listMenusFromCache() {
  68 + // Guava ImmutableMap 对应的 value 类型为 ImmutableCollection
  69 + // 而 ImmutableList 在 copyof 时,如果入参类型为 ImmutableCollection 时,会进行包装,而不会进行复制。
  70 + return ImmutableList.copyOf(menuCache.values());
  71 + }
  72 +
  73 + @Override
  74 + public List<SysMenuDO> listMenusFromCache(Collection<Long> menuIds) {
  75 + if (CollectionUtil.isEmpty(menuIds)) {
  76 + return Collections.emptyList();
  77 + }
  78 + return menuCache.values().stream().filter(menuDO -> menuIds.contains(menuDO.getMenuId()))
  79 + .collect(Collectors.toList());
  80 + }
  81 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission.impl;
  2 +
  3 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleDeptMapper;
  4 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleMenuMapper;
  5 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysUserRoleMapper;
  6 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.*;
  7 +import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
  8 +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
  9 +import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
  10 +import cn.iocoder.dashboard.util.collection.CollectionUtils;
  11 +import cn.iocoder.dashboard.util.collection.MapUtils;
  12 +import com.google.common.collect.ImmutableMultimap;
  13 +import com.google.common.collect.Multimap;
  14 +import lombok.extern.slf4j.Slf4j;
  15 +import org.springframework.stereotype.Service;
  16 +
  17 +import javax.annotation.PostConstruct;
  18 +import javax.annotation.Resource;
  19 +import java.util.Collection;
  20 +import java.util.List;
  21 +
  22 +/**
  23 + * 权限 Service 实现类
  24 + *
  25 + * @author 初始化
  26 + */
  27 +@Service
  28 +@Slf4j
  29 +public class SysPermissionServiceImpl implements SysPermissionService {
  30 +
  31 + /**
  32 + * 角色编号与菜单编号的缓存映射
  33 + * key:角色编号
  34 + * value:菜单编号的数组
  35 + *
  36 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  37 + */
  38 + private volatile Multimap<Long, Long> roleMenuCache;
  39 + /**
  40 + * 菜单编号与角色编号的缓存映射
  41 + * key:菜单编号
  42 + * value:角色编号的数组
  43 + *
  44 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  45 + */
  46 + private volatile Multimap<Long, Long> menuRoleCache;
  47 +
  48 + @Resource
  49 + private SysRoleMenuMapper roleMenuMapper;
  50 + @Resource
  51 + private SysUserRoleMapper userRoleMapper;
  52 + @Resource
  53 + private SysRoleDeptMapper roleDeptMapper;
  54 +
  55 + @Resource
  56 + private SysRoleService roleService;
  57 + @Resource
  58 + private SysMenuService menuService;
  59 +
  60 + /**
  61 + * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存
  62 + */
  63 + @Override
  64 + @PostConstruct
  65 + public void init() {
  66 + // 初始化 roleMenuCache 和 menuRoleCache 缓存
  67 + List<SysRoleMenuDO> roleMenuList = roleMenuMapper.selectList(null);
  68 + ImmutableMultimap.Builder<Long, Long> roleMenuCacheBuilder = ImmutableMultimap.builder();
  69 + ImmutableMultimap.Builder<Long, Long> menuRoleCacheBuilder = ImmutableMultimap.builder();
  70 + roleMenuList.forEach(roleMenuDO -> {
  71 + roleMenuCacheBuilder.put(roleMenuDO.getRoleId(), roleMenuDO.getMenuId());
  72 + menuRoleCacheBuilder.put(roleMenuDO.getMenuId(), roleMenuDO.getRoleId());
  73 + });
  74 + roleMenuCache = roleMenuCacheBuilder.build();
  75 + menuRoleCache = menuRoleCacheBuilder.build();
  76 + log.info("[init][初始化角色与菜单的关联数量为 {}]", roleMenuList.size());
  77 + }
  78 +
  79 + @Override
  80 + public List<SysMenuDO> listRoleMenusFromCache(Collection<Long> roleIds) {
  81 + // 判断角色是否包含管理员
  82 + List<SysRoleDO> roleList = roleService.listRolesFromCache(roleIds);
  83 + boolean hasAdmin = roleService.hasAnyAdmin(roleList);
  84 + // 获得角色拥有的菜单关联
  85 + if (hasAdmin) { // 管理员,获取到全部
  86 + return menuService.listMenusFromCache();
  87 + }
  88 + List<Long> menuIds = MapUtils.getList(roleMenuCache, roleIds);
  89 + return menuService.listMenusFromCache(menuIds);
  90 + }
  91 +
  92 + @Override
  93 + public List<Long> listUserRoleIds(Long userId) {
  94 + List<SysUserRoleDO> userRoleList = userRoleMapper.selectListByUserId(userId);
  95 + return CollectionUtils.convertList(userRoleList, SysUserRoleDO::getRoleId);
  96 + }
  97 +
  98 + @Override
  99 + public Long getDeptRoleId(Long deptId) {
  100 + SysRoleDeptDO roleDept = roleDeptMapper.selectById(deptId);
  101 + return roleDept != null ? roleDept.getRoleId() : null;
  102 + }
  103 +
  104 +}
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission.impl;
  2 +
  3 +import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.permission.SysRoleMapper;
  5 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
  6 +import cn.iocoder.dashboard.modules.system.enums.permission.RoleKeyEnum;
  7 +import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
  8 +import com.google.common.collect.ImmutableMap;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.stereotype.Service;
  11 +
  12 +import javax.annotation.PostConstruct;
  13 +import javax.annotation.Resource;
  14 +import java.util.Collection;
  15 +import java.util.Collections;
  16 +import java.util.List;
  17 +import java.util.Map;
  18 +import java.util.stream.Collectors;
  19 +
  20 +/**
  21 + * 角色 Service 实现类
  22 + */
  23 +@Service
  24 +@Slf4j
  25 +public class SysRoleServiceImpl implements SysRoleService {
  26 +
  27 + @Resource
  28 + private SysRoleMapper roleMapper;
  29 +
  30 + /**
  31 + * 角色缓存
  32 + * key:角色编号 {@link SysRoleDO#getRoleId()}
  33 + *
  34 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  35 + */
  36 + private volatile Map<Long, SysRoleDO> roleCache;
  37 +
  38 + /**
  39 + * 初始化 {@link #roleCache} 缓存
  40 + */
  41 + @Override
  42 + @PostConstruct
  43 + public void init() {
  44 + // 从数据库中读取
  45 + List<SysRoleDO> roleDOList = roleMapper.selectList(null);
  46 + // 写入缓存
  47 + ImmutableMap.Builder<Long, SysRoleDO> builder = ImmutableMap.builder();
  48 + roleDOList.forEach(sysRoleDO -> builder.put(sysRoleDO.getRoleId(), sysRoleDO));
  49 + roleCache = builder.build();
  50 + log.info("[init][初始化 Role 数量为 {}]", roleDOList.size());
  51 + }
  52 +
  53 + @Override
  54 + public List<SysRoleDO> listRolesFromCache(Collection<Long> roleIds) {
  55 + if (CollectionUtil.isEmpty(roleIds)) {
  56 + return Collections.emptyList();
  57 + }
  58 + return roleCache.values().stream().filter(roleDO -> roleIds.contains(roleDO.getRoleId()))
  59 + .collect(Collectors.toList());
  60 + }
  61 +
  62 + @Override
  63 + public boolean hasAnyAdmin(Collection<SysRoleDO> roleList) {
  64 + if (CollectionUtil.isEmpty(roleList)) {
  65 + return false;
  66 + }
  67 + return roleList.stream().anyMatch(roleDO -> RoleKeyEnum.ADMIN.getKey().equals(roleDO.getRoleKey()));
  68 + }
  69 +
  70 +}
... ...