feat: 数据分组授权.

This commit is contained in:
lijiahang
2023-11-23 17:19:42 +08:00
parent 1188502bb6
commit 2230d4ed8b
30 changed files with 727 additions and 74 deletions

View File

@@ -0,0 +1,49 @@
package com.orion.ops.framework.common.entity;
import java.util.List;
/**
* 树节点
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 16:52
*/
public interface TreeNode<T extends TreeNode<T>> {
/**
* id
*
* @return id
*/
Long getId();
/**
* parentId
*
* @return parentId
*/
Long getParentId();
/**
* sort
*
* @return sort
*/
Integer getSort();
/**
* children
*
* @return children
*/
List<T> getChildren();
/**
* 设置 children
*
* @param children children
*/
void setChildren(List<T> children);
}

View File

@@ -0,0 +1,84 @@
package com.orion.ops.framework.common.utils;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.entity.TreeNode;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* 树工具类
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 16:52
*/
public class TreeUtils {
private TreeUtils() {
}
/**
* 获取节点以及父节点
*
* @param nodes nodes
* @param idList idList
* @param result result
* @param <T> T
*/
public static <T extends TreeNode<T>> void getAllNodes(List<T> nodes,
List<Long> idList,
List<T> result) {
if (Lists.isEmpty(idList)) {
return;
}
// 获取当前节点的数据
List<T> currentNodes = nodes.stream()
.filter(s -> idList.contains(s.getId()))
.collect(Collectors.toList());
if (currentNodes.isEmpty()) {
return;
}
result.addAll(currentNodes);
// 获取父节点id
List<Long> parentIdList = currentNodes.stream()
.map(T::getParentId)
.distinct()
.collect(Collectors.toList());
// 如果为空 或者唯一的元素为 rootId 直接返回
if (parentIdList.isEmpty()
|| parentIdList.size() == 1
|| parentIdList.get(0).equals(Const.ROOT_PARENT_ID)) {
return;
}
// 递归
getAllNodes(nodes, parentIdList, result);
}
/**
* 构建树
*
* @param parentNode parentNode
* @param nodes nodes
* @param <T> T
*/
public static <T extends TreeNode<T>> void buildGroupTree(T parentNode,
List<T> nodes) {
// 获取子节点
List<T> childrenNodes = nodes.stream()
.filter(s -> parentNode.getId().equals(s.getParentId()))
.sorted(Comparator.comparing(T::getSort))
.collect(Collectors.toList());
if (childrenNodes.isEmpty()) {
return;
}
parentNode.setChildren(childrenNodes);
// 遍历子节点
for (T childrenNode : childrenNodes) {
buildGroupTree(childrenNode, nodes);
}
}
}

View File

@@ -0,0 +1,45 @@
package com.orion.ops.module.asset.controller;
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
import com.orion.ops.framework.security.core.utils.SecurityUtils;
import com.orion.ops.framework.web.core.annotation.RestWrapper;
import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO;
import com.orion.ops.module.asset.service.HostGroupService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* 资产模块 授权数据服务
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 14:10
*/
@Tag(name = "asset - 授权数据服务")
@Slf4j
@Validated
@RestWrapper
@RestController
@RequestMapping("/asset/authorized-data")
public class AssetDataController {
@Resource
private HostGroupService hostGroupService;
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/host-group")
@Operation(summary = "查询已授权的主机分组")
public List<HostGroupTreeVO> getAuthorizedHostGroup() {
return hostGroupService.getUserAuthorizedHostGroup(SecurityUtils.getLoginUserId());
}
}

View File

@@ -6,6 +6,8 @@ import com.orion.ops.framework.log.core.annotation.IgnoreLog;
import com.orion.ops.framework.log.core.enums.IgnoreLogMode; import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
import com.orion.ops.framework.web.core.annotation.RestWrapper; import com.orion.ops.framework.web.core.annotation.RestWrapper;
import com.orion.ops.module.asset.define.operator.HostGroupOperatorType; import com.orion.ops.module.asset.define.operator.HostGroupOperatorType;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantQueryRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest; import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest;
import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO; import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO;
import com.orion.ops.module.asset.service.HostGroupService; import com.orion.ops.module.asset.service.HostGroupService;
@@ -45,7 +47,7 @@ public class HostGroupController {
@OperatorLog(HostGroupOperatorType.CREATE) @OperatorLog(HostGroupOperatorType.CREATE)
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建主机分组 - 管理") @Operation(summary = "创建主机分组")
@PreAuthorize("@ss.hasPermission('asset:host-group:create')") @PreAuthorize("@ss.hasPermission('asset:host-group:create')")
public Long createHostGroup(@Validated @RequestBody DataGroupCreateDTO request) { public Long createHostGroup(@Validated @RequestBody DataGroupCreateDTO request) {
return hostGroupService.createHostGroup(request); return hostGroupService.createHostGroup(request);
@@ -53,7 +55,7 @@ public class HostGroupController {
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/tree") @GetMapping("/tree")
@Operation(summary = "查询主机分组 - 管理") @Operation(summary = "查询主机分组")
@PreAuthorize("@ss.hasPermission('asset:host-group:query')") @PreAuthorize("@ss.hasPermission('asset:host-group:query')")
public List<HostGroupTreeVO> queryHostGroupTree() { public List<HostGroupTreeVO> queryHostGroupTree() {
return hostGroupService.queryHostGroupTree(); return hostGroupService.queryHostGroupTree();
@@ -61,7 +63,7 @@ public class HostGroupController {
@OperatorLog(HostGroupOperatorType.RENAME) @OperatorLog(HostGroupOperatorType.RENAME)
@PutMapping("/rename") @PutMapping("/rename")
@Operation(summary = "修改名称 - 管理") @Operation(summary = "修改名称")
@PreAuthorize("@ss.hasPermission('asset:host-group:update')") @PreAuthorize("@ss.hasPermission('asset:host-group:update')")
public Integer updateHostGroupName(@Validated @RequestBody DataGroupRenameDTO request) { public Integer updateHostGroupName(@Validated @RequestBody DataGroupRenameDTO request) {
return hostGroupService.updateHostGroupName(request); return hostGroupService.updateHostGroupName(request);
@@ -69,7 +71,7 @@ public class HostGroupController {
@OperatorLog(HostGroupOperatorType.MOVE) @OperatorLog(HostGroupOperatorType.MOVE)
@PutMapping("/move") @PutMapping("/move")
@Operation(summary = "移动位置 - 管理") @Operation(summary = "移动位置")
@PreAuthorize("@ss.hasPermission('asset:host-group:update')") @PreAuthorize("@ss.hasPermission('asset:host-group:update')")
public Integer moveHostGroup(@Validated @RequestBody DataGroupMoveDTO request) { public Integer moveHostGroup(@Validated @RequestBody DataGroupMoveDTO request) {
return hostGroupService.moveHostGroup(request); return hostGroupService.moveHostGroup(request);
@@ -77,7 +79,7 @@ public class HostGroupController {
@OperatorLog(HostGroupOperatorType.DELETE) @OperatorLog(HostGroupOperatorType.DELETE)
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "删除主机分组 - 管理") @Operation(summary = "删除主机分组")
@PreAuthorize("@ss.hasPermission('asset:host-group:delete')") @PreAuthorize("@ss.hasPermission('asset:host-group:delete')")
public Integer deleteHostGroup(@RequestParam("id") Long id) { public Integer deleteHostGroup(@RequestParam("id") Long id) {
return hostGroupService.deleteHostGroup(id); return hostGroupService.deleteHostGroup(id);
@@ -85,7 +87,7 @@ public class HostGroupController {
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/rel-list") @GetMapping("/rel-list")
@Operation(summary = "查询分组内主机 - 管理") @Operation(summary = "查询分组内主机")
@Parameter(name = "groupId", description = "groupId", required = true) @Parameter(name = "groupId", description = "groupId", required = true)
@PreAuthorize("@ss.hasPermission('asset:host-group:query')") @PreAuthorize("@ss.hasPermission('asset:host-group:query')")
public Set<Long> queryHostGroupRel(@RequestParam("groupId") Long groupId) { public Set<Long> queryHostGroupRel(@RequestParam("groupId") Long groupId) {
@@ -93,13 +95,33 @@ public class HostGroupController {
} }
@OperatorLog(HostGroupOperatorType.UPDATE_REL) @OperatorLog(HostGroupOperatorType.UPDATE_REL)
@PostMapping("/update-rel") @PutMapping("/update-rel")
@Operation(summary = "修改分组内主机 - 管理") @Operation(summary = "修改分组内主机")
@PreAuthorize("@ss.hasPermission('asset:host:update')") @PreAuthorize("@ss.hasPermission('asset:host-group:update')")
public HttpWrapper<?> updateHostGroupRel(@Validated @RequestBody HostGroupRelUpdateRequest request) { public HttpWrapper<?> updateHostGroupRel(@Validated @RequestBody HostGroupRelUpdateRequest request) {
hostGroupService.updateHostGroupRel(request); hostGroupService.updateHostGroupRel(request);
return HttpWrapper.ok(); return HttpWrapper.ok();
} }
// TODO 日志 host-group:grant
// TODO 菜单 asset:host-group:grant
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/get-authorized-group")
@Operation(summary = "获取已授权的分组")
@PreAuthorize("@ss.hasPermission('asset:host-group:grant')")
public List<Long> getAuthorizedHostGroup(@RequestParam HostGroupGrantQueryRequest request) {
return hostGroupService.getAuthorizedHostGroup(request);
}
@OperatorLog(HostGroupOperatorType.GRANT)
@PutMapping("/grant")
@Operation(summary = "主机分组授权")
@PreAuthorize("@ss.hasPermission('asset:host-group:grant')")
public HttpWrapper<?> grantHostGroup(@RequestBody HostGroupGrantRequest request) {
hostGroupService.grantHostGroup(request);
return HttpWrapper.ok();
}
} }

View File

@@ -26,6 +26,8 @@ public class HostGroupOperatorType extends InitializingOperatorTypes {
public static final String UPDATE_REL = "host-group:update-rel"; public static final String UPDATE_REL = "host-group:update-rel";
public static final String GRANT = "host-group:grant";
@Override @Override
public OperatorType[] types() { public OperatorType[] types() {
return new OperatorType[]{ return new OperatorType[]{
@@ -34,6 +36,7 @@ public class HostGroupOperatorType extends InitializingOperatorTypes {
new OperatorType(L, MOVE, "移动主机分组 <sb>${source}</sb> 到 <sb>${target}(${position})</sb>"), new OperatorType(L, MOVE, "移动主机分组 <sb>${source}</sb> 到 <sb>${target}(${position})</sb>"),
new OperatorType(H, DELETE, "删除主机分组 <sb>${groupName}</sb>"), new OperatorType(H, DELETE, "删除主机分组 <sb>${groupName}</sb>"),
new OperatorType(M, UPDATE_REL, "修改分组内主机 <sb>${groupName}</sb>"), new OperatorType(M, UPDATE_REL, "修改分组内主机 <sb>${groupName}</sb>"),
new OperatorType(H, GRANT, "将主机分组权限授予 <sb>${type}</sb> <sb>${name}</sb>"),
}; };
} }

View File

@@ -0,0 +1,31 @@
package com.orion.ops.module.asset.entity.request.host;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 主机分组 查询请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 11:56
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "HostGroupQueryRequest", description = "主机分组 查询请求对象")
public class HostGroupGrantQueryRequest implements Serializable {
@Schema(description = "用户id")
private Long userId;
@Schema(description = "角色id")
private Long roleId;
}

View File

@@ -0,0 +1,35 @@
package com.orion.ops.module.asset.entity.request.host;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 主机分组 授权请求对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 11:56
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "HostGroupGrantRequest", description = "主机分组 授权请求对象")
public class HostGroupGrantRequest implements Serializable {
@Schema(description = "用户id")
private Long userId;
@Schema(description = "角色id")
private Long roleId;
@Schema(description = "分组id")
private List<Long> groupIdList;
}

View File

@@ -1,6 +1,7 @@
package com.orion.ops.module.asset.entity.vo; package com.orion.ops.module.asset.entity.vo;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.orion.ops.framework.common.entity.TreeNode;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@@ -8,6 +9,7 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@@ -22,7 +24,8 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "HostGroupTreeVO", description = "主机秘钥 视图响应对象") @Schema(name = "HostGroupTreeVO", description = "主机秘钥 视图响应对象")
public class HostGroupTreeVO implements Serializable { public class HostGroupTreeVO implements TreeNode<HostGroupTreeVO>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@JsonProperty("key") @JsonProperty("key")
@@ -36,7 +39,13 @@ public class HostGroupTreeVO implements Serializable {
@Schema(description = "组名称") @Schema(description = "组名称")
private String name; private String name;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "子节点") @Schema(description = "子节点")
private List<HostGroupTreeVO> children; private List<HostGroupTreeVO> children;
@Schema(description = "分组内主机id")
private Collection<Long> hosts;
} }

View File

@@ -1,5 +1,7 @@
package com.orion.ops.module.asset.service; package com.orion.ops.module.asset.service;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantQueryRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest; import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest;
import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO; import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO;
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO; import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
@@ -72,4 +74,27 @@ public interface HostGroupService {
*/ */
void updateHostGroupRel(HostGroupRelUpdateRequest request); void updateHostGroupRel(HostGroupRelUpdateRequest request);
/**
* 获取已授权的分组
*
* @param request request
* @return grantGroupId
*/
List<Long> getAuthorizedHostGroup(HostGroupGrantQueryRequest request);
/**
* 授权主机分组
*
* @param request request
*/
void grantHostGroup(HostGroupGrantRequest request);
/**
* 查询用户已授权的主机分组和主机
*
* @param userId userId
* @return group
*/
List<HostGroupTreeVO> getUserAuthorizedHostGroup(Long userId);
} }

View File

@@ -1,23 +1,27 @@
package com.orion.ops.module.asset.service.impl; package com.orion.ops.module.asset.service.impl;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.utils.TreeUtils;
import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.module.asset.convert.HostGroupConvert; import com.orion.ops.module.asset.convert.HostGroupConvert;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantQueryRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupGrantRequest;
import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest; import com.orion.ops.module.asset.entity.request.host.HostGroupRelUpdateRequest;
import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO; import com.orion.ops.module.asset.entity.vo.HostGroupTreeVO;
import com.orion.ops.module.asset.service.HostGroupService; import com.orion.ops.module.asset.service.HostGroupService;
import com.orion.ops.module.infra.api.DataGroupApi; import com.orion.ops.module.infra.api.*;
import com.orion.ops.module.infra.api.DataGroupRelApi; import com.orion.ops.module.infra.entity.dto.data.*;
import com.orion.ops.module.infra.api.DataPermissionApi;
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
import com.orion.ops.module.infra.entity.dto.data.DataGroupMoveDTO;
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
import com.orion.ops.module.infra.enums.DataGroupTypeEnum; import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
import com.orion.ops.module.infra.enums.DataPermissionTypeEnum; import com.orion.ops.module.infra.enums.DataPermissionTypeEnum;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@@ -39,6 +43,12 @@ public class HostGroupServiceImpl implements HostGroupService {
@Resource @Resource
private DataPermissionApi dataPermissionApi; private DataPermissionApi dataPermissionApi;
@Resource
private SystemRoleApi systemRoleApi;
@Resource
private SystemUserApi systemUserApi;
@Override @Override
public Long createHostGroup(DataGroupCreateDTO request) { public Long createHostGroup(DataGroupCreateDTO request) {
return dataGroupApi.createDataGroup(DataGroupTypeEnum.HOST, request); return dataGroupApi.createDataGroup(DataGroupTypeEnum.HOST, request);
@@ -80,4 +90,93 @@ public class HostGroupServiceImpl implements HostGroupService {
dataGroupRelApi.updateGroupRel(request.getGroupId(), request.getHostIdList()); dataGroupRelApi.updateGroupRel(request.getGroupId(), request.getHostIdList());
} }
@Override
public List<Long> getAuthorizedHostGroup(HostGroupGrantQueryRequest request) {
Long userId = request.getUserId();
Long roleId = request.getRoleId();
Valid.isTrue(userId != null || roleId != null);
if (userId != null) {
// 查询用户数据
return dataPermissionApi.getRelIdListByUserId(DataPermissionTypeEnum.HOST_GROUP, userId);
} else {
// 查询角色数据
return dataPermissionApi.getRelIdListByRoleId(DataPermissionTypeEnum.HOST_GROUP, roleId);
}
}
@Override
public void grantHostGroup(HostGroupGrantRequest request) {
Long userId = request.getUserId();
Long roleId = request.getRoleId();
Valid.isTrue(userId != null || roleId != null);
if (userId != null) {
// 检测用户是否存在
Valid.notNull(systemUserApi.getUserById(userId), ErrorMessage.USER_ABSENT);
}
if (roleId != null) {
// 检测角色是否存在
Valid.notNull(systemRoleApi.getRoleById(roleId), ErrorMessage.ROLE_ABSENT);
}
// 授权
DataPermissionUpdateDTO grant = DataPermissionUpdateDTO.builder()
.roleId(roleId)
.userId(userId)
.relIdList(request.getGroupIdList())
.build();
dataPermissionApi.updateDataPermission(DataPermissionTypeEnum.HOST_GROUP, grant);
}
@Override
public List<HostGroupTreeVO> getUserAuthorizedHostGroup(Long userId) {
if (systemUserApi.isAdminUser(userId)) {
// 管理员查询所有
return this.buildUserAuthorizedHostGroup(null);
} else {
// 其他用户查询授权的分组
List<Long> authorizedGroupIdList = dataPermissionApi.getUserAuthorizedRelIdList(DataPermissionTypeEnum.HOST_GROUP, userId);
if (authorizedGroupIdList.isEmpty()) {
return Lists.empty();
}
return this.buildUserAuthorizedHostGroup(authorizedGroupIdList);
}
}
/**
* 构建授权的主机分组树
*
* @param authorizedGroupIdList authorizedGroupIdList
* @return tree
*/
private List<HostGroupTreeVO> buildUserAuthorizedHostGroup(List<Long> authorizedGroupIdList) {
// 查询分组
List<DataGroupDTO> dataGroup = dataGroupApi.getDataGroupList(DataGroupTypeEnum.HOST);
// 过滤分组
if (!Lists.isEmpty(authorizedGroupIdList)) {
// 构建已授权的分组
List<DataGroupDTO> relNodes = new ArrayList<>();
TreeUtils.getAllNodes(dataGroup, authorizedGroupIdList, relNodes);
dataGroup = relNodes;
}
// 查询分组引用
Map<Long, Set<Long>> groupRel = dataGroupRelApi.getGroupRelList(DataGroupTypeEnum.HOST);
// 设置组内数据
List<HostGroupTreeVO> groupList = HostGroupConvert.MAPPER.toList(dataGroup);
if (Lists.isEmpty(authorizedGroupIdList)) {
// 设置全部数据
groupList.forEach(s -> s.setHosts(groupRel.get(s.getId())));
} else {
// 仅设置已授权的数据
groupList.stream()
.filter(s -> authorizedGroupIdList.contains(s.getId()))
.forEach(s -> s.setHosts(groupRel.get(s.getId())));
}
// 构建树
HostGroupTreeVO rootNode = HostGroupTreeVO.builder()
.id(Const.ROOT_PARENT_ID)
.sort(Const.DEFAULT_SORT)
.build();
TreeUtils.buildGroupTree(rootNode, groupList);
return rootNode.getChildren();
}
} }

View File

@@ -31,7 +31,7 @@ public interface DataPermissionApi {
void updateDataPermission(DataPermissionTypeEnum type, DataPermissionUpdateDTO dto); void updateDataPermission(DataPermissionTypeEnum type, DataPermissionUpdateDTO dto);
/** /**
* 通过 userId 查询 (不包含角色 不走缓存) * 通过 userId 查询数据权限 (不包含角色 不走缓存)
* *
* @param type type * @param type type
* @param userId userId * @param userId userId
@@ -40,7 +40,7 @@ public interface DataPermissionApi {
List<Long> getRelIdListByUserId(DataPermissionTypeEnum type, Long userId); List<Long> getRelIdListByUserId(DataPermissionTypeEnum type, Long userId);
/** /**
* 通过 roleId 查询 不走缓存 * 通过 roleId 查询数据权限 不走缓存
* *
* @param type type * @param type type
* @param roleId roleId * @param roleId roleId
@@ -49,13 +49,13 @@ public interface DataPermissionApi {
List<Long> getRelIdListByRoleId(DataPermissionTypeEnum type, Long roleId); List<Long> getRelIdListByRoleId(DataPermissionTypeEnum type, Long roleId);
/** /**
* 通过 userId 查询 (包含角色 走缓存) * 查询 userId 已授权的数据权限 (包含角色 走缓存)
* *
* @param type type * @param type type
* @param userId userId * @param userId userId
* @return relId * @return relId
*/ */
List<Long> getAllowRelIdList(DataPermissionTypeEnum type, Long userId); List<Long> getUserAuthorizedRelIdList(DataPermissionTypeEnum type, Long userId);
/** /**
* 通过 relId 删除 * 通过 relId 删除

View File

@@ -0,0 +1,22 @@
package com.orion.ops.module.infra.api;
import com.orion.ops.module.infra.entity.dto.role.SystemRoleDTO;
/**
* 角色服务
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 15:16
*/
public interface SystemRoleApi {
/**
* 查询角色
*
* @param id id
* @return role
*/
SystemRoleDTO getRoleById(Long id);
}

View File

@@ -0,0 +1,30 @@
package com.orion.ops.module.infra.api;
import com.orion.ops.module.infra.entity.dto.user.SystemUserDTO;
/**
* 用户服务
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 15:15
*/
public interface SystemUserApi {
/**
* 通过 id 查询用户
*
* @param id id
* @return user
*/
SystemUserDTO getUserById(Long id);
/**
* 用户是否为管理员用户
*
* @param id id
* @return isAdmin
*/
boolean isAdminUser(Long id);
}

View File

@@ -1,5 +1,6 @@
package com.orion.ops.module.infra.entity.dto.data; package com.orion.ops.module.infra.entity.dto.data;
import com.orion.ops.framework.common.entity.TreeNode;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@@ -21,7 +22,7 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "DataGroupDTO", description = "数据分组 业务对象") @Schema(name = "DataGroupDTO", description = "数据分组 业务对象")
public class DataGroupDTO implements Serializable { public class DataGroupDTO implements TreeNode<DataGroupDTO>, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -0,0 +1,39 @@
package com.orion.ops.module.infra.entity.dto.role;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 角色 业务对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-7-16 01:19
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "SystemRoleDTO", description = "角色 业务对象")
public class SystemRoleDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private Long id;
@Schema(description = "角色名称")
private String name;
@Schema(description = "角色编码")
private String code;
@Schema(description = "状态 0停用 1启用")
private Integer status;
}

View File

@@ -0,0 +1,52 @@
package com.orion.ops.module.infra.entity.dto.user;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* 用户 业务对象
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-7-13 18:42
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "SystemUserDTO", description = "用户 业务对象")
public class SystemUserDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "花名")
private String nickname;
@Schema(description = "头像地址")
private String avatar;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "邮箱")
private String email;
@Schema(description = "用户状态 0停用 1启用 2锁定")
private Integer status;
@Schema(description = "最后登录时间")
private Date lastLoginTime;
}

View File

@@ -60,8 +60,8 @@ public class DataPermissionApiImpl implements DataPermissionApi {
} }
@Override @Override
public List<Long> getAllowRelIdList(DataPermissionTypeEnum type, Long userId) { public List<Long> getUserAuthorizedRelIdList(DataPermissionTypeEnum type, Long userId) {
return dataPermissionService.getAllowRelIdList(type.name(), userId); return dataPermissionService.getUserAuthorizedRelIdList(type.name(), userId);
} }
@Override @Override

View File

@@ -0,0 +1,34 @@
package com.orion.ops.module.infra.api.impl;
import com.orion.ops.module.infra.api.SystemRoleApi;
import com.orion.ops.module.infra.convert.SystemRoleProviderConvert;
import com.orion.ops.module.infra.dao.SystemRoleDAO;
import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import com.orion.ops.module.infra.entity.dto.role.SystemRoleDTO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 角色服务实现
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 15:16
*/
@Service
public class SystemRoleApiImpl implements SystemRoleApi {
@Resource
private SystemRoleDAO systemRoleDAO;
@Override
public SystemRoleDTO getRoleById(Long id) {
SystemRoleDO role = systemRoleDAO.selectById(id);
if (role == null) {
return null;
}
return SystemRoleProviderConvert.MAPPER.to(role);
}
}

View File

@@ -0,0 +1,43 @@
package com.orion.ops.module.infra.api.impl;
import com.orion.ops.module.infra.api.SystemUserApi;
import com.orion.ops.module.infra.convert.SystemUserProviderConvert;
import com.orion.ops.module.infra.dao.SystemUserDAO;
import com.orion.ops.module.infra.entity.domain.SystemUserDO;
import com.orion.ops.module.infra.entity.dto.user.SystemUserDTO;
import com.orion.ops.module.infra.service.SystemUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 用户服务实现
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/11/23 15:15
*/
@Service
public class SystemUserApiImpl implements SystemUserApi {
@Resource
private SystemUserDAO systemUserDAO;
@Resource
private SystemUserService systemUserService;
@Override
public SystemUserDTO getUserById(Long id) {
SystemUserDO user = systemUserDAO.selectById(id);
if (user == null) {
return null;
}
return SystemUserProviderConvert.MAPPER.to(user);
}
@Override
public boolean isAdminUser(Long id) {
return systemUserService.isAdminUser(id);
}
}

View File

@@ -0,0 +1,22 @@
package com.orion.ops.module.infra.convert;
import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import com.orion.ops.module.infra.entity.dto.role.SystemRoleDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 角色 对外对象转换器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-7-16 01:19
*/
@Mapper
public interface SystemRoleProviderConvert {
SystemRoleProviderConvert MAPPER = Mappers.getMapper(SystemRoleProviderConvert.class);
SystemRoleDTO to(SystemRoleDO domain);
}

View File

@@ -0,0 +1,22 @@
package com.orion.ops.module.infra.convert;
import com.orion.ops.module.infra.entity.domain.SystemUserDO;
import com.orion.ops.module.infra.entity.dto.user.SystemUserDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 用户 对外对象转换器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-7-13 18:42
*/
@Mapper
public interface SystemUserProviderConvert {
SystemUserProviderConvert MAPPER = Mappers.getMapper(SystemUserProviderConvert.class);
SystemUserDTO to(SystemUserDO domain);
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.ops.framework.mybatis.core.mapper.IMapper; import com.orion.ops.framework.mybatis.core.mapper.IMapper;
import com.orion.ops.module.infra.entity.domain.SystemRoleDO; import com.orion.ops.module.infra.entity.domain.SystemRoleDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -30,4 +31,13 @@ public interface SystemRoleDAO extends IMapper<SystemRoleDO> {
return this.selectList(wrapper); return this.selectList(wrapper);
} }
/**
* 通过 userId 和 roleCode 查询 roleId (检查用户是否包含某个角色)
*
* @param userId userId
* @param code code
* @return roleId
*/
Long getRoleIdByUserIdAndRoleCode(@Param("userId") Long userId, @Param("code") String code);
} }

View File

@@ -1,6 +1,7 @@
package com.orion.ops.module.infra.entity.dto; package com.orion.ops.module.infra.entity.dto;
import com.orion.lang.define.cache.key.model.LongCacheIdModel; import com.orion.lang.define.cache.key.model.LongCacheIdModel;
import com.orion.ops.framework.common.entity.TreeNode;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@@ -22,7 +23,7 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@Schema(name = "DataGroupCacheDTO", description = "数据分组 缓存对象") @Schema(name = "DataGroupCacheDTO", description = "数据分组 缓存对象")
public class DataGroupCacheDTO implements LongCacheIdModel, Serializable { public class DataGroupCacheDTO implements TreeNode<DataGroupCacheDTO>, LongCacheIdModel, Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -28,7 +28,7 @@ public interface DataPermissionService {
void updateDataPermission(DataPermissionUpdateRequest request); void updateDataPermission(DataPermissionUpdateRequest request);
/** /**
* 通过 userId 查询 (不包含角色 不走缓存) * 通过 userId 查询数据权限 (不包含角色 不走缓存)
* *
* @param type type * @param type type
* @param userId userId * @param userId userId
@@ -37,7 +37,7 @@ public interface DataPermissionService {
List<Long> getRelIdListByUserId(String type, Long userId); List<Long> getRelIdListByUserId(String type, Long userId);
/** /**
* 通过 roleId 查询 不走缓存 * 通过 roleId 查询数据权限 不走缓存
* *
* @param type type * @param type type
* @param roleId roleId * @param roleId roleId
@@ -46,13 +46,13 @@ public interface DataPermissionService {
List<Long> getRelIdListByRoleId(String type, Long roleId); List<Long> getRelIdListByRoleId(String type, Long roleId);
/** /**
* 通过 userId 查询 (包含角色 走缓存) * 查询 userId 已授权的数据权限 (包含角色 走缓存)
* *
* @param type type * @param type type
* @param userId userId * @param userId userId
* @return relId * @return relId
*/ */
List<Long> getAllowRelIdList(String type, Long userId); List<Long> getUserAuthorizedRelIdList(String type, Long userId);
/** /**
* 通过 relId 删除 * 通过 relId 删除

View File

@@ -7,6 +7,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.Const;
import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.constant.ErrorMessage;
import com.orion.ops.framework.common.enums.MovePosition; import com.orion.ops.framework.common.enums.MovePosition;
import com.orion.ops.framework.common.utils.TreeUtils;
import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.common.utils.Valid;
import com.orion.ops.framework.redis.core.utils.RedisStrings; import com.orion.ops.framework.redis.core.utils.RedisStrings;
import com.orion.ops.framework.redis.core.utils.barrier.CacheBarriers; import com.orion.ops.framework.redis.core.utils.barrier.CacheBarriers;
@@ -25,7 +26,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -185,7 +185,7 @@ public class DataGroupServiceImpl implements DataGroupService {
.id(Const.ROOT_PARENT_ID) .id(Const.ROOT_PARENT_ID)
.sort(Const.DEFAULT_SORT) .sort(Const.DEFAULT_SORT)
.build(); .build();
this.buildGroupTree(rootNode, rows); TreeUtils.buildGroupTree(rootNode, rows);
treeData = rootNode.getChildren(); treeData = rootNode.getChildren();
} }
// 设置缓存 // 设置缓存
@@ -196,29 +196,6 @@ public class DataGroupServiceImpl implements DataGroupService {
return treeData; return treeData;
} }
/**
* 构建树
*
* @param parentNode parentNode
* @param nodes nodes
*/
private void buildGroupTree(DataGroupCacheDTO parentNode,
List<DataGroupCacheDTO> nodes) {
// 获取子节点
List<DataGroupCacheDTO> childrenNodes = nodes.stream()
.filter(s -> parentNode.getId().equals(s.getParentId()))
.sorted(Comparator.comparing(DataGroupCacheDTO::getSort))
.collect(Collectors.toList());
if (childrenNodes.isEmpty()) {
return;
}
parentNode.setChildren(childrenNodes);
// 遍历子节点
for (DataGroupCacheDTO childrenNode : childrenNodes) {
this.buildGroupTree(childrenNode, nodes);
}
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Integer deleteDataGroupById(Long id) { public Integer deleteDataGroupById(Long id) {

View File

@@ -130,7 +130,7 @@ public class DataPermissionServiceImpl implements DataPermissionService {
} }
@Override @Override
public List<Long> getAllowRelIdList(String type, Long userId) { public List<Long> getUserAuthorizedRelIdList(String type, Long userId) {
String cacheKey = DataPermissionCacheKeyDefine.DATA_PERMISSION_USER.format(type, userId); String cacheKey = DataPermissionCacheKeyDefine.DATA_PERMISSION_USER.format(type, userId);
// 获取缓存 // 获取缓存
List<Long> list = RedisLists.range(cacheKey, Long::valueOf); List<Long> list = RedisLists.range(cacheKey, Long::valueOf);

View File

@@ -22,7 +22,6 @@ import com.orion.ops.module.infra.dao.SystemUserRoleDAO;
import com.orion.ops.module.infra.define.RoleDefine; import com.orion.ops.module.infra.define.RoleDefine;
import com.orion.ops.module.infra.define.cache.TipsCacheKeyDefine; import com.orion.ops.module.infra.define.cache.TipsCacheKeyDefine;
import com.orion.ops.module.infra.define.cache.UserCacheKeyDefine; 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.domain.SystemUserDO;
import com.orion.ops.module.infra.entity.dto.UserInfoDTO; import com.orion.ops.module.infra.entity.dto.UserInfoDTO;
import com.orion.ops.module.infra.entity.request.user.*; import com.orion.ops.module.infra.entity.request.user.*;
@@ -275,16 +274,7 @@ public class SystemUserServiceImpl implements SystemUserService {
@Override @Override
public boolean isAdminUser(Long userId) { public boolean isAdminUser(Long userId) {
// 查询用户角色 return systemRoleDAO.getRoleIdByUserIdAndRoleCode(userId, RoleDefine.ADMIN_CODE) != null;
List<Long> roleIdList = systemUserRoleDAO.selectRoleIdByUserId(userId);
if (!roleIdList.isEmpty()) {
// 查询角色信息
return systemRoleDAO.selectBatchIds(roleIdList)
.stream()
.map(SystemRoleDO::getCode)
.anyMatch(RoleDefine::isAdmin);
}
return false;
} }
/** /**

View File

@@ -20,4 +20,12 @@
id, name, code, status, create_time, update_time, creator, updater, deleted id, name, code, status, create_time, update_time, creator, updater, deleted
</sql> </sql>
<select id="getRoleIdByUserIdAndRoleCode" resultType="java.lang.Long">
SELECT role_id
FROM system_user_role
WHERE user_id = 1
AND deleted = 0
AND role_id IN (SELECT id FROM system_role WHERE CODE = 'admin' AND deleted = 0) LIMIT 1
</select>
</mapper> </mapper>

View File

@@ -43,50 +43,50 @@ export interface HostGroupRelUpdateRequest {
} }
/** /**
* 创建主机分组 - 管理 * 创建主机分组
*/ */
export function createHostGroup(request: HostGroupCreateRequest) { export function createHostGroup(request: HostGroupCreateRequest) {
return axios.post<number>('/asset/host-group/create', request); return axios.post<number>('/asset/host-group/create', request);
} }
/** /**
* 更新主机分组名称 - 管理 * 更新主机分组名称
*/ */
export function updateHostGroupName(request: HostGroupRenameRequest) { export function updateHostGroupName(request: HostGroupRenameRequest) {
return axios.put('/asset/host-group/rename', request); return axios.put('/asset/host-group/rename', request);
} }
/** /**
* 移动主机分组 - 管理 * 移动主机分组
*/ */
export function moveHostGroup(request: HostGroupMoveRequest) { export function moveHostGroup(request: HostGroupMoveRequest) {
return axios.put('/asset/host-group/move', request); return axios.put('/asset/host-group/move', request);
} }
/** /**
* 查询主机分组树 - 管理 * 查询主机分组树
*/ */
export function getHostGroupTree() { export function getHostGroupTree() {
return axios.get<Array<HostGroupQueryResponse>>('/asset/host-group/tree'); return axios.get<Array<HostGroupQueryResponse>>('/asset/host-group/tree');
} }
/** /**
* 删除主机分组 - 管理 * 删除主机分组
*/ */
export function deleteHostGroup(id: number) { export function deleteHostGroup(id: number) {
return axios.delete('/asset/host-group/delete', { params: { id } }); return axios.delete('/asset/host-group/delete', { params: { id } });
} }
/** /**
* 查询分组内主机 - 管理 * 查询分组内主机
*/ */
export function getHostGroupRelList(groupId: number) { export function getHostGroupRelList(groupId: number) {
return axios.get<Array<number>>('/asset/host-group/rel-list', { params: { groupId } }); return axios.get<Array<number>>('/asset/host-group/rel-list', { params: { groupId } });
} }
/** /**
* 修改分组内主机 - 管理 * 修改分组内主机
*/ */
export function updateHostGroupRel(request: HostGroupRelUpdateRequest) { export function updateHostGroupRel(request: HostGroupRelUpdateRequest) {
return axios.post('/asset/host-group/update-rel', request); return axios.put('/asset/host-group/update-rel', request);
} }