瀏覽代碼

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

YunaiV 4 年之前
父節點
當前提交
97e842a59f

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java

@@ -81,7 +81,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
                                       Map<String, String> queryString, String requestBody, Exception ex) {
         // 处理用户信息
         accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
-        accessLog.setUserType(WebFrameworkUtils.getUesrType(request));
+        accessLog.setUserType(WebFrameworkUtils.getUserType(request));
         // 设置访问结果
         CommonResult<?> result = WebFrameworkUtils.getCommonResult(request);
         if (result != null) {

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java

@@ -269,7 +269,7 @@ public class GlobalExceptionHandler {
     private void initExceptionLog(ApiErrorLogCreateDTO errorLog, HttpServletRequest request, Throwable e) {
         // 处理用户信息
         errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
-        errorLog.setUserType(WebFrameworkUtils.getUesrType(request));
+        errorLog.setUserType(WebFrameworkUtils.getUserType(request));
         // 设置异常字段
         errorLog.setExceptionName(e.getClass().getName());
         errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));

+ 1 - 1
src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java

@@ -31,7 +31,7 @@ public class WebFrameworkUtils {
         return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID);
     }
 
-    public static Integer getUesrType(HttpServletRequest request) {
+    public static Integer getUserType(HttpServletRequest request) {
         return UserTypeEnum.ADMIN.getValue(); // TODO 芋艿:等后续优化
     }
 

+ 8 - 0
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java

@@ -33,6 +33,14 @@ public interface SysRoleMenuMapper extends BaseMapperX<SysRoleMenuDO> {
                 .in("menu_id", menuIds));
     }
 
+    default void deleteListByMenuId(Long menuId) {
+        delete(new QueryWrapper<SysRoleMenuDO>().eq("menu_id", menuId));
+    }
+
+    default void deleteListByRoleId(Long roleId) {
+        delete(new QueryWrapper<SysRoleMenuDO>().eq("role_id", roleId));
+    }
+
     default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
         return selectOne(new QueryWrapper<SysRoleMenuDO>().select("id")
                 .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;

+ 10 - 2
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java

@@ -1,8 +1,8 @@
 package cn.iocoder.dashboard.modules.system.dal.mysql.permission;
 
+import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysUserRoleDO;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.Collection;
@@ -10,7 +10,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Mapper
-public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
+public interface SysUserRoleMapper extends BaseMapperX<SysUserRoleDO> {
 
     default List<SysUserRoleDO> selectListByUserId(Long userId) {
         return selectList(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
@@ -32,4 +32,12 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRoleDO> {
                 .in("role_id", roleIds));
     }
 
+    default void deleteListByUserId(Long userId) {
+        delete(new QueryWrapper<SysUserRoleDO>().eq("user_id", userId));
+    }
+
+    default void deleteListByRoleId(Long roleId) {
+        delete(new QueryWrapper<SysUserRoleDO>().eq("role_id", roleId));
+    }
+
 }

+ 0 - 1
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java

@@ -153,7 +153,6 @@ public class SysDeptServiceImpl implements SysDeptService {
         }
         // 删除部门
         deptMapper.deleteById(id);
-        // TODO 需要处理下与角色的数据权限关联,等做数据权限一起处理下
         // 发送刷新消息
         deptProducer.sendDeptRefreshMessage();
     }

+ 26 - 7
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java

@@ -231,22 +231,41 @@ public class SysPermissionServiceImpl implements SysPermissionService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void processRoleDeleted(Long roleId) {
-        // TODO 实现我
-//        // 标记删除 RoleResource
-//        roleResourceMapper.deleteByRoleId(roleId);
-//        // 标记删除 AdminRole
-//        adminRoleMapper.deleteByRoleId(roleId);
+        // 标记删除 UserRole
+        userRoleMapper.deleteListByRoleId(roleId);
+        // 标记删除 RoleMenu
+        roleMenuMapper.deleteListByRoleId(roleId);
+        // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+
+            @Override
+            public void afterCommit() {
+                permissionProducer.sendRoleMenuRefreshMessage();
+            }
+
+        });
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void processMenuDeleted(Long menuId) {
-        // TODO 实现我
+        roleMenuMapper.deleteListByMenuId(menuId);
+        // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了
+        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+
+            @Override
+            public void afterCommit() {
+                permissionProducer.sendRoleMenuRefreshMessage();
+            }
+
+        });
     }
 
     @Override
     public void processUserDeleted(Long userId) {
-        // TODO 实现我
+        userRoleMapper.deleteListByUserId(userId);
     }
 
     @Override

+ 2 - 0
src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
 import org.redisson.spring.starter.RedissonAutoConfiguration;
 import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.Import;
 import org.springframework.test.context.ActiveProfiles;
@@ -30,6 +31,7 @@ public class BaseDbAndRedisUnitTest {
             // DB 配置类
             DataSourceConfiguration.class, // 自己的 DB 配置类
             DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
             DruidDataSourceAutoConfigure.class, // Druid 自动配置类
             // MyBatis 配置类
             MybatisConfiguration.class, // 自己的 MyBatis 配置类

+ 2 - 0
src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java

@@ -5,6 +5,7 @@ import cn.iocoder.dashboard.framework.mybatis.config.MybatisConfiguration;
 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.Import;
 import org.springframework.test.context.ActiveProfiles;
@@ -26,6 +27,7 @@ public class BaseDbUnitTest {
             // DB 配置类
             DataSourceConfiguration.class, // 自己的 DB 配置类
             DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
             DruidDataSourceAutoConfigure.class, // Druid 自动配置类
             // MyBatis 配置类
             MybatisConfiguration.class, // 自己的 MyBatis 配置类

+ 109 - 0
src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionServiceTest.java

@@ -0,0 +1,109 @@
+package cn.iocoder.dashboard.modules.system.service.permission;
+
+import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleMenuDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysUserRoleDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMenuMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysUserRoleMapper;
+import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysPermissionProducer;
+import cn.iocoder.dashboard.modules.system.service.permission.impl.SysPermissionServiceImpl;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.dashboard.util.RandomUtils.randomLongId;
+import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.verify;
+
+@Import(SysPermissionServiceImpl.class)
+public class SysPermissionServiceTest extends BaseDbUnitTest {
+
+    @Resource
+    private SysPermissionServiceImpl permissionService;
+
+    @Resource
+    private SysRoleMenuMapper roleMenuMapper;
+    @Resource
+    private SysUserRoleMapper userRoleMapper;
+
+    @MockBean
+    private SysRoleService roleService;
+    @MockBean
+    private SysMenuService menuService;
+
+    @MockBean
+    private SysPermissionProducer permissionProducer;
+
+    @Test
+    public void testProcessRoleDeleted() {
+        // 准备参数
+        Long roleId = randomLongId();
+        // mock 数据 UserRole
+        SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除
+        userRoleMapper.insert(userRoleDO01);
+        SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除
+        userRoleMapper.insert(userRoleDO02);
+        // mock 数据 RoleMenu
+        SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除
+        roleMenuMapper.insert(roleMenuDO01);
+        SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除
+        roleMenuMapper.insert(roleMenuDO02);
+
+        // 调用
+        permissionService.processRoleDeleted(roleId);
+        // 断言数据 RoleMenuDO
+        List<SysRoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
+        assertEquals(1, dbRoleMenus.size());
+        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
+        // 断言数据 UserRoleDO
+        List<SysUserRoleDO> dbUserRoles = userRoleMapper.selectList();
+        assertEquals(1, dbUserRoles.size());
+        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+        // 断言调用
+        verify(permissionProducer).sendRoleMenuRefreshMessage();
+    }
+
+    @Test
+    public void testProcessMenuDeleted() {
+        // 准备参数
+        Long menuId = randomLongId();
+        // mock 数据
+        SysRoleMenuDO roleMenuDO01 = randomPojo(SysRoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除
+        roleMenuMapper.insert(roleMenuDO01);
+        SysRoleMenuDO roleMenuDO02 = randomPojo(SysRoleMenuDO.class); // 不被删除
+        roleMenuMapper.insert(roleMenuDO02);
+
+        // 调用
+        permissionService.processMenuDeleted(menuId);
+        // 断言数据
+        List<SysRoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
+        assertEquals(1, dbRoleMenus.size());
+        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
+        // 断言调用
+        verify(permissionProducer).sendRoleMenuRefreshMessage();
+    }
+
+    @Test
+    public void testProcessUserDeleted() {
+        // 准备参数
+        Long userId = randomLongId();
+        // mock 数据
+        SysUserRoleDO userRoleDO01 = randomPojo(SysUserRoleDO.class, o -> o.setUserId(userId)); // 被删除
+        userRoleMapper.insert(userRoleDO01);
+        SysUserRoleDO userRoleDO02 = randomPojo(SysUserRoleDO.class); // 不被删除
+        userRoleMapper.insert(userRoleDO02);
+
+        // 调用
+        permissionService.processUserDeleted(userId);
+        // 断言数据
+        List<SysUserRoleDO> dbUserRoles = userRoleMapper.selectList();
+        assertEquals(1, dbUserRoles.size());
+        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+    }
+
+}

+ 1 - 0
src/test/resources/sql/clean.sql

@@ -8,6 +8,7 @@ DELETE FROM "sys_dict_data";
 DELETE FROM "sys_role";
 DELETE FROM "sys_role_menu";
 DELETE FROM "sys_menu";
+DELETE FROM "sys_user_role";
 DELETE FROM "sys_dict_type";
 DELETE FROM "sys_user_session";
 DELETE FROM "sys_post";

+ 13 - 1
src/test/resources/sql/create_tables.sql

@@ -113,6 +113,18 @@ CREATE TABLE IF NOT EXISTS "sys_menu" (
     PRIMARY KEY ("id")
 ) COMMENT '菜单权限表';
 
+CREATE TABLE IF NOT EXISTS "sys_user_role" (
+     "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+     "user_id" bigint NOT NULL,
+     "role_id" bigint NOT NULL,
+     "creator" varchar(64) DEFAULT '',
+     "create_time" timestamp DEFAULT NULL,
+     "updater" varchar(64) DEFAULT '',
+     "update_time" timestamp DEFAULT NULL,
+     "deleted" bit DEFAULT FALSE,
+     PRIMARY KEY ("id")
+) COMMENT '用户和角色关联表';
+
 CREATE TABLE IF NOT EXISTS "sys_dict_type" (
     "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
     "name" varchar(100) NOT NULL DEFAULT '',
@@ -297,4 +309,4 @@ create table "inf_api_error_log" (
  "update_time" timestamp not null default current_timestamp,
  "deleted" bit not null default false,
  primary key ("id")
-) comment '系统异常日志';
+) comment '系统异常日志';