Commit 49b4eedfc0ca13bfb0c4fdfab952b0574c754153

Authored by YunaiV
1 parent 97db4586

增加 UserRole 的缓存,完善权限相关的单元测试

yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -93,7 +93,7 @@ public class AuthController { @@ -93,7 +93,7 @@ public class AuthController {
93 return null; 93 return null;
94 } 94 }
95 // 获得角色列表 95 // 获得角色列表
96 - Set<Long> roleIds = permissionService.getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); 96 + Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
97 List<RoleDO> roleList = roleService.getRolesFromCache(roleIds); 97 List<RoleDO> roleList = roleService.getRolesFromCache(roleIds);
98 // 获得菜单列表 98 // 获得菜单列表
99 List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds, 99 List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds,
@@ -107,7 +107,7 @@ public class AuthController { @@ -107,7 +107,7 @@ public class AuthController {
107 @ApiOperation("获得登录用户的菜单列表") 107 @ApiOperation("获得登录用户的菜单列表")
108 public CommonResult<List<AuthMenuRespVO>> getMenus() { 108 public CommonResult<List<AuthMenuRespVO>> getMenus() {
109 // 获得角色列表 109 // 获得角色列表
110 - Set<Long> roleIds = permissionService.getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); 110 + Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
111 // 获得用户拥有的菜单列表 111 // 获得用户拥有的菜单列表
112 List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds, 112 List<MenuDO> menuList = permissionService.getRoleMenuListFromCache(roleIds,
113 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型 113 SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/UserRoleMapper.java
@@ -4,8 +4,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -4,8 +4,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; 4 import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
  7 +import org.apache.ibatis.annotations.Select;
7 8
8 import java.util.Collection; 9 import java.util.Collection;
  10 +import java.util.Date;
9 import java.util.List; 11 import java.util.List;
10 12
11 @Mapper 13 @Mapper
@@ -36,4 +38,8 @@ public interface UserRoleMapper extends BaseMapperX&lt;UserRoleDO&gt; { @@ -36,4 +38,8 @@ public interface UserRoleMapper extends BaseMapperX&lt;UserRoleDO&gt; {
36 default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) { 38 default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) {
37 return selectList(UserRoleDO::getRoleId, roleIds); 39 return selectList(UserRoleDO::getRoleId, roleIds);
38 } 40 }
  41 +
  42 + @Select("SELECT COUNT(*) FROM system_user_role WHERE update_time > #{maxUpdateTime}")
  43 + Long selectCountByUpdateTimeGt(Date maxUpdateTime);
  44 +
39 } 45 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/UserRoleRefreshConsumer.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.mq.consumer.permission;
  2 +
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
  4 +import cn.iocoder.yudao.module.system.mq.message.permission.UserRoleRefreshMessage;
  5 +import cn.iocoder.yudao.module.system.service.permission.PermissionService;
  6 +import lombok.extern.slf4j.Slf4j;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +/**
  12 + * 针对 {@link UserRoleRefreshMessage} 的消费者
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@Component
  17 +@Slf4j
  18 +public class UserRoleRefreshConsumer extends AbstractChannelMessageListener<UserRoleRefreshMessage> {
  19 +
  20 + @Resource
  21 + private PermissionService permissionService;
  22 +
  23 + @Override
  24 + public void onMessage(UserRoleRefreshMessage message) {
  25 + log.info("[onMessage][收到 User 与 Role 的关联刷新消息]");
  26 + permissionService.initLocalCache();
  27 + }
  28 +
  29 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/UserRoleRefreshMessage.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.mq.message.permission;
  2 +
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +
  7 +/**
  8 + * 用户与角色的数据刷新 Message
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class UserRoleRefreshMessage extends AbstractChannelMessage {
  15 +
  16 + @Override
  17 + public String getChannel() {
  18 + return "system.user-role.refresh";
  19 + }
  20 +
  21 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.mq.producer.permission; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.mq.producer.permission;
2 2
3 import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage; 3 import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage;
4 import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; 4 import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
  5 +import cn.iocoder.yudao.module.system.mq.message.permission.UserRoleRefreshMessage;
5 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
6 7
7 import javax.annotation.Resource; 8 import javax.annotation.Resource;
@@ -23,4 +24,12 @@ public class PermissionProducer { @@ -23,4 +24,12 @@ public class PermissionProducer {
23 redisMQTemplate.send(message); 24 redisMQTemplate.send(message);
24 } 25 }
25 26
  27 + /**
  28 + * 发送 {@link UserRoleRefreshMessage} 消息
  29 + */
  30 + public void sendUserRoleRefreshMessage() {
  31 + UserRoleRefreshMessage message = new UserRoleRefreshMessage();
  32 + redisMQTemplate.send(message);
  33 + }
  34 +
26 } 35 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java
@@ -37,13 +37,13 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D @@ -37,13 +37,13 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
37 Collection<Integer> menusStatuses); 37 Collection<Integer> menusStatuses);
38 38
39 /** 39 /**
40 - * 获得用户拥有的角色编号集合 40 + * 获得用户拥有的角色编号集合,从缓存中获取
41 * 41 *
42 * @param userId 用户编号 42 * @param userId 用户编号
43 * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤 43 * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤
44 * @return 角色编号集合 44 * @return 角色编号集合
45 */ 45 */
46 - Set<Long> getUserRoleIds(Long userId, @Nullable Collection<Integer> roleStatuses); 46 + Set<Long> getUserRoleIdsFromCache(Long userId, @Nullable Collection<Integer> roleStatuses);
47 47
48 /** 48 /**
49 * 获得角色拥有的菜单编号集合 49 * 获得角色拥有的菜单编号集合
@@ -54,6 +54,14 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D @@ -54,6 +54,14 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
54 Set<Long> getRoleMenuIds(Long roleId); 54 Set<Long> getRoleMenuIds(Long roleId);
55 55
56 /** 56 /**
  57 + * 获得拥有多个角色的用户编号集合
  58 + *
  59 + * @param roleIds 角色编号集合
  60 + * @return 用户编号集合
  61 + */
  62 + Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds);
  63 +
  64 + /**
57 * 设置角色菜单 65 * 设置角色菜单
58 * 66 *
59 * @param roleId 角色编号 67 * @param roleId 角色编号
@@ -70,14 +78,6 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D @@ -70,14 +78,6 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
70 Set<Long> getUserRoleIdListByUserId(Long userId); 78 Set<Long> getUserRoleIdListByUserId(Long userId);
71 79
72 /** 80 /**
73 - * 获得拥有某个角色的用户编号集合  
74 - *  
75 - * @param roleId 角色编号  
76 - * @return 用户编号集合  
77 - */  
78 - Set<Long> getUserRoleIdListByRoleId(Long roleId);  
79 -  
80 - /**  
81 * 设置用户角色 81 * 设置用户角色
82 * 82 *
83 * @param userId 角色编号 83 * @param userId 角色编号
@@ -115,12 +115,4 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D @@ -115,12 +115,4 @@ public interface PermissionService extends SecurityPermissionFrameworkService, D
115 */ 115 */
116 void processUserDeleted(Long userId); 116 void processUserDeleted(Long userId);
117 117
118 - /**  
119 - * 获得拥有多个角色的用户编号集合  
120 - *  
121 - * @param roleIds 角色编号集合  
122 - * @return 用户编号集合  
123 - */  
124 - Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds);  
125 -  
126 } 118 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
@@ -23,10 +23,13 @@ import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; @@ -23,10 +23,13 @@ import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
23 import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; 23 import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
24 import cn.iocoder.yudao.module.system.service.dept.DeptService; 24 import cn.iocoder.yudao.module.system.service.dept.DeptService;
25 import cn.iocoder.yudao.module.system.service.user.AdminUserService; 25 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
  26 +import com.google.common.annotations.VisibleForTesting;
26 import com.google.common.base.Suppliers; 27 import com.google.common.base.Suppliers;
27 import com.google.common.collect.ImmutableMultimap; 28 import com.google.common.collect.ImmutableMultimap;
28 import com.google.common.collect.Multimap; 29 import com.google.common.collect.Multimap;
29 import com.google.common.collect.Sets; 30 import com.google.common.collect.Sets;
  31 +import lombok.Getter;
  32 +import lombok.Setter;
30 import lombok.extern.slf4j.Slf4j; 33 import lombok.extern.slf4j.Slf4j;
31 import org.springframework.context.annotation.Lazy; 34 import org.springframework.context.annotation.Lazy;
32 import org.springframework.scheduling.annotation.Scheduled; 35 import org.springframework.scheduling.annotation.Scheduled;
@@ -40,6 +43,8 @@ import javax.annotation.Resource; @@ -40,6 +43,8 @@ import javax.annotation.Resource;
40 import java.util.*; 43 import java.util.*;
41 import java.util.function.Supplier; 44 import java.util.function.Supplier;
42 45
  46 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  47 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
43 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 48 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
44 import static java.util.Collections.singleton; 49 import static java.util.Collections.singleton;
45 50
@@ -65,6 +70,8 @@ public class PermissionServiceImpl implements PermissionService { @@ -65,6 +70,8 @@ public class PermissionServiceImpl implements PermissionService {
65 * 70 *
66 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 71 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
67 */ 72 */
  73 + @Getter
  74 + @Setter // 单元测试
68 private volatile Multimap<Long, Long> roleMenuCache; 75 private volatile Multimap<Long, Long> roleMenuCache;
69 /** 76 /**
70 * 菜单编号与角色编号的缓存映射 77 * 菜单编号与角色编号的缓存映射
@@ -73,11 +80,29 @@ public class PermissionServiceImpl implements PermissionService { @@ -73,11 +80,29 @@ public class PermissionServiceImpl implements PermissionService {
73 * 80 *
74 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 81 * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
75 */ 82 */
  83 + @Getter
76 private volatile Multimap<Long, Long> menuRoleCache; 84 private volatile Multimap<Long, Long> menuRoleCache;
77 /** 85 /**
78 - * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新 86 + * 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新
79 */ 87 */
80 - private volatile Date maxUpdateTime; 88 + @Getter
  89 + private volatile Date roleMenuMaxUpdateTime;
  90 +
  91 + /**
  92 + * 用户编号与角色编号的缓存映射
  93 + * key:用户编号
  94 + * value:角色编号的数组
  95 + *
  96 + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
  97 + */
  98 + @Getter
  99 + @Setter // 单元测试需要
  100 + private volatile Map<Long, Set<Long>> userRoleCache;
  101 + /**
  102 + * 缓存 UserRole 的最大更新时间,用于后续的增量轮询,判断是否有更新
  103 + */
  104 + @Getter
  105 + private volatile Date userRoleMaxUpdateTime;
81 106
82 @Resource 107 @Resource
83 private RoleMenuMapper roleMenuMapper; 108 private RoleMenuMapper roleMenuMapper;
@@ -104,15 +129,21 @@ public class PermissionServiceImpl implements PermissionService { @@ -104,15 +129,21 @@ public class PermissionServiceImpl implements PermissionService {
104 @Lazy // 注入自己,所以延迟加载 129 @Lazy // 注入自己,所以延迟加载
105 private PermissionService self; 130 private PermissionService self;
106 131
107 - /**  
108 - * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存  
109 - */  
110 @Override 132 @Override
111 @PostConstruct 133 @PostConstruct
112 @TenantIgnore // 初始化缓存,无需租户过滤 134 @TenantIgnore // 初始化缓存,无需租户过滤
113 public void initLocalCache() { 135 public void initLocalCache() {
  136 + initUserRoleLocalCache();
  137 + initRoleMenuLocalCache();
  138 + }
  139 +
  140 + /**
  141 + * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存
  142 + */
  143 + @VisibleForTesting
  144 + void initRoleMenuLocalCache() {
114 // 获取角色与菜单的关联列表,如果有更新 145 // 获取角色与菜单的关联列表,如果有更新
115 - List<RoleMenuDO> roleMenuList = loadRoleMenuIfUpdate(maxUpdateTime); 146 + List<RoleMenuDO> roleMenuList = loadRoleMenuIfUpdate(roleMenuMaxUpdateTime);
116 if (CollUtil.isEmpty(roleMenuList)) { 147 if (CollUtil.isEmpty(roleMenuList)) {
117 return; 148 return;
118 } 149 }
@@ -126,8 +157,27 @@ public class PermissionServiceImpl implements PermissionService { @@ -126,8 +157,27 @@ public class PermissionServiceImpl implements PermissionService {
126 }); 157 });
127 roleMenuCache = roleMenuCacheBuilder.build(); 158 roleMenuCache = roleMenuCacheBuilder.build();
128 menuRoleCache = menuRoleCacheBuilder.build(); 159 menuRoleCache = menuRoleCacheBuilder.build();
129 - maxUpdateTime = CollectionUtils.getMaxValue(roleMenuList, RoleMenuDO::getUpdateTime);  
130 - log.info("[initLocalCache][初始化角色与菜单的关联数量为 {}]", roleMenuList.size()); 160 + roleMenuMaxUpdateTime = getMaxValue(roleMenuList, RoleMenuDO::getUpdateTime);
  161 + log.info("[initRoleMenuLocalCache][初始化角色与菜单的关联数量为 {}]", roleMenuList.size());
  162 + }
  163 +
  164 + /**
  165 + * 初始化 {@link #userRoleCache} 缓存
  166 + */
  167 + @VisibleForTesting
  168 + void initUserRoleLocalCache() {
  169 + // 获取用户与角色的关联列表,如果有更新
  170 + List<UserRoleDO> userRoleList = loadUserRoleIfUpdate(userRoleMaxUpdateTime);
  171 + if (CollUtil.isEmpty(userRoleList)) {
  172 + return;
  173 + }
  174 +
  175 + // 初始化 userRoleCache 缓存
  176 + ImmutableMultimap.Builder<Long, Long> userRoleCacheBuilder = ImmutableMultimap.builder();
  177 + userRoleList.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId()));
  178 + userRoleCache = CollectionUtils.convertMultiMap2(userRoleList, UserRoleDO::getUserId, UserRoleDO::getRoleId);
  179 + userRoleMaxUpdateTime = getMaxValue(userRoleList, UserRoleDO::getUpdateTime);
  180 + log.info("[initUserRoleLocalCache][初始化用户与角色的关联数量为 {}]", userRoleList.size());
131 } 181 }
132 182
133 @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) 183 @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
@@ -156,6 +206,27 @@ public class PermissionServiceImpl implements PermissionService { @@ -156,6 +206,27 @@ public class PermissionServiceImpl implements PermissionService {
156 return roleMenuMapper.selectList(); 206 return roleMenuMapper.selectList();
157 } 207 }
158 208
  209 + /**
  210 + * 如果用户与角色的关联发生变化,从数据库中获取最新的全量用户与角色的关联。
  211 + * 如果未发生变化,则返回空
  212 + *
  213 + * @param maxUpdateTime 当前角色与菜单的关联的最大更新时间
  214 + * @return 角色与菜单的关联列表
  215 + */
  216 + protected List<UserRoleDO> loadUserRoleIfUpdate(Date maxUpdateTime) {
  217 + // 第一步,判断是否要更新。
  218 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
  219 + log.info("[loadUserRoleIfUpdate][首次加载全量用户与角色的关联]");
  220 + } else { // 判断数据库中是否有更新的用户与角色的关联
  221 + if (userRoleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
  222 + return null;
  223 + }
  224 + log.info("[loadUserRoleIfUpdate][增量加载全量用户与角色的关联]");
  225 + }
  226 + // 第二步,如果有更新,则从数据库加载所有用户与角色的关联
  227 + return userRoleMapper.selectList();
  228 + }
  229 +
159 @Override 230 @Override
160 public List<MenuDO> getRoleMenuListFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes, 231 public List<MenuDO> getRoleMenuListFromCache(Collection<Long> roleIds, Collection<Integer> menuTypes,
161 Collection<Integer> menusStatuses) { 232 Collection<Integer> menusStatuses) {
@@ -176,35 +247,33 @@ public class PermissionServiceImpl implements PermissionService { @@ -176,35 +247,33 @@ public class PermissionServiceImpl implements PermissionService {
176 } 247 }
177 248
178 @Override 249 @Override
179 - public Set<Long> getUserRoleIds(Long userId, Collection<Integer> roleStatuses) {  
180 - List<UserRoleDO> userRoleList = userRoleMapper.selectListByUserId(userId); 250 + public Set<Long> getUserRoleIdsFromCache(Long userId, Collection<Integer> roleStatuses) {
  251 + Set<Long> roleIds = new HashSet<>(userRoleCache.get(userId));
181 // 过滤角色状态 252 // 过滤角色状态
182 if (CollectionUtil.isNotEmpty(roleStatuses)) { 253 if (CollectionUtil.isNotEmpty(roleStatuses)) {
183 - userRoleList.removeIf(userRoleDO -> {  
184 - RoleDO role = roleService.getRoleFromCache(userRoleDO.getRoleId()); 254 + roleIds.removeIf(roleId -> {
  255 + RoleDO role = roleService.getRoleFromCache(roleId);
185 return role == null || !roleStatuses.contains(role.getStatus()); 256 return role == null || !roleStatuses.contains(role.getStatus());
186 }); 257 });
187 } 258 }
188 - return CollectionUtils.convertSet(userRoleList, UserRoleDO::getRoleId); 259 + return roleIds;
189 } 260 }
190 261
191 @Override 262 @Override
192 public Set<Long> getRoleMenuIds(Long roleId) { 263 public Set<Long> getRoleMenuIds(Long roleId) {
193 // 如果是管理员的情况下,获取全部菜单编号 264 // 如果是管理员的情况下,获取全部菜单编号
194 - RoleDO role = roleService.getRole(roleId);  
195 - if (roleService.hasAnySuperAdmin(Collections.singletonList(role))) {  
196 - return CollectionUtils.convertSet(menuService.getMenus(), MenuDO::getId); 265 + if (roleService.hasAnySuperAdmin(Collections.singleton(roleId))) {
  266 + return convertSet(menuService.getMenus(), MenuDO::getId);
197 } 267 }
198 // 如果是非管理员的情况下,获得拥有的菜单编号 268 // 如果是非管理员的情况下,获得拥有的菜单编号
199 - return CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId),  
200 - RoleMenuDO::getMenuId); 269 + return convertSet(roleMenuMapper.selectListByRoleId(roleId), RoleMenuDO::getMenuId);
201 } 270 }
202 271
203 @Override 272 @Override
204 @Transactional(rollbackFor = Exception.class) 273 @Transactional(rollbackFor = Exception.class)
205 public void assignRoleMenu(Long roleId, Set<Long> menuIds) { 274 public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
206 // 获得角色拥有菜单编号 275 // 获得角色拥有菜单编号
207 - Set<Long> dbMenuIds = CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId), 276 + Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId),
208 RoleMenuDO::getMenuId); 277 RoleMenuDO::getMenuId);
209 // 计算新增和删除的菜单编号 278 // 计算新增和删除的菜单编号
210 Collection<Long> createMenuIds = CollUtil.subtract(menuIds, dbMenuIds); 279 Collection<Long> createMenuIds = CollUtil.subtract(menuIds, dbMenuIds);
@@ -234,20 +303,21 @@ public class PermissionServiceImpl implements PermissionService { @@ -234,20 +303,21 @@ public class PermissionServiceImpl implements PermissionService {
234 303
235 @Override 304 @Override
236 public Set<Long> getUserRoleIdListByUserId(Long userId) { 305 public Set<Long> getUserRoleIdListByUserId(Long userId) {
237 - return CollectionUtils.convertSet(userRoleMapper.selectListByUserId(userId), 306 + return convertSet(userRoleMapper.selectListByUserId(userId),
238 UserRoleDO::getRoleId); 307 UserRoleDO::getRoleId);
239 } 308 }
240 309
241 @Override 310 @Override
242 - public Set<Long> getUserRoleIdListByRoleId(Long roleId) {  
243 - return CollectionUtils.convertSet(userRoleMapper.selectListByRoleId(roleId),  
244 - UserRoleDO::getRoleId); 311 + public Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds) {
  312 + return convertSet(userRoleMapper.selectListByRoleIds(roleIds),
  313 + UserRoleDO::getUserId);
245 } 314 }
246 315
247 @Override 316 @Override
  317 + @Transactional(rollbackFor = Exception.class)
248 public void assignUserRole(Long userId, Set<Long> roleIds) { 318 public void assignUserRole(Long userId, Set<Long> roleIds) {
249 // 获得角色拥有角色编号 319 // 获得角色拥有角色编号
250 - Set<Long> dbRoleIds = CollectionUtils.convertSet(userRoleMapper.selectListByUserId(userId), 320 + Set<Long> dbRoleIds = convertSet(userRoleMapper.selectListByUserId(userId),
251 UserRoleDO::getRoleId); 321 UserRoleDO::getRoleId);
252 // 计算新增和删除的角色编号 322 // 计算新增和删除的角色编号
253 Collection<Long> createRoleIds = CollUtil.subtract(roleIds, dbRoleIds); 323 Collection<Long> createRoleIds = CollUtil.subtract(roleIds, dbRoleIds);
@@ -264,6 +334,15 @@ public class PermissionServiceImpl implements PermissionService { @@ -264,6 +334,15 @@ public class PermissionServiceImpl implements PermissionService {
264 if (!CollectionUtil.isEmpty(deleteMenuIds)) { 334 if (!CollectionUtil.isEmpty(deleteMenuIds)) {
265 userRoleMapper.deleteListByUserIdAndRoleIdIds(userId, deleteMenuIds); 335 userRoleMapper.deleteListByUserIdAndRoleIdIds(userId, deleteMenuIds);
266 } 336 }
  337 + // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
  338 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  339 +
  340 + @Override
  341 + public void afterCommit() {
  342 + permissionProducer.sendUserRoleRefreshMessage();
  343 + }
  344 +
  345 + });
267 } 346 }
268 347
269 @Override 348 @Override
@@ -284,6 +363,7 @@ public class PermissionServiceImpl implements PermissionService { @@ -284,6 +363,7 @@ public class PermissionServiceImpl implements PermissionService {
284 @Override 363 @Override
285 public void afterCommit() { 364 public void afterCommit() {
286 permissionProducer.sendRoleMenuRefreshMessage(); 365 permissionProducer.sendRoleMenuRefreshMessage();
  366 + permissionProducer.sendUserRoleRefreshMessage();
287 } 367 }
288 368
289 }); 369 });
@@ -305,8 +385,17 @@ public class PermissionServiceImpl implements PermissionService { @@ -305,8 +385,17 @@ public class PermissionServiceImpl implements PermissionService {
305 } 385 }
306 386
307 @Override 387 @Override
  388 + @Transactional(rollbackFor = Exception.class)
308 public void processUserDeleted(Long userId) { 389 public void processUserDeleted(Long userId) {
309 userRoleMapper.deleteListByUserId(userId); 390 userRoleMapper.deleteListByUserId(userId);
  391 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  392 +
  393 + @Override
  394 + public void afterCommit() {
  395 + permissionProducer.sendUserRoleRefreshMessage();
  396 + }
  397 +
  398 + });
310 } 399 }
311 400
312 @Override 401 @Override
@@ -322,7 +411,7 @@ public class PermissionServiceImpl implements PermissionService { @@ -322,7 +411,7 @@ public class PermissionServiceImpl implements PermissionService {
322 } 411 }
323 412
324 // 获得当前登录的角色。如果为空,说明没有权限 413 // 获得当前登录的角色。如果为空,说明没有权限
325 - Set<Long> roleIds = getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); 414 + Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
326 if (CollUtil.isEmpty(roleIds)) { 415 if (CollUtil.isEmpty(roleIds)) {
327 return false; 416 return false;
328 } 417 }
@@ -357,7 +446,7 @@ public class PermissionServiceImpl implements PermissionService { @@ -357,7 +446,7 @@ public class PermissionServiceImpl implements PermissionService {
357 } 446 }
358 447
359 // 获得当前登录的角色。如果为空,说明没有权限 448 // 获得当前登录的角色。如果为空,说明没有权限
360 - Set<Long> roleIds = getUserRoleIds(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus())); 449 + Set<Long> roleIds = getUserRoleIdsFromCache(getLoginUserId(), singleton(CommonStatusEnum.ENABLE.getStatus()));
361 if (CollUtil.isEmpty(roleIds)) { 450 if (CollUtil.isEmpty(roleIds)) {
362 return false; 451 return false;
363 } 452 }
@@ -365,7 +454,7 @@ public class PermissionServiceImpl implements PermissionService { @@ -365,7 +454,7 @@ public class PermissionServiceImpl implements PermissionService {
365 if (roleService.hasAnySuperAdmin(roleIds)) { 454 if (roleService.hasAnySuperAdmin(roleIds)) {
366 return true; 455 return true;
367 } 456 }
368 - Set<String> userRoles = CollectionUtils.convertSet(roleService.getRolesFromCache(roleIds), 457 + Set<String> userRoles = convertSet(roleService.getRolesFromCache(roleIds),
369 RoleDO::getCode); 458 RoleDO::getCode);
370 return CollUtil.containsAny(userRoles, Sets.newHashSet(roles)); 459 return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
371 } 460 }
@@ -375,7 +464,7 @@ public class PermissionServiceImpl implements PermissionService { @@ -375,7 +464,7 @@ public class PermissionServiceImpl implements PermissionService {
375 public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) { 464 public DeptDataPermissionRespDTO getDeptDataPermission(Long userId) {
376 DeptDataPermissionRespDTO result = new DeptDataPermissionRespDTO(); 465 DeptDataPermissionRespDTO result = new DeptDataPermissionRespDTO();
377 // 获得用户的角色 466 // 获得用户的角色
378 - Set<Long> roleIds = getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); 467 + Set<Long> roleIds = getUserRoleIdsFromCache(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
379 if (CollUtil.isEmpty(roleIds)) { 468 if (CollUtil.isEmpty(roleIds)) {
380 return result; 469 return result;
381 } 470 }
@@ -425,10 +514,4 @@ public class PermissionServiceImpl implements PermissionService { @@ -425,10 +514,4 @@ public class PermissionServiceImpl implements PermissionService {
425 return result; 514 return result;
426 } 515 }
427 516
428 - @Override  
429 - public Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds) {  
430 - return CollectionUtils.convertSet(userRoleMapper.selectListByRoleIds(roleIds),  
431 - UserRoleDO::getUserId);  
432 - }  
433 -  
434 } 517 }
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java
1 package cn.iocoder.yudao.module.system.service.permission; 1 package cn.iocoder.yudao.module.system.service.permission;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.map.MapUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  6 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
5 import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO; 7 import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 8 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
7 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; 9 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
  10 +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
8 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; 11 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
9 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; 12 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
10 import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO; 13 import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
@@ -17,20 +20,24 @@ import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; @@ -17,20 +20,24 @@ import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
17 import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; 20 import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
18 import cn.iocoder.yudao.module.system.service.dept.DeptService; 21 import cn.iocoder.yudao.module.system.service.dept.DeptService;
19 import cn.iocoder.yudao.module.system.service.user.AdminUserService; 22 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
  23 +import com.google.common.collect.ImmutableMultimap;
  24 +import com.google.common.collect.Multimap;
20 import org.junit.jupiter.api.Test; 25 import org.junit.jupiter.api.Test;
21 import org.springframework.boot.test.mock.mockito.MockBean; 26 import org.springframework.boot.test.mock.mockito.MockBean;
22 import org.springframework.context.annotation.Import; 27 import org.springframework.context.annotation.Import;
23 28
24 import javax.annotation.Resource; 29 import javax.annotation.Resource;
25 -import java.util.List; 30 +import java.util.*;
26 31
  32 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 33 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
28 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;  
29 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 34 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  35 +import static java.util.Arrays.asList;
30 import static java.util.Collections.singleton; 36 import static java.util.Collections.singleton;
31 import static java.util.Collections.singletonList; 37 import static java.util.Collections.singletonList;
32 import static org.junit.jupiter.api.Assertions.*; 38 import static org.junit.jupiter.api.Assertions.*;
33 import static org.mockito.ArgumentMatchers.eq; 39 import static org.mockito.ArgumentMatchers.eq;
  40 +import static org.mockito.ArgumentMatchers.same;
34 import static org.mockito.Mockito.verify; 41 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when; 42 import static org.mockito.Mockito.when;
36 43
@@ -63,6 +70,226 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -63,6 +70,226 @@ public class PermissionServiceTest extends BaseDbUnitTest {
63 private PermissionProducer permissionProducer; 70 private PermissionProducer permissionProducer;
64 71
65 @Test 72 @Test
  73 + public void testInitRoleMenuLocalCache() {
  74 + // mock 数据
  75 + RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L));
  76 + roleMenuMapper.insert(roleMenuDO01);
  77 + RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(20L));
  78 + roleMenuMapper.insert(roleMenuDO02);
  79 +
  80 + // 调用
  81 + permissionService.initRoleMenuLocalCache();
  82 + // 断言 roleMenuCache 缓存
  83 + assertEquals(1, permissionService.getRoleMenuCache().keySet().size());
  84 + assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L));
  85 + // 断言 menuRoleCache 缓存
  86 + assertEquals(2, permissionService.getMenuRoleCache().size());
  87 + assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(10L));
  88 + assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(20L));
  89 + // 断言 maxUpdateTime 缓存
  90 + Date maxUpdateTime = permissionService.getRoleMenuMaxUpdateTime();
  91 + assertEquals(ObjectUtils.max(roleMenuDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime);
  92 + }
  93 +
  94 + @Test
  95 + public void testInitUserRoleLocalCache() {
  96 + // mock 数据
  97 + UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
  98 + userRoleMapper.insert(userRoleDO01);
  99 + UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
  100 + userRoleMapper.insert(roleMenuDO02);
  101 +
  102 + // 调用
  103 + permissionService.initUserRoleLocalCache();
  104 + // 断言 roleMenuCache 缓存
  105 + assertEquals(1, permissionService.getUserRoleCache().size());
  106 + assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L));
  107 + // 断言 maxUpdateTime 缓存
  108 + Date maxUpdateTime = permissionService.getUserRoleMaxUpdateTime();
  109 + assertEquals(ObjectUtils.max(userRoleDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime);
  110 + }
  111 +
  112 + @Test
  113 + public void testGetRoleMenuListFromCache_superAdmin() {
  114 + // 准备参数
  115 + Collection<Long> roleIds = singletonList(100L);
  116 + Collection<Integer> menuTypes = asList(2, 3);
  117 + Collection<Integer> menusStatuses = asList(0, 1);
  118 + // mock 方法
  119 + List<RoleDO> roleList = singletonList(randomPojo(RoleDO.class, o -> o.setId(100L)));
  120 + when(roleService.getRolesFromCache(eq(roleIds))).thenReturn(roleList);
  121 + when(roleService.hasAnySuperAdmin(same(roleList))).thenReturn(true);
  122 + List<MenuDO> menuList = randomPojoList(MenuDO.class);
  123 + when(menuService.getMenuListFromCache(eq(menuTypes), eq(menusStatuses))).thenReturn(menuList);
  124 +
  125 + // 调用
  126 + List<MenuDO> result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses);
  127 + // 断言
  128 + assertSame(menuList, result);
  129 + }
  130 +
  131 + @Test
  132 + public void testGetRoleMenuListFromCache_normal() {
  133 + // 准备参数
  134 + Collection<Long> roleIds = asSet(100L, 200L);
  135 + Collection<Integer> menuTypes = asList(2, 3);
  136 + Collection<Integer> menusStatuses = asList(0, 1);
  137 + // mock 方法
  138 + Multimap<Long, Long> roleMenuCache = ImmutableMultimap.<Long, Long>builder().put(100L, 1000L)
  139 + .put(200L, 2000L).put(200L, 2001L).build();
  140 + permissionService.setRoleMenuCache(roleMenuCache);
  141 + List<MenuDO> menuList = randomPojoList(MenuDO.class);
  142 + when(menuService.getMenuListFromCache(eq(asList(1000L, 2000L, 2001L)), eq(menuTypes), eq(menusStatuses))).thenReturn(menuList);
  143 +
  144 + // 调用
  145 + List<MenuDO> result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses);
  146 + // 断言
  147 + assertSame(menuList, result);
  148 + }
  149 +
  150 + @Test
  151 + public void testGetUserRoleIdsFromCache() {
  152 + // 准备参数
  153 + Long userId = 1L;
  154 + Collection<Integer> roleStatuses = singleton(CommonStatusEnum.ENABLE.getStatus());
  155 + // mock 方法
  156 + Map<Long, Set<Long>> userRoleCache = MapUtil.<Long, Set<Long>>builder()
  157 + .put(1L, asSet(10L, 20L)).build();
  158 + permissionService.setUserRoleCache(userRoleCache);
  159 + RoleDO roleDO01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
  160 + when(roleService.getRoleFromCache(eq(10L))).thenReturn(roleDO01);
  161 + RoleDO roleDO02 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
  162 + when(roleService.getRoleFromCache(eq(20L))).thenReturn(roleDO02);
  163 +
  164 + // 调用
  165 + Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(userId, roleStatuses);
  166 + // 断言
  167 + assertEquals(asSet(10L), roleIds);
  168 + }
  169 +
  170 + @Test
  171 + public void testGetRoleMenuIds_superAdmin() {
  172 + // 准备参数
  173 + Long roleId = 100L;
  174 + // mock 方法
  175 + when(roleService.hasAnySuperAdmin(eq(singleton(100L)))).thenReturn(true);
  176 + List<MenuDO> menuList = singletonList(randomPojo(MenuDO.class).setId(1L));
  177 + when(menuService.getMenus()).thenReturn(menuList);
  178 +
  179 + // 调用
  180 + Set<Long> menuIds = permissionService.getRoleMenuIds(roleId);
  181 + // 断言
  182 + assertEquals(singleton(1L), menuIds);
  183 + }
  184 +
  185 + @Test
  186 + public void testGetRoleMenuIds_normal() {
  187 + // 准备参数
  188 + Long roleId = 100L;
  189 + // mock 数据
  190 + RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(1L);
  191 + roleMenuMapper.insert(roleMenu01);
  192 + RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(2L);
  193 + roleMenuMapper.insert(roleMenu02);
  194 +
  195 + // 调用
  196 + Set<Long> menuIds = permissionService.getRoleMenuIds(roleId);
  197 + // 断言
  198 + assertEquals(asSet(1L, 2L), menuIds);
  199 + }
  200 +
  201 + @Test
  202 + public void testAssignRoleMenu() {
  203 + // 准备参数
  204 + Long roleId = 1L;
  205 + Set<Long> menuIds = asSet(200L, 300L);
  206 + // mock 数据
  207 + RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(100L);
  208 + roleMenuMapper.insert(roleMenu01);
  209 + RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(200L);
  210 + roleMenuMapper.insert(roleMenu02);
  211 +
  212 + // 调用
  213 + permissionService.assignRoleMenu(roleId, menuIds);
  214 + // 断言
  215 + List<RoleMenuDO> roleMenuList = roleMenuMapper.selectList();
  216 + assertEquals(2, roleMenuList.size());
  217 + assertEquals(1L, roleMenuList.get(0).getRoleId());
  218 + assertEquals(200L, roleMenuList.get(0).getMenuId());
  219 + assertEquals(1L, roleMenuList.get(1).getRoleId());
  220 + assertEquals(300L, roleMenuList.get(1).getMenuId());
  221 + verify(permissionProducer).sendRoleMenuRefreshMessage();
  222 + }
  223 +
  224 + @Test
  225 + public void testAssignUserRole() {
  226 + // 准备参数
  227 + Long userId = 1L;
  228 + Set<Long> roleIds = asSet(200L, 300L);
  229 + // mock 数据
  230 + UserRoleDO userRole01 = randomPojo(UserRoleDO.class).setUserId(1L).setRoleId(100L);
  231 + userRoleMapper.insert(userRole01);
  232 + UserRoleDO userRole02 = randomPojo(UserRoleDO.class).setUserId(1L).setRoleId(200L);
  233 + userRoleMapper.insert(userRole02);
  234 +
  235 + // 调用
  236 + permissionService.assignUserRole(userId, roleIds);
  237 + // 断言
  238 + List<UserRoleDO> userRoleDOList = userRoleMapper.selectList();
  239 + assertEquals(2, userRoleDOList.size());
  240 + assertEquals(1L, userRoleDOList.get(0).getUserId());
  241 + assertEquals(200L, userRoleDOList.get(0).getRoleId());
  242 + assertEquals(1L, userRoleDOList.get(1).getUserId());
  243 + assertEquals(300L, userRoleDOList.get(1).getRoleId());
  244 + verify(permissionProducer).sendUserRoleRefreshMessage();
  245 + }
  246 +
  247 + @Test
  248 + public void testGetUserRoleIdListByUserId() {
  249 + // 准备参数
  250 + Long userId = 1L;
  251 + // mock 数据
  252 + UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
  253 + userRoleMapper.insert(userRoleDO01);
  254 + UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
  255 + userRoleMapper.insert(roleMenuDO02);
  256 +
  257 + // 调用
  258 + Set<Long> result = permissionService.getUserRoleIdListByUserId(userId);
  259 + // 断言
  260 + assertEquals(asSet(10L, 20L), result);
  261 + }
  262 +
  263 + @Test
  264 + public void testGetUserRoleIdListByRoleIds() {
  265 + // 准备参数
  266 + Collection<Long> roleIds = asSet(10L, 20L);
  267 + // mock 数据
  268 + UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
  269 + userRoleMapper.insert(userRoleDO01);
  270 + UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(2L).setRoleId(20L));
  271 + userRoleMapper.insert(roleMenuDO02);
  272 +
  273 + // 调用
  274 + Set<Long> result = permissionService.getUserRoleIdListByRoleIds(roleIds);
  275 + // 断言
  276 + assertEquals(asSet(1L, 2L), result);
  277 + }
  278 +
  279 + @Test
  280 + public void testAssignRoleDataScope() {
  281 + // 准备参数
  282 + Long roleId = 1L;
  283 + Integer dataScope = 2;
  284 + Set<Long> dataScopeDeptIds = asSet(10L, 20L);
  285 +
  286 + // 调用
  287 + permissionService.assignRoleDataScope(roleId, dataScope, dataScopeDeptIds);
  288 + // 断言
  289 + verify(roleService).updateRoleDataScope(eq(roleId), eq(dataScope), eq(dataScopeDeptIds));
  290 + }
  291 +
  292 + @Test
66 public void testProcessRoleDeleted() { 293 public void testProcessRoleDeleted() {
67 // 准备参数 294 // 准备参数
68 Long roleId = randomLongId(); 295 Long roleId = randomLongId();
@@ -89,6 +316,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -89,6 +316,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
89 assertPojoEquals(dbUserRoles.get(0), userRoleDO02); 316 assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
90 // 断言调用 317 // 断言调用
91 verify(permissionProducer).sendRoleMenuRefreshMessage(); 318 verify(permissionProducer).sendRoleMenuRefreshMessage();
  319 + verify(permissionProducer).sendUserRoleRefreshMessage();
92 } 320 }
93 321
94 @Test 322 @Test
@@ -127,14 +355,33 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -127,14 +355,33 @@ public class PermissionServiceTest extends BaseDbUnitTest {
127 List<UserRoleDO> dbUserRoles = userRoleMapper.selectList(); 355 List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
128 assertEquals(1, dbUserRoles.size()); 356 assertEquals(1, dbUserRoles.size());
129 assertPojoEquals(dbUserRoles.get(0), userRoleDO02); 357 assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
  358 + // 断言调用
  359 + verify(permissionProducer).sendUserRoleRefreshMessage();
130 } 360 }
131 361
  362 +// @Test
  363 +// public void testHasAnyRoles_superAdmin() {
  364 +// // 准备参数
  365 +// String[] roles = new String[]{"yunai", "tudou"};
  366 +// // mock 方法
  367 +// List<RoleDO> roleList = singletonList(randomPojo(RoleDO.class, o -> o.setId(100L)));
  368 +// when(roleService.getRolesFromCache(eq(roleIds))).thenReturn(roleList);
  369 +// when(roleService.hasAnySuperAdmin(same(roleList))).thenReturn(true);
  370 +// List<MenuDO> menuList = randomPojoList(MenuDO.class);
  371 +// when(menuService.getMenuListFromCache(eq(menuTypes), eq(menusStatuses))).thenReturn(menuList);
  372 +//
  373 +// // 调用
  374 +// List<MenuDO> result = permissionService.getRoleMenuListFromCache(roleIds, menuTypes, menusStatuses);
  375 +// // 断言
  376 +// assertSame(menuList, result);
  377 +// }
  378 +
132 @Test 379 @Test
133 public void testGetDeptDataPermission_All() { 380 public void testGetDeptDataPermission_All() {
134 // 准备参数 381 // 准备参数
135 Long userId = 1L; 382 Long userId = 1L;
136 // mock 用户的角色编号 383 // mock 用户的角色编号
137 - userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L)); 384 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
138 // mock 获得用户的角色 385 // mock 获得用户的角色
139 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope()) 386 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())
140 .setStatus(CommonStatusEnum.ENABLE.getStatus())); 387 .setStatus(CommonStatusEnum.ENABLE.getStatus()));
@@ -154,7 +401,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -154,7 +401,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
154 // 准备参数 401 // 准备参数
155 Long userId = 1L; 402 Long userId = 1L;
156 // mock 用户的角色编号 403 // mock 用户的角色编号
157 - userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L)); 404 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
158 // mock 获得用户的角色 405 // mock 获得用户的角色
159 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope()) 406 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())
160 .setStatus(CommonStatusEnum.ENABLE.getStatus())); 407 .setStatus(CommonStatusEnum.ENABLE.getStatus()));
@@ -164,7 +411,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -164,7 +411,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
164 when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用 411 when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
165 412
166 // 调用 413 // 调用
167 - DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(1L); 414 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
168 // 断言 415 // 断言
169 assertFalse(result.getAll()); 416 assertFalse(result.getAll());
170 assertFalse(result.getSelf()); 417 assertFalse(result.getSelf());
@@ -178,7 +425,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -178,7 +425,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
178 // 准备参数 425 // 准备参数
179 Long userId = 1L; 426 Long userId = 1L;
180 // mock 用户的角色编号 427 // mock 用户的角色编号
181 - userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L)); 428 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
182 // mock 获得用户的角色 429 // mock 获得用户的角色
183 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope()) 430 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())
184 .setStatus(CommonStatusEnum.ENABLE.getStatus())); 431 .setStatus(CommonStatusEnum.ENABLE.getStatus()));
@@ -188,7 +435,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -188,7 +435,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
188 when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用 435 when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
189 436
190 // 调用 437 // 调用
191 - DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(1L); 438 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
192 // 断言 439 // 断言
193 assertFalse(result.getAll()); 440 assertFalse(result.getAll());
194 assertFalse(result.getSelf()); 441 assertFalse(result.getSelf());
@@ -201,7 +448,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -201,7 +448,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
201 // 准备参数 448 // 准备参数
202 Long userId = 1L; 449 Long userId = 1L;
203 // mock 用户的角色编号 450 // mock 用户的角色编号
204 - userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L)); 451 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
205 // mock 获得用户的角色 452 // mock 获得用户的角色
206 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope()) 453 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())
207 .setStatus(CommonStatusEnum.ENABLE.getStatus())); 454 .setStatus(CommonStatusEnum.ENABLE.getStatus()));
@@ -229,7 +476,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { @@ -229,7 +476,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
229 // 准备参数 476 // 准备参数
230 Long userId = 1L; 477 Long userId = 1L;
231 // mock 用户的角色编号 478 // mock 用户的角色编号
232 - userRoleMapper.insert(new UserRoleDO().setUserId(userId).setRoleId(2L)); 479 + permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
233 // mock 获得用户的角色 480 // mock 获得用户的角色
234 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope()) 481 RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())
235 .setStatus(CommonStatusEnum.ENABLE.getStatus())); 482 .setStatus(CommonStatusEnum.ENABLE.getStatus()));