修改授权逻辑.

This commit is contained in:
lijiahang
2024-04-18 09:59:10 +08:00
parent 256e54ffd8
commit 1034ba4896
16 changed files with 184 additions and 260 deletions

View File

@@ -18,7 +18,7 @@ import lombok.NoArgsConstructor;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "HostExtraSshModel", description = "主机拓展信息 - color 模型")
@Schema(name = "HostColorExtraModel", description = "主机拓展信息 - color 模型")
public class HostColorExtraModel implements GenericsDataModel {
@Schema(description = "标签 tab 颜色")

View File

@@ -9,7 +9,6 @@ import com.orion.ops.module.asset.dao.HostKeyDAO;
import com.orion.ops.module.asset.enums.HostExtraSshAuthTypeEnum;
import com.orion.ops.module.asset.handler.host.extra.model.HostSshExtraModel;
import com.orion.ops.module.infra.api.DataPermissionApi;
import com.orion.ops.module.infra.api.SystemUserApi;
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
import org.springframework.stereotype.Component;
@@ -31,9 +30,6 @@ public class HostSshExtraStrategy implements MapDataStrategy<HostSshExtraModel>
@Resource
private HostIdentityDAO hostIdentityDAO;
@Resource
private SystemUserApi systemUserApi;
@Resource
private DataPermissionApi dataPermissionApi;
@@ -68,21 +64,18 @@ public class HostSshExtraStrategy implements MapDataStrategy<HostSshExtraModel>
if (identityId != null) {
Valid.notNull(hostIdentityDAO.selectById(identityId), ErrorMessage.IDENTITY_ABSENT);
}
// 非管理员验证权限
Long userId = SecurityUtils.getLoginUserId();
if (!systemUserApi.isAdminUser(userId)) {
// 验证主机秘钥是否有权限
if (keyId != null) {
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_KEY, userId, keyId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_KEY.getPermissionName());
}
// 验证主机身份是否有权限
if (identityId != null) {
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_IDENTITY, userId, identityId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_IDENTITY.getPermissionName());
}
// 验证主机秘钥是否有权限
if (keyId != null) {
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_KEY, userId, keyId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_KEY.getPermissionName());
}
// 验证主机身份是否有权限
if (identityId != null) {
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_IDENTITY, userId, identityId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_IDENTITY.getPermissionName());
}
}

View File

@@ -28,13 +28,21 @@ public interface AssetAuthorizedDataService {
List<Long> getAuthorizedDataRelId(DataPermissionTypeEnum type, AssetAuthorizedDataQueryRequest request);
/**
* 查询用户已授权的主机
* 获取用户已授权的主机id 查询角色
*
* @param userId userId
* @return hostId
*/
List<Long> getUserAuthorizedHostId(Long userId);
/**
* 获取用户已授权&配置已启用的主机id 查询角色
*
* @param userId userId
* @param type type
* @return hostId
*/
List<Long> getUserAuthorizedHostId(Long userId, HostConfigTypeEnum type);
List<Long> getUserAuthorizedHostIdWithEnabledConfig(Long userId, HostConfigTypeEnum type);
/**
* 查询用户已授权的主机
@@ -45,14 +53,6 @@ public interface AssetAuthorizedDataService {
*/
AuthorizedHostWrapperVO getUserAuthorizedHost(Long userId, String type);
/**
* 获取用户已授权的主机id 不查询角色
*
* @param userId userId
* @return hostId
*/
List<Long> getUserAuthorizedHostId(Long userId);
/**
* 查询用户已授权的主机秘钥
*

View File

@@ -28,7 +28,7 @@ public interface HostConfigService {
HostConfigVO getHostConfig(Long hostId, String type);
/**
* 获取配置
* 获取配置 配置未启用会报错
*
* @param hostId hostId
* @param type type

View File

@@ -5,6 +5,7 @@ import com.orion.lang.function.Functions;
import com.orion.lang.utils.Refs;
import com.orion.lang.utils.collect.Lists;
import com.orion.lang.utils.collect.Maps;
import com.orion.lang.utils.collect.Sets;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.utils.TreeUtils;
import com.orion.ops.framework.common.utils.Valid;
@@ -50,9 +51,6 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
@Resource
private DataPermissionApi dataPermissionApi;
@Resource
private SystemUserApi systemUserApi;
@Resource
private HostService hostService;
@@ -91,39 +89,6 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
}
}
@Override
public List<Long> getUserAuthorizedHostId(Long userId, HostConfigTypeEnum type) {
final boolean allData = systemUserApi.isAdminUser(userId);
if (allData) {
// 管理员查询所有
return this.getEnabledConfigHostId(true, Maps.empty(), type.name());
} else {
// 其他用户 查询授权的数据
Map<Long, Set<Long>> dataGroupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST);
// 查询配置启用的主机
return this.getEnabledConfigHostId(false, dataGroupRel, type.name());
}
}
@Override
public AuthorizedHostWrapperVO getUserAuthorizedHost(Long userId, String type) {
if (systemUserApi.isAdminUser(userId)) {
// 管理员查询所有
return this.buildUserAuthorizedHost(userId, null, type);
} else {
// 其他用户 查询授权的数据
List<Long> authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_GROUP, userId);
if (authorizedIdList.isEmpty()) {
// 无数据
return AuthorizedHostWrapperVO.builder()
.groupTree(Lists.empty())
.hostList(Lists.empty())
.build();
}
return this.buildUserAuthorizedHost(userId, authorizedIdList, type);
}
}
@Override
public List<Long> getUserAuthorizedHostId(Long userId) {
// 查询授权的分组
@@ -143,60 +108,30 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
}
@Override
public List<HostKeyVO> getUserAuthorizedHostKey(Long userId) {
if (systemUserApi.isAdminUser(userId)) {
// 管理员查询所有
return hostKeyService.getHostKeyList();
} else {
// 其他用户 查询授权的数据
List<Long> authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_KEY, userId);
if (authorizedIdList.isEmpty()) {
return Lists.empty();
}
// 映射数据
Map<Long, HostKeyVO> keys = hostKeyService.getHostKeyList()
.stream()
.collect(Collectors.toMap(HostKeyVO::getId, Function.identity(), Functions.right()));
return authorizedIdList.stream()
.map(keys::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
public List<Long> getUserAuthorizedHostIdWithEnabledConfig(Long userId, HostConfigTypeEnum type) {
// 获取启用的主机
List<Long> hostIdList = this.getUserAuthorizedHostId(userId);
if (hostIdList.isEmpty()) {
return hostIdList;
}
// 获取启用配置的主机
return hostConfigService.getEnabledConfigHostId(type.name(), hostIdList);
}
@Override
public List<HostIdentityVO> getUserAuthorizedHostIdentity(Long userId) {
if (systemUserApi.isAdminUser(userId)) {
// 管理员查询所有
return hostIdentityService.getHostIdentityList();
} else {
// 其他用户 查询授权的数据
List<Long> authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_IDENTITY, userId);
if (authorizedIdList.isEmpty()) {
return Lists.empty();
}
// 映射数据
Map<Long, HostIdentityVO> identities = hostIdentityService.getHostIdentityList()
.stream()
.collect(Collectors.toMap(HostIdentityVO::getId, Function.identity(), Functions.right()));
return authorizedIdList.stream()
.map(identities::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
}
/**
* 构建授权的主机分组树
*
* @param userId userId
* @param authorizedGroupIdList authorizedGroupIdList
* @param type type
* @return tree
*/
@SneakyThrows
private AuthorizedHostWrapperVO buildUserAuthorizedHost(Long userId, List<Long> authorizedGroupIdList, String type) {
final boolean allData = Lists.isEmpty(authorizedGroupIdList);
@Override
public AuthorizedHostWrapperVO getUserAuthorizedHost(Long userId, String type) {
// 查询授权的数据
List<Long> authorizedGroupIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_GROUP, userId);
if (Lists.isEmpty(authorizedGroupIdList)) {
// 无数据
return AuthorizedHostWrapperVO.builder()
.groupTree(Lists.empty())
.treeNodes(Maps.empty())
.hostList(Lists.empty())
.latestHosts(Sets.empty())
.build();
}
AuthorizedHostWrapperVO wrapper = new AuthorizedHostWrapperVO();
// 查询我的收藏
Future<List<Long>> favoriteResult = favoriteApi.getFavoriteRelIdListAsync(FavoriteTypeEnum.HOST, userId);
@@ -210,28 +145,14 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
List<DataGroupDTO> dataGroup = dataGroupApi.getDataGroupList(DataGroupTypeEnum.HOST);
// 查询分组引用
Map<Long, Set<Long>> dataGroupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST);
// 查询配置启用的主机
List<Long> enabledConfigHostId = this.getEnabledConfigHostId(allData, dataGroupRel, type);
// 过滤已经授权的分组
if (!allData) {
// 构建已授权的分组
List<DataGroupDTO> relNodes = new ArrayList<>();
TreeUtils.getAllNodes(dataGroup, authorizedGroupIdList, relNodes);
dataGroup = new ArrayList<>(new HashSet<>(relNodes));
}
// 过滤掉无分组权限以及未启用配置的主机
this.filterEnabledAuthorizedHost(dataGroup, dataGroupRel, authorizedGroupIdList, type);
// 设置主机分组树
wrapper.setGroupTree(this.getAuthorizedHostGroupTree(dataGroup));
// 设置主机分组下的主机
wrapper.setTreeNodes(this.getAuthorizedHostGroupNodes(allData,
dataGroup,
dataGroupRel,
authorizedGroupIdList));
// 设置已授权的所有主机
wrapper.setHostList(this.getAuthorizedHostList(allData,
dataGroup,
dataGroupRel,
authorizedGroupIdList,
enabledConfigHostId));
// 设置主机列表
wrapper.setHostList(this.getAuthorizedHostList(dataGroupRel));
// 设置主机分组节点映射
wrapper.setTreeNodes(Maps.map(dataGroupRel, String::valueOf, Function.identity()));
// 设置主机拓展信息
this.getAuthorizedHostExtra(wrapper.getHostList(),
favoriteResult.get(),
@@ -241,34 +162,63 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
return wrapper;
}
/**
* 获取已启用配置的 hostId
*
* @param allData allData
* @param dataGroupRel dataGroupRel
* @param type type
* @return enabledHostIdList
*/
private List<Long> getEnabledConfigHostId(boolean allData,
Map<Long, Set<Long>> dataGroupRel,
String type) {
List<Long> hostIdList = null;
if (!allData) {
// 非全部数据从分组映射中获取
hostIdList = dataGroupRel.values()
.stream()
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
if (hostIdList.isEmpty()) {
return Lists.empty();
}
@Override
public List<HostKeyVO> getUserAuthorizedHostKey(Long userId) {
// 查询授权的数据
List<Long> authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_KEY, userId);
if (authorizedIdList.isEmpty()) {
return Lists.empty();
}
// 查询启用配置的主机
// 查询数据
return hostKeyService.getHostKeyList()
.stream()
.filter(s -> authorizedIdList.contains(s.getId()))
.collect(Collectors.toList());
}
@Override
public List<HostIdentityVO> getUserAuthorizedHostIdentity(Long userId) {
// 查询授权的数据
List<Long> authorizedIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_IDENTITY, userId);
if (authorizedIdList.isEmpty()) {
return Lists.empty();
}
// 查询数据
return hostIdentityService.getHostIdentityList()
.stream()
.filter(s -> authorizedIdList.contains(s.getId()))
.collect(Collectors.toList());
}
/**
* 过滤掉未授权的 dataGroupRel 和 dataGroupRel
* 过滤掉未启用配置的 dataGroupRel
*
* @param dataGroup dataGroup
* @param dataGroupRel dataGroupRel
* @param authorizedGroupIdList authorizedGroupIdList
* @param type type
*/
private void filterEnabledAuthorizedHost(List<DataGroupDTO> dataGroup,
Map<Long, Set<Long>> dataGroupRel,
List<Long> authorizedGroupIdList,
String type) {
// 过滤未授权的分组
List<DataGroupDTO> authorizedDataGroup = new ArrayList<>();
TreeUtils.getAllNodes(dataGroup, authorizedGroupIdList, authorizedDataGroup);
dataGroup.clear();
dataGroup.addAll(new HashSet<>(authorizedDataGroup));
// 移除未授权的分组引用
dataGroupRel.keySet().removeIf(s -> !authorizedGroupIdList.contains(s));
// 查询配置已启用的主机
List<Long> hostIdList = dataGroupRel.values()
.stream()
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
List<Long> enabledConfigHostId = hostConfigService.getEnabledConfigHostId(type, hostIdList);
// 从分组引用中移除
// 从分组引用中移除未启用的主机
dataGroupRel.forEach((k, v) -> v.removeIf(s -> !enabledConfigHostId.contains(s)));
return enabledConfigHostId;
}
/**
@@ -288,59 +238,19 @@ public class AssetAuthorizedDataServiceImpl implements AssetAuthorizedDataServic
}
/**
* 获取主机分组树 主机节点映射
* 查询已授权的主机列表
*
* @param allData allData
* @param dataGroup dataGroup
* @param dataGroupRel dataGroupRel
* @param authorizedGroupIdList authorizedGroupIdList
* @return hostGroupId:hostIdList
*/
private Map<String, Set<Long>> getAuthorizedHostGroupNodes(boolean allData,
List<DataGroupDTO> dataGroup,
Map<Long, Set<Long>> dataGroupRel,
List<Long> authorizedGroupIdList) {
Map<String, Set<Long>> result = new HashMap<>();
dataGroup.stream()
.map(DataGroupDTO::getId)
// 因为可能父菜单没有授权 这里需要判断分组权限
.filter(id -> allData || authorizedGroupIdList.contains(id))
.forEach(s -> result.put(String.valueOf(s), dataGroupRel.get(s)));
return result;
}
/**
* 查询已授权的所有主机
*
* @param allData allData
* @param dataGroup dataGroup
* @param dataGroupRel dataGroupRel
* @param authorizedGroupIdList authorizedGroupIdList
* @param enabledConfigHostId enabledConfigHostId
* @param dataGroupRel dataGroupRel
* @return hosts
*/
private List<HostVO> getAuthorizedHostList(boolean allData,
List<DataGroupDTO> dataGroup,
Map<Long, Set<Long>> dataGroupRel,
List<Long> authorizedGroupIdList,
List<Long> enabledConfigHostId) {
private List<HostVO> getAuthorizedHostList(Map<Long, Set<Long>> dataGroupRel) {
// 查询主机列表
List<HostVO> hosts = hostService.getHostListByCache()
Map<Long, HostVO> hostMap = hostService.getHostListByCache()
.stream()
.filter(s -> enabledConfigHostId.contains(s.getId()))
.collect(Collectors.toList());
// 全部数据直接返回
if (allData) {
return hosts;
}
Map<Long, HostVO> hostMap = hosts.stream()
.collect(Collectors.toMap(HostVO::getId, Function.identity(), Functions.right()));
// 设置已授权的数据
return dataGroup.stream()
.map(DataGroupDTO::getId)
// 因为可能父菜单没有授权 这里需要判断分组权限
.filter(authorizedGroupIdList::contains)
.map(dataGroupRel::get)
// 设置已授权的数据
return dataGroupRel.values()
.stream()
.filter(Lists::isNoneEmpty)
.flatMap(Collection::stream)
.distinct()

View File

@@ -66,7 +66,8 @@ public class AssetDataGrantServiceImpl implements AssetDataGrantService {
List<Long> idList = request.getIdList();
if (!Lists.isEmpty(idList)) {
List<DataGroupDTO> groupList = dataGroupApi.getByIdList(idList);
Valid.eq(groupList.size(), idList.size(), ErrorMessage.DATA_MODIFIED);
idList.clear();
idList.addAll(Lists.map(groupList, DataGroupDTO::getId));
}
// 数据授权
SpringHolder.getBean(AssetDataGrantService.class)
@@ -82,7 +83,8 @@ public class AssetDataGrantServiceImpl implements AssetDataGrantService {
List<Long> idList = request.getIdList();
if (!Lists.isEmpty(idList)) {
List<HostKeyDO> keys = hostKeyDAO.selectBatchIds(idList);
Valid.eq(keys.size(), idList.size(), ErrorMessage.DATA_MODIFIED);
idList.clear();
idList.addAll(Lists.map(keys, HostKeyDO::getId));
}
// 数据授权
SpringHolder.getBean(AssetDataGrantService.class)
@@ -98,7 +100,8 @@ public class AssetDataGrantServiceImpl implements AssetDataGrantService {
List<Long> idList = request.getIdList();
if (!Lists.isEmpty(idList)) {
List<HostIdentityDO> identities = hostIdentityDAO.selectBatchIds(idList);
Valid.eq(identities.size(), idList.size(), ErrorMessage.DATA_MODIFIED);
idList.clear();
idList.addAll(Lists.map(identities, HostIdentityDO::getId));
}
// 数据授权
SpringHolder.getBean(AssetDataGrantService.class)

View File

@@ -94,7 +94,7 @@ public class ExecCommandServiceImpl implements ExecCommandService {
Long userId = user.getId();
List<Long> hostIdList = request.getHostIdList();
// 检查主机权限
List<Long> authorizedHostIdList = assetAuthorizedDataService.getUserAuthorizedHostId(userId, HostConfigTypeEnum.SSH);
List<Long> authorizedHostIdList = assetAuthorizedDataService.getUserAuthorizedHostIdWithEnabledConfig(userId, HostConfigTypeEnum.SSH);
hostIdList.removeIf(s -> !authorizedHostIdList.contains(s));
log.info("ExecService.startExecCommand host hostList: {}", hostIdList);
Valid.notEmpty(hostIdList, ErrorMessage.CHECK_AUTHORIZED_HOST);

View File

@@ -360,7 +360,7 @@ public class ExecJobServiceImpl implements ExecJobService {
*/
private void checkHostPermission(List<Long> hostIdList) {
// 查询有权限的主机
List<Long> authorizedHostIdList = assetAuthorizedDataService.getUserAuthorizedHostId(SecurityUtils.getLoginUserId(), HostConfigTypeEnum.SSH);
List<Long> authorizedHostIdList = assetAuthorizedDataService.getUserAuthorizedHostIdWithEnabledConfig(SecurityUtils.getLoginUserId(), HostConfigTypeEnum.SSH);
for (Long hostId : hostIdList) {
Valid.isTrue(authorizedHostIdList.contains(hostId), Strings.format(ErrorMessage.PLEASE_CHECK_HOST_SSH, hostId));
}

View File

@@ -28,6 +28,8 @@ import com.orion.ops.module.asset.entity.vo.HostIdentityVO;
import com.orion.ops.module.asset.enums.HostIdentityTypeEnum;
import com.orion.ops.module.asset.service.HostIdentityService;
import com.orion.ops.module.infra.api.DataExtraApi;
import com.orion.ops.module.infra.api.DataPermissionApi;
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -61,6 +63,9 @@ public class HostIdentityServiceImpl implements HostIdentityService {
@Resource
private DataExtraApi dataExtraApi;
@Resource
private DataPermissionApi dataPermissionApi;
@Override
public Long createHostIdentity(HostIdentityCreateRequest request) {
log.info("HostIdentityService-createHostIdentity request: {}", JSON.toJSONString(request));
@@ -193,6 +198,8 @@ public class HostIdentityServiceImpl implements HostIdentityService {
hostConfigDAO.setIdentityIdWithNull(id);
// 删除主机身份额外配置
dataExtraApi.deleteHostIdentityExtra(id);
// 删除数据权限
dataPermissionApi.deleteByRelId(DataPermissionTypeEnum.HOST_IDENTITY, id);
// 删除缓存
RedisMaps.delete(HostCacheKeyDefine.HOST_IDENTITY.getKey(), record.getId());
log.info("HostIdentityService-deleteHostIdentityById effect: {}", effect);

View File

@@ -24,6 +24,8 @@ import com.orion.ops.module.asset.entity.request.host.HostKeyUpdateRequest;
import com.orion.ops.module.asset.entity.vo.HostKeyVO;
import com.orion.ops.module.asset.service.HostKeyService;
import com.orion.ops.module.infra.api.DataExtraApi;
import com.orion.ops.module.infra.api.DataPermissionApi;
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -56,6 +58,9 @@ public class HostKeyServiceImpl implements HostKeyService {
@Resource
private DataExtraApi dataExtraApi;
@Resource
private DataPermissionApi dataPermissionApi;
@Override
public Long createHostKey(HostKeyCreateRequest request) {
log.info("HostKeyService-createHostKey request: {}", JSON.toJSONString(request));
@@ -179,6 +184,8 @@ public class HostKeyServiceImpl implements HostKeyService {
hostConfigDAO.setKeyIdWithNull(id);
// 删除主机秘钥额外配置
dataExtraApi.deleteHostKeyExtra(id);
// 删除数据权限
dataPermissionApi.deleteByRelId(DataPermissionTypeEnum.HOST_KEY, id);
// 删除缓存
RedisMaps.delete(HostCacheKeyDefine.HOST_KEY.getKey(), record.getId());
log.info("HostKeyService-deleteHostKeyById effect: {}", effect);

View File

@@ -31,8 +31,6 @@ import com.orion.ops.module.asset.service.HostConfigService;
import com.orion.ops.module.asset.service.HostExtraService;
import com.orion.ops.module.asset.service.HostTerminalService;
import com.orion.ops.module.infra.api.DataPermissionApi;
import com.orion.ops.module.infra.api.SystemUserApi;
import com.orion.ops.module.infra.entity.dto.user.SystemUserDTO;
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -76,9 +74,6 @@ public class HostTerminalServiceImpl implements HostTerminalService {
@Resource
private DataPermissionApi dataPermissionApi;
@Resource
private SystemUserApi systemUserApi;
@Override
public JSONArray getTerminalThemes() {
try (InputStream in = HostTerminalService.class.getResourceAsStream(TERMINAL_PATH)) {
@@ -129,35 +124,28 @@ public class HostTerminalServiceImpl implements HostTerminalService {
public HostTerminalConnectDTO getTerminalConnectInfo(Long userId, HostDO host, HostConnectTypeEnum type) {
Long hostId = host.getId();
log.info("HostConnectService.getTerminalConnectInfo hostId: {}, userId: {}", hostId, userId);
// 查询用户
SystemUserDTO user = systemUserApi.getUserById(userId);
Valid.notNull(user, ErrorMessage.USER_ABSENT);
// 验证主机是否有权限
List<Long> hostIdList = assetAuthorizedDataService.getUserAuthorizedHostId(userId);
Valid.isTrue(hostIdList.contains(hostId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_GROUP.getPermissionName());
// 查询主机配置
HostSshConfigModel config = hostConfigService.getHostConfig(hostId, HostConfigTypeEnum.SSH);
Valid.notNull(config, ErrorMessage.CONFIG_ABSENT);
// 查询主机额外配置
HostSshExtraModel extra = hostExtraService.getHostExtra(userId, hostId, HostExtraItemEnum.SSH);
// 非管理员检查权限
if (!systemUserApi.isAdminUser(userId)) {
// 验证主机是否有权限
List<Long> hostIdList = assetAuthorizedDataService.getUserAuthorizedHostId(userId);
Valid.isTrue(hostIdList.contains(hostId),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_GROUP.getPermissionName());
// 检查额外配置权限
if (extra != null) {
HostExtraSshAuthTypeEnum extraAuthType = HostExtraSshAuthTypeEnum.of(extra.getAuthType());
if (HostExtraSshAuthTypeEnum.CUSTOM_KEY.equals(extraAuthType)) {
// 验证主机秘钥是否有权限
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_KEY, userId, extra.getKeyId()),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_KEY.getPermissionName());
} else if (HostExtraSshAuthTypeEnum.CUSTOM_IDENTITY.equals(extraAuthType)) {
// 验证主机身份是否有权限
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_IDENTITY, userId, extra.getIdentityId()),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_IDENTITY.getPermissionName());
}
if (extra != null) {
HostExtraSshAuthTypeEnum extraAuthType = HostExtraSshAuthTypeEnum.of(extra.getAuthType());
if (HostExtraSshAuthTypeEnum.CUSTOM_KEY.equals(extraAuthType)) {
// 验证主机秘钥是否有权限
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_KEY, userId, extra.getKeyId()),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_KEY.getPermissionName());
} else if (HostExtraSshAuthTypeEnum.CUSTOM_IDENTITY.equals(extraAuthType)) {
// 验证主机身份是否有权限
Valid.isTrue(dataPermissionApi.hasPermission(DataPermissionTypeEnum.HOST_IDENTITY, userId, extra.getIdentityId()),
ErrorMessage.ANY_NO_PERMISSION,
DataPermissionTypeEnum.HOST_IDENTITY.getPermissionName());
}
}
// 获取连接配置

View File

@@ -198,7 +198,7 @@ public class DataPermissionServiceImpl implements DataPermissionService {
.collect(Collectors.toList());
List<Long> userIdList = mapper.apply(DataPermissionDO::getUserId);
List<Long> roleIdList = mapper.apply(DataPermissionDO::getRoleId);
this.deleteCache(userIdList, roleIdList);
this.deleteCache(type, userIdList, roleIdList);
return effect;
}
@@ -208,7 +208,7 @@ public class DataPermissionServiceImpl implements DataPermissionService {
// 删除
int effect = dataPermissionDAO.delete(wrapper);
// 删除缓存
this.deleteCache(Lists.singleton(userId), null);
this.deleteCache(null, Lists.singleton(userId), null);
return effect;
}
@@ -218,7 +218,7 @@ public class DataPermissionServiceImpl implements DataPermissionService {
// 删除
int effect = dataPermissionDAO.delete(wrapper);
// 删除缓存
this.deleteCache(null, Lists.singleton(roleId));
this.deleteCache(null, null, Lists.singleton(roleId));
return effect;
}
@@ -277,10 +277,11 @@ public class DataPermissionServiceImpl implements DataPermissionService {
/**
* 删除缓存
*
* @param type type
* @param userIdList userIdList
* @param roleIdList roleIdList
*/
private void deleteCache(List<Long> userIdList, List<Long> roleIdList) {
private void deleteCache(String type, List<Long> userIdList, List<Long> roleIdList) {
Set<Long> deleteUserIdList = new HashSet<>(4);
if (!Lists.isEmpty(userIdList)) {
deleteUserIdList.addAll(userIdList);
@@ -293,12 +294,21 @@ public class DataPermissionServiceImpl implements DataPermissionService {
if (deleteUserIdList.isEmpty()) {
return;
}
// 删除的类型
List<String> types;
if (type == null) {
types = Arrays.stream(DataPermissionTypeEnum.values())
.map(Enum::name)
.collect(Collectors.toList());
} else {
types = Lists.singleton(type);
}
// 删除缓存
List<String> keys = new ArrayList<>();
for (DataPermissionTypeEnum type : DataPermissionTypeEnum.values()) {
userIdList.stream()
for (String value : types) {
deleteUserIdList.stream()
.filter(Objects::nonNull)
.map(s -> DataPermissionCacheKeyDefine.DATA_PERMISSION_USER.format(type.name(), s))
.map(s -> DataPermissionCacheKeyDefine.DATA_PERMISSION_USER.format(value, s))
.forEach(keys::add);
}
RedisLists.delete(keys);

View File

@@ -20,12 +20,10 @@
<!-- 角色提示信息 -->
<template v-if="type === GrantType.ROLE">
当前选择的角色为 <span class="span-blue mr4">{{ currentSubject.text }}</span>
<span class="span-blue ml4" v-if="currentSubject.code === AdminRoleCode">管理员拥有全部权限, 无需配置</span>
</template>
<!-- 用户提示信息 -->
<template v-else-if="type === GrantType.USER">
当前选择的用户为 <span class="span-blue mr4">{{ currentSubject.text }}</span>
<span class="ml4">若当前选择的用户角色包含管理员则无需配置 (管理员拥有全部权限)</span>
</template>
</span>
</a-alert>
@@ -57,7 +55,6 @@
import type { TabRouterItem } from '@/components/view/tab-router/types';
import type { AssetAuthorizedDataQueryRequest, AssetDataGrantRequest } from '@/api/asset/asset-data-grant';
import { ref } from 'vue';
import { AdminRoleCode } from '@/types/const';
import { GrantType } from '../types/const';
import RouterRoles from './router-roles.vue';
import RouterUsers from './router-users.vue';

View File

@@ -1,11 +1,11 @@
<template>
<grant-layout :type="type"
:loading="loading"
@fetch="fetchAuthorizedGroup"
@fetch="fetchAuthorizedData"
@grant="doGrant">
<!-- 分组 -->
<host-group-tree outer-class="group-main-tree"
v-model:checked-keys="checkedGroups"
<host-group-tree v-model:checked-keys="checkedGroups"
outer-class="group-main-tree"
:checkable="true"
:editable="false"
:loading="loading"
@@ -44,7 +44,7 @@
const selectedGroup = ref<TreeNodeData>({});
// 获取授权列表
const fetchAuthorizedGroup = async (request: AssetAuthorizedDataQueryRequest) => {
const fetchAuthorizedData = async (request: AssetAuthorizedDataQueryRequest) => {
setLoading(true);
try {
const { data } = await getAuthorizedHostGroup(request);
@@ -60,6 +60,7 @@
const doGrant = async (request: AssetDataGrantRequest) => {
setLoading(true);
try {
// 执行授权
await grantHostGroup({
...request,
idList: checkedGroups.value
@@ -69,6 +70,8 @@
} finally {
setLoading(false);
}
// 查询数据
await fetchAuthorizedData(request);
};
</script>

View File

@@ -1,7 +1,7 @@
<template>
<grant-layout :type="type"
:loading="loading"
@fetch="fetchAuthorizedGroup"
@fetch="fetchAuthorizedData"
@grant="doGrant">
<!-- 主机身份表格 -->
<a-table row-key="id"
@@ -73,7 +73,7 @@
const hostKeys = ref<Array<HostKeyQueryResponse>>([]);
// 获取授权列表
const fetchAuthorizedGroup = async (request: AssetAuthorizedDataQueryRequest) => {
const fetchAuthorizedData = async (request: AssetAuthorizedDataQueryRequest) => {
setLoading(true);
try {
const { data } = await getAuthorizedHostIdentity(request);
@@ -88,6 +88,7 @@
const doGrant = async (request: AssetDataGrantRequest) => {
setLoading(true);
try {
// 执行授权
await grantHostIdentity({
...request,
idList: selectedKeys.value
@@ -97,6 +98,8 @@
} finally {
setLoading(false);
}
// 查询数据
await fetchAuthorizedData(request);
};
// 点击行

View File

@@ -1,7 +1,7 @@
<template>
<grant-layout :type="type"
:loading="loading"
@fetch="fetchAuthorizedGroup"
@fetch="fetchAuthorizedData"
@grant="doGrant">
<!-- 主机秘钥表格 -->
<a-table row-key="id"
@@ -49,7 +49,7 @@
const hostKeys = ref<Array<HostKeyQueryResponse>>([]);
// 获取授权列表
const fetchAuthorizedGroup = async (request: AssetAuthorizedDataQueryRequest) => {
const fetchAuthorizedData = async (request: AssetAuthorizedDataQueryRequest) => {
setLoading(true);
try {
const { data } = await getAuthorizedHostKey(request);
@@ -64,6 +64,7 @@
const doGrant = async (request: AssetDataGrantRequest) => {
setLoading(true);
try {
// 执行授权
await grantHostKey({
...request,
idList: selectedKeys.value
@@ -73,6 +74,8 @@
} finally {
setLoading(false);
}
// 查询数据
await fetchAuthorizedData(request);
};
// 点击行