Commit 97e842a59f0d7832af3a7e416d465c0c1af63433
1 parent
f4818d26
完善 role、user、menu 删除时,对权限的影响
Showing
12 changed files
with
174 additions
and
14 deletions
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<SysRoleMenuDO> { |
| 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<SysUserRoleDO> { |
| 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
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
src/test/resources/sql/create_tables.sql
| ... | ... | @@ -113,6 +113,18 @@ CREATE TABLE IF NOT EXISTS "sys_menu" ( |
| 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 "inf_api_error_log" ( |
| 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 '系统异常日志'; | ... | ... |