mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-11 06:57:12 +08:00
fix(system/role): 修复角色菜单权限缓存未清理错误,优化角色菜单缓存逻辑
Closes #IBNENK
This commit is contained in:
@@ -42,9 +42,9 @@ public class CacheConstants {
|
|||||||
public static final String USER_KEY_PREFIX = "USER" + DELIMITER;
|
public static final String USER_KEY_PREFIX = "USER" + DELIMITER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单缓存键前缀
|
* 角色菜单缓存键前缀
|
||||||
*/
|
*/
|
||||||
public static final String MENU_KEY_PREFIX = "MENU" + DELIMITER;
|
public static final String ROLE_MENU_KEY_PREFIX = "ROLE_MENU" + DELIMITER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字典缓存键前缀
|
* 字典缓存键前缀
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package top.continew.admin.common.context;
|
package top.continew.admin.common.context;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import top.continew.admin.common.enums.DataScopeEnum;
|
import top.continew.admin.common.enums.DataScopeEnum;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
@@ -29,6 +30,7 @@ import java.io.Serializable;
|
|||||||
* @since 2023/3/7 22:08
|
* @since 2023/3/7 22:08
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
public class RoleContext implements Serializable {
|
public class RoleContext implements Serializable {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
@@ -48,4 +50,10 @@ public class RoleContext implements Serializable {
|
|||||||
* 数据权限
|
* 数据权限
|
||||||
*/
|
*/
|
||||||
private DataScopeEnum dataScope;
|
private DataScopeEnum dataScope;
|
||||||
|
|
||||||
|
public RoleContext(Long id, String code, DataScopeEnum dataScope) {
|
||||||
|
this.id = id;
|
||||||
|
this.code = code;
|
||||||
|
this.dataScope = dataScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@ import top.continew.admin.auth.model.resp.LoginResp;
|
|||||||
import top.continew.admin.auth.model.resp.RouteResp;
|
import top.continew.admin.auth.model.resp.RouteResp;
|
||||||
import top.continew.admin.auth.service.AuthService;
|
import top.continew.admin.auth.service.AuthService;
|
||||||
import top.continew.admin.common.constant.SysConstants;
|
import top.continew.admin.common.constant.SysConstants;
|
||||||
|
import top.continew.admin.common.context.RoleContext;
|
||||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||||
import top.continew.admin.system.enums.MenuTypeEnum;
|
import top.continew.admin.system.enums.MenuTypeEnum;
|
||||||
import top.continew.admin.system.model.resp.ClientResp;
|
import top.continew.admin.system.model.resp.ClientResp;
|
||||||
@@ -86,16 +87,16 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RouteResp> buildRouteTree(Long userId) {
|
public List<RouteResp> buildRouteTree(Long userId) {
|
||||||
Set<String> roleCodeSet = roleService.listCodeByUserId(userId);
|
Set<RoleContext> roleSet = roleService.listByUserId(userId);
|
||||||
if (CollUtil.isEmpty(roleCodeSet)) {
|
if (CollUtil.isEmpty(roleSet)) {
|
||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
// 查询菜单列表
|
// 查询菜单列表
|
||||||
Set<MenuResp> menuSet = new LinkedHashSet<>();
|
Set<MenuResp> menuSet = new LinkedHashSet<>();
|
||||||
if (roleCodeSet.contains(SysConstants.SUPER_ROLE_CODE)) {
|
if (roleSet.stream().anyMatch(r -> SysConstants.SUPER_ROLE_ID.equals(r.getId()))) {
|
||||||
menuSet.addAll(menuService.listAll());
|
menuSet.addAll(menuService.listByRoleId(SysConstants.SUPER_ROLE_ID));
|
||||||
} else {
|
} else {
|
||||||
roleCodeSet.forEach(roleCode -> menuSet.addAll(menuService.listByRoleCode(roleCode)));
|
roleSet.forEach(r -> menuSet.addAll(menuService.listByRoleId(r.getId())));
|
||||||
}
|
}
|
||||||
List<MenuResp> menuList = menuSet.stream().filter(m -> !MenuTypeEnum.BUTTON.equals(m.getType())).toList();
|
List<MenuResp> menuList = menuSet.stream().filter(m -> !MenuTypeEnum.BUTTON.equals(m.getType())).toList();
|
||||||
if (CollUtil.isEmpty(menuList)) {
|
if (CollUtil.isEmpty(menuList)) {
|
||||||
|
@@ -40,10 +40,10 @@ public interface MenuMapper extends BaseMapper<MenuDO> {
|
|||||||
Set<String> selectPermissionByUserId(@Param("userId") Long userId);
|
Set<String> selectPermissionByUserId(@Param("userId") Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色编码查询
|
* 根据角色 ID 查询
|
||||||
*
|
*
|
||||||
* @param roleCode 角色编码
|
* @param roleId 角色 ID
|
||||||
* @return 菜单列表
|
* @return 菜单列表
|
||||||
*/
|
*/
|
||||||
List<MenuDO> selectListByRoleCode(@Param("roleCode") String roleCode);
|
List<MenuDO> selectListByRoleId(@Param("roleId") Long roleId);
|
||||||
}
|
}
|
||||||
|
@@ -34,13 +34,6 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public interface MenuService extends BaseService<MenuResp, MenuResp, MenuQuery, MenuReq>, IService<MenuDO> {
|
public interface MenuService extends BaseService<MenuResp, MenuResp, MenuQuery, MenuReq>, IService<MenuDO> {
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询全部菜单
|
|
||||||
*
|
|
||||||
* @return 菜单列表
|
|
||||||
*/
|
|
||||||
List<MenuResp> listAll();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户 ID 查询
|
* 根据用户 ID 查询
|
||||||
*
|
*
|
||||||
@@ -50,10 +43,10 @@ public interface MenuService extends BaseService<MenuResp, MenuResp, MenuQuery,
|
|||||||
Set<String> listPermissionByUserId(Long userId);
|
Set<String> listPermissionByUserId(Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色编码查询
|
* 根据角色 ID 查询
|
||||||
*
|
*
|
||||||
* @param roleCode 角色编码
|
* @param roleId 角色 ID
|
||||||
* @return 菜单列表
|
* @return 菜单列表
|
||||||
*/
|
*/
|
||||||
List<MenuResp> listByRoleCode(String roleCode);
|
List<MenuResp> listByRoleId(Long roleId);
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import top.continew.admin.common.constant.CacheConstants;
|
import top.continew.admin.common.constant.CacheConstants;
|
||||||
|
import top.continew.admin.common.constant.SysConstants;
|
||||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||||
import top.continew.admin.system.enums.MenuTypeEnum;
|
import top.continew.admin.system.enums.MenuTypeEnum;
|
||||||
import top.continew.admin.system.mapper.MenuMapper;
|
import top.continew.admin.system.mapper.MenuMapper;
|
||||||
@@ -62,7 +63,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
|
|||||||
if (MenuTypeEnum.DIR.equals(req.getType())) {
|
if (MenuTypeEnum.DIR.equals(req.getType())) {
|
||||||
req.setComponent(StrUtil.blankToDefault(req.getComponent(), "Layout"));
|
req.setComponent(StrUtil.blankToDefault(req.getComponent(), "Layout"));
|
||||||
}
|
}
|
||||||
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
||||||
return super.add(req);
|
return super.add(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
|
|||||||
MenuDO oldMenu = super.getById(id);
|
MenuDO oldMenu = super.getById(id);
|
||||||
CheckUtils.throwIfNotEqual(req.getType(), oldMenu.getType(), "不允许修改菜单类型");
|
CheckUtils.throwIfNotEqual(req.getType(), oldMenu.getType(), "不允许修改菜单类型");
|
||||||
super.update(req, id);
|
super.update(req, id);
|
||||||
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,13 +87,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
|
|||||||
public void delete(List<Long> ids) {
|
public void delete(List<Long> ids) {
|
||||||
baseMapper.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
|
baseMapper.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
|
||||||
super.delete(ids);
|
super.delete(ids);
|
||||||
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Cached(key = "'ALL'", name = CacheConstants.MENU_KEY_PREFIX)
|
|
||||||
public List<MenuResp> listAll() {
|
|
||||||
return super.list(new MenuQuery(DisEnableStatusEnum.ENABLE), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,9 +96,12 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Cached(key = "#roleCode", name = CacheConstants.MENU_KEY_PREFIX)
|
@Cached(key = "#roleId", name = CacheConstants.ROLE_MENU_KEY_PREFIX)
|
||||||
public List<MenuResp> listByRoleCode(String roleCode) {
|
public List<MenuResp> listByRoleId(Long roleId) {
|
||||||
List<MenuDO> menuList = baseMapper.selectListByRoleCode(roleCode);
|
if (SysConstants.SUPER_ROLE_ID.equals(roleId)) {
|
||||||
|
return super.list(new MenuQuery(DisEnableStatusEnum.ENABLE), null);
|
||||||
|
}
|
||||||
|
List<MenuDO> menuList = baseMapper.selectListByRoleId(roleId);
|
||||||
List<MenuResp> list = BeanUtil.copyToList(menuList, MenuResp.class);
|
List<MenuResp> list = BeanUtil.copyToList(menuList, MenuResp.class);
|
||||||
list.forEach(super::fill);
|
list.forEach(super::fill);
|
||||||
return list;
|
return list;
|
||||||
|
@@ -18,7 +18,6 @@ package top.continew.admin.system.service.impl;
|
|||||||
|
|
||||||
import cn.crane4j.annotation.ContainerMethod;
|
import cn.crane4j.annotation.ContainerMethod;
|
||||||
import cn.crane4j.annotation.MappingType;
|
import cn.crane4j.annotation.MappingType;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.alicp.jetcache.anno.CacheInvalidate;
|
import com.alicp.jetcache.anno.CacheInvalidate;
|
||||||
@@ -45,7 +44,10 @@ import top.continew.admin.system.service.*;
|
|||||||
import top.continew.starter.core.validation.CheckUtils;
|
import top.continew.starter.core.validation.CheckUtils;
|
||||||
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
import top.continew.starter.extension.crud.service.BaseServiceImpl;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +81,6 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@CacheInvalidate(key = "#req.code == 'admin' ? 'ALL' : #req.code", name = CacheConstants.MENU_KEY_PREFIX)
|
|
||||||
public void update(RoleReq req, Long id) {
|
public void update(RoleReq req, Long id) {
|
||||||
String name = req.getName();
|
String name = req.getName();
|
||||||
CheckUtils.throwIf(this.isNameExists(name, id), "修改失败,[{}] 已存在", name);
|
CheckUtils.throwIf(this.isNameExists(name, id), "修改失败,[{}] 已存在", name);
|
||||||
@@ -120,6 +121,7 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@CacheInvalidate(key = "#id", name = CacheConstants.ROLE_MENU_KEY_PREFIX)
|
||||||
public void updatePermission(Long id, RoleUpdatePermissionReq req) {
|
public void updatePermission(Long id, RoleUpdatePermissionReq req) {
|
||||||
super.getById(id);
|
super.getById(id);
|
||||||
// 保存角色和菜单关联
|
// 保存角色和菜单关联
|
||||||
@@ -148,13 +150,9 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
|||||||
super.fill(obj);
|
super.fill(obj);
|
||||||
if (obj instanceof RoleDetailResp detail) {
|
if (obj instanceof RoleDetailResp detail) {
|
||||||
Long roleId = detail.getId();
|
Long roleId = detail.getId();
|
||||||
if (SysConstants.SUPER_ROLE_CODE.equals(detail.getCode())) {
|
List<MenuResp> list = menuService.listByRoleId(roleId);
|
||||||
List<MenuResp> list = menuService.listAll();
|
List<Long> menuIds = list.stream().map(MenuResp::getId).toList();
|
||||||
List<Long> menuIds = list.stream().map(MenuResp::getId).toList();
|
detail.setMenuIds(menuIds);
|
||||||
detail.setMenuIds(menuIds);
|
|
||||||
} else {
|
|
||||||
detail.setMenuIds(roleMenuService.listMenuIdByRoleIds(CollUtil.newArrayList(roleId)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,8 +192,13 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
|
|||||||
if (CollUtil.isEmpty(roleIdList)) {
|
if (CollUtil.isEmpty(roleIdList)) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
List<RoleDO> roleList = baseMapper.lambdaQuery().in(RoleDO::getId, roleIdList).list();
|
List<RoleDO> roleList = baseMapper.lambdaQuery()
|
||||||
return new HashSet<>(BeanUtil.copyToList(roleList, RoleContext.class));
|
.select(RoleDO::getId, RoleDO::getCode, RoleDO::getDataScope)
|
||||||
|
.in(RoleDO::getId, roleIdList)
|
||||||
|
.list();
|
||||||
|
return roleList.stream()
|
||||||
|
.map(r -> new RoleContext(r.getId(), r.getCode(), r.getDataScope()))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -13,12 +13,12 @@
|
|||||||
AND t1.permission IS NOT NULL
|
AND t1.permission IS NOT NULL
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectListByRoleCode" resultType="top.continew.admin.system.model.entity.MenuDO">
|
<select id="selectListByRoleId" resultType="top.continew.admin.system.model.entity.MenuDO">
|
||||||
SELECT t1.*
|
SELECT t1.*
|
||||||
FROM sys_menu AS t1
|
FROM sys_menu AS t1
|
||||||
LEFT JOIN sys_role_menu AS t2 ON t2.menu_id = t1.id
|
LEFT JOIN sys_role_menu AS t2 ON t2.menu_id = t1.id
|
||||||
LEFT JOIN sys_role AS t3 ON t3.id = t2.role_id
|
LEFT JOIN sys_role AS t3 ON t3.id = t2.role_id
|
||||||
WHERE t3.code = #{roleCode}
|
WHERE t3.id = #{roleId}
|
||||||
AND t1.status = 1
|
AND t1.status = 1
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
@@ -131,7 +131,7 @@ public class DemoEnvironmentJob {
|
|||||||
roleMenuMapper.lambdaUpdate().notIn(RoleMenuDO::getRoleId, ROLE_FLAG).remove();
|
roleMenuMapper.lambdaUpdate().notIn(RoleMenuDO::getRoleId, ROLE_FLAG).remove();
|
||||||
return roleMapper.lambdaUpdate().notIn(RoleDO::getId, ROLE_FLAG).remove();
|
return roleMapper.lambdaUpdate().notIn(RoleDO::getId, ROLE_FLAG).remove();
|
||||||
});
|
});
|
||||||
this.clean(menuCount, "菜单", CacheConstants.MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()
|
this.clean(menuCount, "菜单", CacheConstants.ROLE_MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()
|
||||||
.gt(MenuDO::getId, DELETE_FLAG)
|
.gt(MenuDO::getId, DELETE_FLAG)
|
||||||
.remove());
|
.remove());
|
||||||
this.clean(deptCount, "部门", null, () -> deptMapper.lambdaUpdate().gt(DeptDO::getId, DEPT_FLAG).remove());
|
this.clean(deptCount, "部门", null, () -> deptMapper.lambdaUpdate().gt(DeptDO::getId, DEPT_FLAG).remove());
|
||||||
|
Reference in New Issue
Block a user