diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java index 618deba5e..593e03c87 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/filter/ApiAccessLogFilter.java @@ -81,7 +81,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { Map 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) { diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java index aa064288e..75704145c 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/core/handler/GlobalExceptionHandler.java +++ b/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)); diff --git a/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java b/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java index 2cf6211ff..faacbdb99 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/web/core/util/WebFrameworkUtils.java +++ b/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 芋艿:等后续优化 } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java index b93bb5917..a28d546e4 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysRoleMenuMapper.java @@ -33,6 +33,14 @@ public interface SysRoleMenuMapper extends BaseMapperX { .in("menu_id", menuIds)); } + default void deleteListByMenuId(Long menuId) { + delete(new QueryWrapper().eq("menu_id", menuId)); + } + + default void deleteListByRoleId(Long roleId) { + delete(new QueryWrapper().eq("role_id", roleId)); + } + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { return selectOne(new QueryWrapper().select("id") .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java index ff1c3d4f3..f40db1432 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/permission/SysUserRoleMapper.java +++ b/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 { +public interface SysUserRoleMapper extends BaseMapperX { default List selectListByUserId(Long userId) { return selectList(new QueryWrapper().eq("user_id", userId)); @@ -32,4 +32,12 @@ public interface SysUserRoleMapper extends BaseMapper { .in("role_id", roleIds)); } + default void deleteListByUserId(Long userId) { + delete(new QueryWrapper().eq("user_id", userId)); + } + + default void deleteListByRoleId(Long roleId) { + delete(new QueryWrapper().eq("role_id", roleId)); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java index 65777ef06..96e3d1ad0 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/dept/impl/SysDeptServiceImpl.java +++ b/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(); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 27a9c7676..0e1b053da 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/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 diff --git a/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java b/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java index 43d28da9f..f1e2dddd4 100644 --- a/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java +++ b/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 配置类 diff --git a/src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java b/src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java index 821118279..19e930f1a 100644 --- a/src/test/java/cn/iocoder/dashboard/BaseDbUnitTest.java +++ b/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 配置类 diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionServiceTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionServiceTest.java new file mode 100644 index 000000000..a4b5fa71e --- /dev/null +++ b/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 dbRoleMenus = roleMenuMapper.selectList(); + assertEquals(1, dbRoleMenus.size()); + assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02); + // 断言数据 UserRoleDO + List 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 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 dbUserRoles = userRoleMapper.selectList(); + assertEquals(1, dbUserRoles.size()); + assertPojoEquals(dbUserRoles.get(0), userRoleDO02); + } + +} diff --git a/src/test/resources/sql/clean.sql b/src/test/resources/sql/clean.sql index 75372fd1a..bcd6aeec9 100644 --- a/src/test/resources/sql/clean.sql +++ b/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"; diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index 26c588717..b4161b515 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/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 '系统异常日志'; \ No newline at end of file +) comment '系统异常日志';