修改用户缓存结构.
This commit is contained in:
@@ -35,6 +35,6 @@ public class LoginUser {
|
||||
private Long timestamp;
|
||||
|
||||
@Schema(description = "角色")
|
||||
private List<String> roles;
|
||||
private List<UserRole> roles;
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
* 初始化权限缓存
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// 管理员角色编码
|
||||
export const AdminCode = 'admin';
|
||||
|
||||
// 角色状态
|
||||
export const RoleStatus = {
|
||||
// 停用
|
||||
|
||||
Reference in New Issue
Block a user