修改用户缓存结构.

This commit is contained in:
lijiahangmax
2023-11-21 00:39:15 +08:00
parent 6c056cecff
commit 8fe105fc8a
14 changed files with 108 additions and 72 deletions

View File

@@ -35,6 +35,6 @@ public class LoginUser {
private Long timestamp;
@Schema(description = "角色")
private List<String> roles;
private List<UserRole> roles;
}

View File

@@ -0,0 +1,28 @@
package com.orion.ops.framework.common.security;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* 用户角色
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/20 23:39
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Schema(name = "UserRole", description = "用户角色")
public class UserRole {
@EqualsAndHashCode.Include
@Schema(description = "id")
private Long id;
@Schema(description = "角色")
private String code;
}

View File

@@ -22,7 +22,7 @@ public interface PermissionService {
*
* @return cache
*/
Map<String, SystemRoleDO> getRoleCache();
Map<Long, SystemRoleDO> getRoleCache();
/**
* 获取 菜单缓存 以作角色权限直接引用
@@ -36,7 +36,7 @@ public interface PermissionService {
*
* @return cache
*/
Map<String, List<SystemMenuCacheDTO>> getRoleMenuCache();
Map<Long, List<SystemMenuCacheDTO>> getRoleMenuCache();
/**
* 初始化权限缓存

View File

@@ -40,9 +40,9 @@ public interface SystemUserRoleService {
/**
* 删除用户缓存中的角色
*
* @param roleCode roleCode
* @param roleId roleId
* @param userIdList userIdList
*/
void deleteUserCacheRoleAsync(String roleCode, List<Long> userIdList);
void deleteUserCacheRoleAsync(Long roleId, List<Long> userIdList);
}

View File

@@ -10,6 +10,7 @@ import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.common.utils.CryptoUtils;
import com.orion.ops.framework.common.utils.IpUtils;
import com.orion.ops.framework.common.utils.Valid;
@@ -20,7 +21,6 @@ import com.orion.ops.module.infra.convert.SystemUserConvert;
import com.orion.ops.module.infra.dao.SystemUserDAO;
import com.orion.ops.module.infra.dao.SystemUserRoleDAO;
import com.orion.ops.module.infra.define.cache.UserCacheKeyDefine;
import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import com.orion.ops.module.infra.entity.domain.SystemUserDO;
import com.orion.ops.module.infra.entity.dto.LoginTokenDTO;
import com.orion.ops.module.infra.entity.dto.LoginTokenIdentityDTO;
@@ -289,16 +289,16 @@ public class AuthenticationServiceImpl implements AuthenticationService {
Long id = user.getId();
// 查询用户角色
List<Long> roleIds = systemUserRoleDAO.selectRoleIdByUserId(id);
List<String> roleCodeList = permissionService.getRoleCache()
List<UserRole> roleList = permissionService.getRoleCache()
.values()
.stream()
.filter(s -> roleIds.contains(s.getId()))
.map(SystemRoleDO::getCode)
.map(r -> new UserRole(r.getId(), r.getCode()))
.collect(Collectors.toList());
// 设置用户缓存
String userInfoKey = UserCacheKeyDefine.USER_INFO.format(id);
LoginUser loginUser = SystemUserConvert.MAPPER.toLoginUser(user);
loginUser.setRoles(roleCodeList);
loginUser.setRoles(roleList);
RedisStrings.setJson(userInfoKey, UserCacheKeyDefine.USER_INFO, loginUser);
return loginUser;
}

View File

@@ -4,6 +4,7 @@ import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.module.infra.convert.SystemMenuConvert;
import com.orion.ops.module.infra.convert.SystemUserConvert;
@@ -51,13 +52,13 @@ import java.util.stream.Stream;
public class PermissionServiceImpl implements PermissionService {
@Getter
private final Map<String, SystemRoleDO> roleCache = new HashMap<>();
private final Map<Long, SystemRoleDO> roleCache = new HashMap<>();
@Getter
private final List<SystemMenuCacheDTO> menuCache = new ArrayList<>();
@Getter
private final Map<String, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
private final Map<Long, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
@Resource
private SystemRoleDAO systemRoleDAO;
@@ -87,10 +88,8 @@ public class PermissionServiceImpl implements PermissionService {
roleMenuCache.clear();
// 加载所有角色
List<SystemRoleDO> roles = systemRoleDAO.selectList(null);
Map<Long, SystemRoleDO> roleRel = roles.stream()
.collect(Collectors.toMap(SystemRoleDO::getId, Function.identity()));
for (SystemRoleDO role : roles) {
roleCache.put(role.getCode(), role);
roleCache.put(role.getId(), role);
}
// 加载所有菜单信息
List<SystemMenuDO> menuList = systemMenuDAO.selectList(null);
@@ -103,17 +102,14 @@ public class PermissionServiceImpl implements PermissionService {
.stream()
.collect(Collectors.groupingBy(SystemRoleMenuDO::getRoleId,
Collectors.mapping(SystemRoleMenuDO::getMenuId, Collectors.toList())))
.forEach((rid, mids) -> {
.forEach((roleId, menuIdList) -> {
// 获取菜单引用
List<SystemMenuCacheDTO> roleMenus = mids.stream()
List<SystemMenuCacheDTO> roleMenus = menuIdList.stream()
.map(menuMapping::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 获取角色引用
Optional.ofNullable(rid)
.map(roleRel::get)
.map(SystemRoleDO::getCode)
.ifPresent(code -> roleMenuCache.put(code, roleMenus));
roleMenuCache.put(roleId, roleMenus);
});
log.info("initPermissionCache-end used: {}ms", System.currentTimeMillis() - start);
}
@@ -121,7 +117,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override
public boolean hasRole(String role) {
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) {
return false;
}
@@ -132,7 +128,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override
public boolean hasPermission(String permission) {
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) {
return false;
}
@@ -150,7 +146,7 @@ public class PermissionServiceImpl implements PermissionService {
return true;
}
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) {
return false;
}
@@ -170,7 +166,7 @@ public class PermissionServiceImpl implements PermissionService {
@Override
public List<SystemMenuVO> getUserMenuList() {
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
List<String> roles = this.getUserEnabledRoleCode();
if (roles.isEmpty()) {
return Lists.empty();
}
@@ -206,7 +202,7 @@ public class PermissionServiceImpl implements PermissionService {
// 获取用户系统偏好
Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM);
// 获取用户角色
List<String> roles = this.getUserEnabledRoles();
List<String> roles = this.getUserEnabledRoleCode();
// 获取用户权限
List<String> permissions;
if (roles.isEmpty()) {
@@ -266,32 +262,27 @@ public class PermissionServiceImpl implements PermissionService {
*
* @return roles
*/
private List<String> getUserEnabledRoles() {
private List<String> getUserEnabledRoleCode() {
// 获取当前用户角色
List<String> roles = Optional.ofNullable(SecurityUtils.getLoginUser())
List<UserRole> userRoles = Optional.ofNullable(SecurityUtils.getLoginUser())
.map(LoginUser::getRoles)
.orElse(Lists.empty());
if (Lists.isEmpty(roles)) {
.orElse(null);
if (Lists.isEmpty(userRoles)) {
return Lists.empty();
}
// 过滤未启用的角色
return roles.stream()
.filter(this::checkRoleEnabled)
// 获取角色编码
List<String> roleCodes = userRoles.stream()
.map(UserRole::getId)
.map(roleCache::get)
.filter(Objects::nonNull)
// 过滤未启用的角色
.filter(r -> RoleStatusEnum.ENABLED.getStatus().equals(r.getStatus()))
.map(SystemRoleDO::getCode)
.collect(Collectors.toList());
}
/**
* 检查角色是否启用
*
* @param role role
* @return 是否启用
*/
private boolean checkRoleEnabled(String role) {
SystemRoleDO systemRole = roleCache.get(role);
if (systemRole == null) {
return false;
if (Lists.isEmpty(roleCodes)) {
return Lists.empty();
}
return RoleStatusEnum.ENABLED.getStatus().equals(systemRole.getStatus());
return roleCodes;
}
}

View File

@@ -104,12 +104,8 @@ public class SystemRoleMenuServiceImpl implements SystemRoleMenuService {
effect += insertMenuIdList.size();
}
// 更新缓存
Map<String, List<SystemMenuCacheDTO>> cache = permissionService.getRoleMenuCache();
List<SystemMenuCacheDTO> roleCache = cache.get(role.getCode());
if (Lists.isEmpty(roleCache)) {
roleCache = new ArrayList<>();
cache.put(role.getCode(), roleCache);
}
Map<Long, List<SystemMenuCacheDTO>> cache = permissionService.getRoleMenuCache();
List<SystemMenuCacheDTO> roleCache = cache.computeIfAbsent(roleId, s -> new ArrayList<>());
roleCache.clear();
roleCache.addAll(SystemMenuConvert.MAPPER.toCache(menuList));
return effect;

View File

@@ -67,7 +67,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.insert(record);
log.info("SystemRoleService-createSystemRole effect: {}, domain: {}", effect, JSON.toJSONString(record));
// 设置到缓存
permissionService.getRoleCache().put(record.getCode(), record);
permissionService.getRoleCache().put(record.getId(), record);
return record.getId();
}
@@ -87,7 +87,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.updateById(updateRecord);
log.info("SystemRoleService-updateSystemRoleById effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
// 设置到缓存
SystemRoleDO roleCache = permissionService.getRoleCache().get(record.getCode());
SystemRoleDO roleCache = permissionService.getRoleCache().get(id);
roleCache.setName(updateRecord.getName());
return effect;
}
@@ -112,7 +112,7 @@ public class SystemRoleServiceImpl implements SystemRoleService {
int effect = systemRoleDAO.updateById(updateRecord);
log.info("SystemRoleService-updateRoleStatus effect: {}, updateRecord: {}", effect, JSON.toJSONString(updateRecord));
// 修改缓存状态
SystemRoleDO roleCache = permissionService.getRoleCache().get(record.getCode());
SystemRoleDO roleCache = permissionService.getRoleCache().get(id);
roleCache.setStatus(status);
return effect;
}
@@ -173,11 +173,11 @@ public class SystemRoleServiceImpl implements SystemRoleService {
// 删除角色菜单关联
effect += systemRoleMenuDAO.deleteByRoleId(id);
// 删除角色缓存
permissionService.getRoleCache().remove(code);
permissionService.getRoleCache().remove(id);
// 删除菜单缓存
permissionService.getRoleMenuCache().remove(code);
permissionService.getRoleMenuCache().remove(id);
// 删除用户缓存中的角色
systemUserRoleService.deleteUserCacheRoleAsync(code, userIdList);
systemUserRoleService.deleteUserCacheRoleAsync(id, userIdList);
return effect;
}

View File

@@ -4,6 +4,7 @@ import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.biz.operator.log.core.uitls.OperatorLogs;
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.security.LoginUser;
import com.orion.ops.framework.common.security.UserRole;
import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.module.infra.dao.SystemRoleDAO;
@@ -101,25 +102,25 @@ public class SystemUserRoleServiceImpl implements SystemUserRoleService {
effect += addUserRoles.size();
// 更新缓存中的角色
RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> {
List<String> roleCodeList = userRoles.stream()
.map(SystemRoleDO::getCode)
List<UserRole> roles = userRoles.stream()
.map(role -> new UserRole(role.getId(), role.getCode()))
.collect(Collectors.toList());
s.setRoles(roleCodeList);
s.setRoles(roles);
}, userId);
return effect;
}
@Override
@Async("asyncExecutor")
public void deleteUserCacheRoleAsync(String roleCode, List<Long> userIdList) {
public void deleteUserCacheRoleAsync(Long roleId, List<Long> userIdList) {
for (Long userId : userIdList) {
RedisStrings.<LoginUser>processSetJson(UserCacheKeyDefine.USER_INFO, s -> {
List<String> roles = s.getRoles();
List<UserRole> roles = s.getRoles();
if (Lists.isEmpty(roles)) {
return;
}
// 移除角色
roles.remove(roleCode);
roles.removeIf(role -> roleId.equals(role.getId()));
}, userId);
}
}

View File

@@ -1,3 +1,4 @@
import type { MenuQueryResponse } from '@/api/system/menu';
import axios from 'axios';
/**
@@ -15,6 +16,22 @@ export interface LoginResponse {
token: string;
}
/**
* 用户权限响应
*/
export interface UserPermissionResponse {
user: {
id: number;
username: string;
nickname: string;
avatar: string;
systemPreference: Record<string, any>;
tippedKeys: Array<string>;
};
roles: Array<string>;
permissions: Array<string>;
}
/**
* 登录
*/
@@ -33,12 +50,12 @@ export function logout() {
* 获取用户信息
*/
export function getUserPermission() {
return axios.get('/infra/permission/user');
return axios.get<UserPermissionResponse>('/infra/permission/user');
}
/**
* 获取菜单列表
*/
export function getMenuList() {
return axios.get('/infra/permission/menu');
return axios.get<Array<MenuQueryResponse>>('/infra/permission/menu');
}

View File

@@ -58,7 +58,7 @@ export default function usePermission() {
* 是否有角色
*/
hasAnyRole(role: string[]) {
return userStore.roles?.includes('*') ||
return userStore.roles?.includes('admin') ||
role.map(s => userStore.roles?.includes(s))
.filter(Boolean).length > 0;
}

View File

@@ -28,8 +28,8 @@
<!-- 传输框 -->
<a-transfer v-model="value"
:data="data"
:source-input-search-props="{ placeholder:'请输入主机名称/编码/IP' }"
:target-input-search-props="{ placeholder:'请输入主机名称/编码/IP' }"
:source-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
:target-input-search-props="{ placeholder: '请输入主机名称/编码/IP' }"
:disabled="!group.key"
show-search
one-way>

View File

@@ -80,7 +80,7 @@
type="warning"
@ok="toggleRoleStatus(record)">
<a-button v-permission="['infra:system-role:delete']"
:disabled="record.code === 'admin'"
:disabled="record.code === AdminCode"
:status="toggleDictValue(roleStatusKey, record.status, 'status')"
type="text"
size="mini">
@@ -89,7 +89,7 @@
</a-popconfirm>
<!-- 分配菜单 -->
<a-button v-permission="['infra:system-role:grant-menu']"
:disabled="record.code === 'admin'"
:disabled="record.code === AdminCode"
type="text"
size="mini"
@click="emits('openGrant', record)">
@@ -108,7 +108,7 @@
type="warning"
@ok="deleteRow(record)">
<a-button v-permission="['infra:system-role:delete']"
:disabled="record.code === 'admin'"
:disabled="record.code === AdminCode"
type="text"
size="mini"
status="danger">
@@ -134,7 +134,7 @@
import { Message } from '@arco-design/web-vue';
import useLoading from '@/hooks/loading';
import columns from '../types/table.columns';
import { roleStatusKey } from '../types/const';
import { roleStatusKey, AdminCode } from '../types/const';
import { usePagination } from '@/types/table';
import { useDictStore } from '@/store';

View File

@@ -1,3 +1,6 @@
// 管理员角色编码
export const AdminCode = 'admin';
// 角色状态
export const RoleStatus = {
// 停用