Commit 97e842a59f0d7832af3a7e416d465c0c1af63433

Authored by YunaiV
1 parent f4818d26

完善 role、user、menu 删除时,对权限的影响

src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java
... ... @@ -81,7 +81,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
81 81 Map<String, String> queryString, String requestBody, Exception ex) {
82 82 // 处理用户信息
83 83 accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
84   - accessLog.setUserType(WebFrameworkUtils.getUesrType(request));
  84 + accessLog.setUserType(WebFrameworkUtils.getUserType(request));
85 85 // 设置访问结果
86 86 CommonResult<?> result = WebFrameworkUtils.getCommonResult(request);
87 87 if (result != null) {
... ...
src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java
... ... @@ -269,7 +269,7 @@ public class GlobalExceptionHandler {
269 269 private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) {
270 270 // 处理用户信息
271 271 errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
272   - errorLog.setUserType(WebFrameworkUtils.getUesrType(request));
  272 + errorLog.setUserType(WebFrameworkUtils.getUserType(request));
273 273 // 设置异常字段
274 274 errorLog.setExceptionName(e.getClass().getName());
275 275 errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));
... ...
src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java
... ... @@ -31,7 +31,7 @@ public class WebFrameworkUtils {
31 31 return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID);
32 32 }
33 33  
34   - public static Integer getUesrType(HttpServletRequest request) {
  34 + public static Integer getUserType(HttpServletRequest request) {
35 35 return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化
36 36 }
37 37  
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java
... ... @@ -33,6 +33,14 @@ public interface SysRoleMenuMapper extends BaseMapperX&lt;SysRoleMenuDO&gt; {
33 33 .in("menu_id", menuIds));
34 34 }
35 35  
  36 + default void deleteListByMenuId(Long menuId) {
  37 + delete(new QueryWrapper<SysRoleMenuDO>().eq("menu_id", menuId));
  38 + }
  39 +
  40 + default void deleteListByRoleId(Long roleId) {
  41 + delete(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId));
  42 + }
  43 +
36 44 default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
37 45 return selectOne(new QueryWrapper<SysRoleMenuDO>().select("id")
38 46 .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java
1 1 package cn.iocoder.dashboard.modules.system.dal.mysql.permission;
2 2  
  3 +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
3 4 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysUserRoleDO;
4 5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5   -import com.baomidou.mybatisplus.core.mapper.BaseMapper;
6 6 import org.apache.ibatis.annotations.Mapper;
7 7  
8 8 import java.util.Collection;
... ... @@ -10,7 +10,7 @@ import java.util.List;
10 10 import java.util.stream.Collectors;
11 11  
12 12 @Mapper
13   -public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
  13 +public interface SysUserRoleMapper extends BaseMapperX<SysUserRoleDO> {
14 14  
15 15 default List<SysUserRoleDO> selectListByUserId(Long userId) {
16 16 return selectList(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
... ... @@ -32,4 +32,12 @@ public interface SysUserRoleMapper extends BaseMapper&lt;SysUserRoleDO&gt; {
32 32 .in("role_id", roleIds));
33 33 }
34 34  
  35 + default void deleteListByUserId(Long userId) {
  36 + delete(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
  37 + }
  38 +
  39 + default void deleteListByRoleId(Long roleId) {
  40 + delete(new QueryWrapper<SysUserRoleDO>().eq("role_id", roleId));
  41 + }
  42 +
35 43 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java
... ... @@ -153,7 +153,6 @@ public class SysDeptServiceImpl implements SysDeptService {
153 153 }
154 154 // 删除部门
155 155 deptMapper.deleteById(id);
156   - // TODO 需要处理下与角色的数据权限关联,等做数据权限一起处理下
157 156 // 发送刷新消息
158 157 deptProducer.sendDeptRefreshMessage();
159 158 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java
... ... @@ -231,22 +231,41 @@ public class SysPermissionServiceImpl implements SysPermissionService {
231 231 }
232 232  
233 233 @Override
  234 + @Transactional(rollbackFor = Exception.class)
234 235 public void processRoleDeleted(Long roleId) {
235   - // TODO 实现我
236   -// // 标记删除 RoleResource
237   -// roleResourceMapper.deleteByRoleId(roleId);
238   -// // 标记删除 AdminRole
239   -// adminRoleMapper.deleteByRoleId(roleId);
  236 + // 标记删除 UserRole
  237 + userRoleMapper.deleteListByRoleId(roleId);
  238 + // 标记删除 RoleMenu
  239 + roleMenuMapper.deleteListByRoleId(roleId);
  240 + // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
  241 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  242 +
  243 + @Override
  244 + public void afterCommit() {
  245 + permissionProducer.sendRoleMenuRefreshMessage();
  246 + }
  247 +
  248 + });
240 249 }
241 250  
242 251 @Override
  252 + @Transactional(rollbackFor = Exception.class)
243 253 public void processMenuDeleted(Long menuId) {
244   - // TODO 实现我
  254 + roleMenuMapper.deleteListByMenuId(menuId);
  255 + // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
  256 + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
  257 +
  258 + @Override
  259 + public void afterCommit() {
  260 + permissionProducer.sendRoleMenuRefreshMessage();
  261 + }
  262 +
  263 + });
245 264 }
246 265  
247 266 @Override
248 267 public void processUserDeleted(Long userId) {
249   - // TODO 实现我
  268 + userRoleMapper.deleteListByUserId(userId);
250 269 }
251 270  
252 271 @Override
... ...
src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java
... ... @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
9 9 import org.redisson.spring.starter.RedissonAutoConfiguration;
10 10 import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
11 11 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  12 +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
12 13 import org.springframework.boot.test.context.SpringBootTest;
13 14 import org.springframework.context.annotation.Import;
14 15 import org.springframework.test.context.ActiveProfiles;
... ... @@ -30,6 +31,7 @@ public class BaseDbAndRedisUnitTest {
30 31 // DB 配置类
31 32 DataSourceConfiguration.class, // 自己的 DB 配置类
32 33 DataSourceAutoConfiguration.class, // Spring DB 自动配置类
  34 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
33 35 DruidDataSourceAutoConfigure.class, // Druid 自动配置类
34 36 // MyBatis 配置类
35 37 MybatisConfiguration.class, // 自己的 MyBatis 配置类
... ...
src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java
... ... @@ -5,6 +5,7 @@ import cn.iocoder.dashboard.framework.mybatis.config.MybatisConfiguration;
5 5 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
6 6 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
7 7 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  8 +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
8 9 import org.springframework.boot.test.context.SpringBootTest;
9 10 import org.springframework.context.annotation.Import;
10 11 import org.springframework.test.context.ActiveProfiles;
... ... @@ -26,6 +27,7 @@ public class BaseDbUnitTest {
26 27 // DB 配置类
27 28 DataSourceConfiguration.class, // 自己的 DB 配置类
28 29 DataSourceAutoConfiguration.class, // Spring DB 自动配置类
  30 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
29 31 DruidDataSourceAutoConfigure.class, // Druid 自动配置类
30 32 // MyBatis 配置类
31 33 MybatisConfiguration.class, // 自己的 MyBatis 配置类
... ...
src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionServiceTest.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.permission;
  2 +
  3 +import cn.iocoder.dashboard.BaseDbUnitTest;
  4 +import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleMenuDO;
  5 +import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysUserRoleDO;
  6 +import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMenuMapper;
  7 +import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysUserRoleMapper;
  8 +import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysPermissionProducer;
  9 +import cn.iocoder.dashboard.modules.system.service.permission.impl.SysPermissionServiceImpl;
  10 +import org.junit.jupiter.api.Test;
  11 +import org.springframework.boot.test.mock.mockito.MockBean;
  12 +import org.springframework.context.annotation.Import;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.List;
  16 +
  17 +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
  18 +import static cn.iocoder.dashboard.util.RandomUtils.randomLongId;
  19 +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
  20 +import static org.junit.jupiter.api.Assertions.assertEquals;
  21 +import static org.mockito.Mockito.verify;
  22 +
  23 +@Import(SysPermissionServiceImpl.class)
  24 +public class SysPermissionServiceTest extends BaseDbUnitTest {
  25 +
  26 + @Resource
  27 + private SysPermissionServiceImpl permissionService;
  28 +
  29 + @Resource
  30 + private SysRoleMenuMapper roleMenuMapper;
  31 + @Resource
  32 + private SysUserRoleMapper userRoleMapper;
  33 +
  34 + @MockBean
  35 + private SysRoleService roleService;
  36 + @MockBean
  37 + private SysMenuService menuService;
  38 +
  39 + @MockBean
  40 + private SysPermissionProducer permissionProducer;
  41 +
  42 + @Test
  43 + public void testProcessRoleDeleted() {
  44 + // 准备参数
  45 + Long roleId = randomLongId();
  46 + // mock 数据 UserRole
  47 + SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除
  48 + userRoleMapper.insert(userRoleDO01);
  49 + SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除
  50 + userRoleMapper.insert(userRoleDO02);
  51 + // mock 数据 RoleMenu
  52 + SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除
  53 + roleMenuMapper.insert(roleMenuDO01);
  54 + SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除
  55 + roleMenuMapper.insert(roleMenuDO02);
  56 +
  57 + // 调用
  58 + permissionService.processRoleDeleted(roleId);
  59 + // 断言数据 RoleMenuDO
  60 + List<SysRoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
  61 + assertEquals(1, dbRoleMenus.size());
  62 + assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
  63 + // 断言数据 UserRoleDO
  64 + List<SysUserRoleDO> dbUserRoles = userRoleMapper.selectList();
  65 + assertEquals(1, dbUserRoles.size());
  66 + assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
  67 + // 断言调用
  68 + verify(permissionProducer).sendRoleMenuRefreshMessage();
  69 + }
  70 +
  71 + @Test
  72 + public void testProcessMenuDeleted() {
  73 + // 准备参数
  74 + Long menuId = randomLongId();
  75 + // mock 数据
  76 + SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除
  77 + roleMenuMapper.insert(roleMenuDO01);
  78 + SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除
  79 + roleMenuMapper.insert(roleMenuDO02);
  80 +
  81 + // 调用
  82 + permissionService.processMenuDeleted(menuId);
  83 + // 断言数据
  84 + List<SysRoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
  85 + assertEquals(1, dbRoleMenus.size());
  86 + assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
  87 + // 断言调用
  88 + verify(permissionProducer).sendRoleMenuRefreshMessage();
  89 + }
  90 +
  91 + @Test
  92 + public void testProcessUserDeleted() {
  93 + // 准备参数
  94 + Long userId = randomLongId();
  95 + // mock 数据
  96 + SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setUserId(userId)); // 被删除
  97 + userRoleMapper.insert(userRoleDO01);
  98 + SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除
  99 + userRoleMapper.insert(userRoleDO02);
  100 +
  101 + // 调用
  102 + permissionService.processUserDeleted(userId);
  103 + // 断言数据
  104 + List<SysUserRoleDO> dbUserRoles = userRoleMapper.selectList();
  105 + assertEquals(1, dbUserRoles.size());
  106 + assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
  107 + }
  108 +
  109 +}
... ...
src/test/resources/sql/clean.sql
... ... @@ -8,6 +8,7 @@ DELETE FROM &quot;sys_dict_data&quot;;
8 8 DELETE FROM "sys_role";
9 9 DELETE FROM "sys_role_menu";
10 10 DELETE FROM "sys_menu";
  11 +DELETE FROM "sys_user_role";
11 12 DELETE FROM "sys_dict_type";
12 13 DELETE FROM "sys_user_session";
13 14 DELETE FROM "sys_post";
... ...
src/test/resources/sql/create_tables.sql
... ... @@ -113,6 +113,18 @@ CREATE TABLE IF NOT EXISTS &quot;sys_menu&quot; (
113 113 PRIMARY KEY ("id")
114 114 ) COMMENT '菜单权限表';
115 115  
  116 +CREATE TABLE IF NOT EXISTS "sys_user_role" (
  117 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  118 + "user_id" bigint NOT NULL,
  119 + "role_id" bigint NOT NULL,
  120 + "creator" varchar(64) DEFAULT '',
  121 + "create_time" timestamp DEFAULT NULL,
  122 + "updater" varchar(64) DEFAULT '',
  123 + "update_time" timestamp DEFAULT NULL,
  124 + "deleted" bit DEFAULT FALSE,
  125 + PRIMARY KEY ("id")
  126 +) COMMENT '用户和角色关联表';
  127 +
116 128 CREATE TABLE IF NOT EXISTS "sys_dict_type" (
117 129 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
118 130 "name" varchar(100) NOT NULL DEFAULT '',
... ... @@ -297,4 +309,4 @@ create table &quot;inf_api_error_log&quot; (
297 309 "update_time" timestamp not null default current_timestamp,
298 310 "deleted" bit not null default false,
299 311 primary key ("id")
300   -) comment '系统异常日志';
301 312 \ No newline at end of file
  313 +) comment '系统异常日志';
... ...