add online monitor and fix admin scopes

This commit is contained in:
baiyanyun
2026-06-02 20:50:42 +08:00
parent f69fb46c59
commit a01fc93594
17 changed files with 998 additions and 7 deletions

View File

@@ -0,0 +1,92 @@
package com.xspaceagi.sandbox.application.dto;
import com.xspaceagi.system.infra.dao.entity.User;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Schema(description = "在线监控聚合信息")
@Data
public class OnlineMonitorDto {
@Schema(description = "客户端总数")
private long totalClientCount;
@Schema(description = "在线客户端数")
private long onlineClientCount;
@Schema(description = "离线客户端数")
private long offlineClientCount;
@Schema(description = "已停用客户端数")
private long inactiveClientCount;
@Schema(description = "用户总数")
private long totalUserCount;
@Schema(description = "启用用户数")
private long enabledUserCount;
@Schema(description = "禁用用户数")
private long disabledUserCount;
@Schema(description = "用户组监控信息")
private List<GroupMonitorDto> groups;
@Schema(description = "用户监控信息")
private List<UserMonitorDto> users;
@Schema(description = "客户端监控信息")
private List<ClientMonitorDto> clients;
@Schema(description = "用户组监控信息")
@Data
public static class GroupMonitorDto {
private Long groupId;
private String groupName;
private Integer authEnabled;
private Integer status;
private Date expireTime;
private Integer maxUserCount;
private long currentUserCount;
private Integer maxClientCount;
private long currentClientCount;
private long onlineClientCount;
private long offlineClientCount;
private long inactiveClientCount;
}
@Schema(description = "用户监控信息")
@Data
public static class UserMonitorDto {
private Long userId;
private String userName;
private String nickName;
private User.Role role;
private User.Status status;
private List<String> groupNames;
private long clientCount;
private long onlineClientCount;
private long inactiveClientCount;
private Date lastLoginTime;
}
@Schema(description = "客户端监控信息")
@Data
public static class ClientMonitorDto {
private Long id;
private String name;
private Long userId;
private String userName;
private String nickName;
private Long groupId;
private String groupName;
private Boolean isActive;
private boolean online;
private Integer maxAgentCount;
private Date created;
private Date modified;
}
}

View File

@@ -1,18 +1,23 @@
package com.xspaceagi.sandbox.ui.web.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xspaceagi.sandbox.application.dto.OnlineMonitorDto;
import com.xspaceagi.sandbox.application.dto.SandboxConfigDto;
import com.xspaceagi.sandbox.application.dto.SandboxConfigQueryDto;
import com.xspaceagi.sandbox.application.dto.SandboxGlobalConfigDto;
import com.xspaceagi.sandbox.application.service.SandboxConfigApplicationService;
import com.xspaceagi.system.application.dto.UserDto;
import com.xspaceagi.system.application.service.SysGroupApplicationService;
import com.xspaceagi.system.application.service.SysRoleApplicationService;
import com.xspaceagi.system.infra.dao.entity.SysGroup;
import com.xspaceagi.system.infra.dao.entity.User;
import com.xspaceagi.system.infra.dao.service.UserService;
import com.xspaceagi.system.spec.annotation.RequireResource;
import com.xspaceagi.system.spec.common.RequestContext;
import com.xspaceagi.system.spec.dto.ReqResult;
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
import com.xspaceagi.system.spec.enums.GroupEnum;
import com.xspaceagi.system.spec.enums.RoleEnum;
import com.xspaceagi.system.spec.exception.BizException;
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
import io.swagger.v3.oas.annotations.Operation;
@@ -21,7 +26,12 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -41,6 +51,12 @@ public class SandboxConfigManageController {
@Resource
private SysGroupApplicationService sysGroupApplicationService;
@Resource
private SysRoleApplicationService sysRoleApplicationService;
@Resource
private UserService userService;
@RequireResource(SANDBOX_CONFIG_QUERY)
@Operation(summary = "分页查询配置列表")
@PostMapping("/page")
@@ -148,6 +164,154 @@ public class SandboxConfigManageController {
return ReqResult.success(globalConfig);
}
@RequireResource(ONLINE_MONITOR_QUERY)
@Operation(summary = "查询在线监控信息")
@GetMapping("/online-monitor")
public ReqResult<OnlineMonitorDto> onlineMonitor() {
boolean platformAdmin = isPlatformAdmin();
List<SysGroup> groups = visibleGroups();
Set<Long> groupIds = groups.stream().map(SysGroup::getId).collect(Collectors.toSet());
List<User> users = visibleUsers(platformAdmin, groupIds);
Set<Long> userIds = users.stream().map(User::getId).collect(Collectors.toSet());
SandboxConfigQueryDto queryDto = new SandboxConfigQueryDto();
queryDto.setPageNum(1);
queryDto.setPageSize(100000);
if (!platformAdmin && !groupIds.isEmpty()) {
queryDto.setGroupIds(new ArrayList<>(groupIds));
} else if (!platformAdmin) {
queryDto.setGroupIds(List.of(-1L));
}
List<SandboxConfigDto> configs = sandboxConfigApplicationService.pageQuery(queryDto).getRecords().stream()
.filter(config -> config.getUserId() != null)
.filter(config -> platformAdmin || userIds.contains(config.getUserId()))
.toList();
return ReqResult.success(buildOnlineMonitor(groups, users, configs));
}
private OnlineMonitorDto buildOnlineMonitor(List<SysGroup> groups, List<User> users, List<SandboxConfigDto> configs) {
Map<Long, SysGroup> groupMap = groups.stream()
.filter(group -> group.getId() != null)
.collect(Collectors.toMap(SysGroup::getId, group -> group, (a, b) -> a));
Map<Long, User> userMap = users.stream()
.filter(user -> user.getId() != null)
.collect(Collectors.toMap(User::getId, user -> user, (a, b) -> a));
Map<Long, List<SysGroup>> userGroupMap = new HashMap<>();
groups.forEach(group -> sysGroupApplicationService.getUserListByGroupId(group.getId())
.forEach(user -> userGroupMap.computeIfAbsent(user.getId(), key -> new ArrayList<>()).add(group)));
OnlineMonitorDto dto = new OnlineMonitorDto();
dto.setTotalClientCount(configs.size());
dto.setOnlineClientCount(configs.stream().filter(config -> Boolean.TRUE.equals(config.getIsActive()) && config.isOnline()).count());
dto.setInactiveClientCount(configs.stream().filter(config -> !Boolean.TRUE.equals(config.getIsActive())).count());
dto.setOfflineClientCount(configs.stream().filter(config -> Boolean.TRUE.equals(config.getIsActive()) && !config.isOnline()).count());
dto.setTotalUserCount(users.size());
dto.setEnabledUserCount(users.stream().filter(user -> user.getStatus() == User.Status.Enabled).count());
dto.setDisabledUserCount(users.stream().filter(user -> user.getStatus() == User.Status.Disabled).count());
dto.setGroups(groups.stream()
.map(group -> buildGroupMonitor(group, users, configs))
.sorted(Comparator.comparing(OnlineMonitorDto.GroupMonitorDto::getGroupId, Comparator.nullsLast(Long::compareTo)))
.toList());
dto.setUsers(users.stream()
.map(user -> buildUserMonitor(user, userGroupMap, configs))
.sorted(Comparator.comparing(OnlineMonitorDto.UserMonitorDto::getUserId, Comparator.nullsLast(Long::compareTo)))
.toList());
dto.setClients(configs.stream()
.map(config -> buildClientMonitor(config, userMap, groupMap))
.sorted(Comparator.comparing(OnlineMonitorDto.ClientMonitorDto::getId, Comparator.nullsLast(Long::compareTo)))
.toList());
return dto;
}
private OnlineMonitorDto.GroupMonitorDto buildGroupMonitor(SysGroup group, List<User> users, List<SandboxConfigDto> configs) {
Set<Long> groupUserIds = sysGroupApplicationService.getUserListByGroupId(group.getId()).stream()
.map(User::getId)
.collect(Collectors.toSet());
List<SandboxConfigDto> groupConfigs = configs.stream()
.filter(config -> Objects.equals(config.getGroupId(), group.getId()))
.toList();
OnlineMonitorDto.GroupMonitorDto dto = new OnlineMonitorDto.GroupMonitorDto();
dto.setGroupId(group.getId());
dto.setGroupName(group.getName());
dto.setAuthEnabled(group.getAuthEnabled());
dto.setStatus(group.getStatus());
dto.setExpireTime(group.getExpireTime());
dto.setMaxUserCount(group.getMaxUserCount());
dto.setCurrentUserCount(users.stream().filter(user -> groupUserIds.contains(user.getId())).count());
dto.setMaxClientCount(group.getMaxClientCount());
dto.setCurrentClientCount(groupConfigs.size());
dto.setOnlineClientCount(groupConfigs.stream().filter(config -> Boolean.TRUE.equals(config.getIsActive()) && config.isOnline()).count());
dto.setInactiveClientCount(groupConfigs.stream().filter(config -> !Boolean.TRUE.equals(config.getIsActive())).count());
dto.setOfflineClientCount(groupConfigs.stream().filter(config -> Boolean.TRUE.equals(config.getIsActive()) && !config.isOnline()).count());
return dto;
}
private OnlineMonitorDto.UserMonitorDto buildUserMonitor(User user, Map<Long, List<SysGroup>> userGroupMap, List<SandboxConfigDto> configs) {
List<SandboxConfigDto> userConfigs = configs.stream()
.filter(config -> Objects.equals(config.getUserId(), user.getId()))
.toList();
OnlineMonitorDto.UserMonitorDto dto = new OnlineMonitorDto.UserMonitorDto();
dto.setUserId(user.getId());
dto.setUserName(user.getUserName());
dto.setNickName(user.getNickName());
dto.setRole(user.getRole());
dto.setStatus(user.getStatus());
dto.setGroupNames(userGroupMap.getOrDefault(user.getId(), List.of()).stream().map(SysGroup::getName).toList());
dto.setClientCount(userConfigs.size());
dto.setOnlineClientCount(userConfigs.stream().filter(config -> Boolean.TRUE.equals(config.getIsActive()) && config.isOnline()).count());
dto.setInactiveClientCount(userConfigs.stream().filter(config -> !Boolean.TRUE.equals(config.getIsActive())).count());
dto.setLastLoginTime(user.getLastLoginTime());
return dto;
}
private OnlineMonitorDto.ClientMonitorDto buildClientMonitor(SandboxConfigDto config, Map<Long, User> userMap, Map<Long, SysGroup> groupMap) {
User user = userMap.get(config.getUserId());
SysGroup group = groupMap.get(config.getGroupId());
OnlineMonitorDto.ClientMonitorDto dto = new OnlineMonitorDto.ClientMonitorDto();
dto.setId(config.getId());
dto.setName(config.getName());
dto.setUserId(config.getUserId());
dto.setUserName(user == null ? null : user.getUserName());
dto.setNickName(user == null ? null : user.getNickName());
dto.setGroupId(config.getGroupId());
dto.setGroupName(group == null ? null : group.getName());
dto.setIsActive(config.getIsActive());
dto.setOnline(config.isOnline());
dto.setMaxAgentCount(config.getMaxAgentCount());
dto.setCreated(config.getCreated());
dto.setModified(config.getModified());
return dto;
}
private List<SysGroup> visibleGroups() {
if (isPlatformAdmin()) {
return sysGroupApplicationService.getGroupList(new SysGroup()).stream()
.filter(group -> !GroupEnum.DEFAULT_GROUP.getCode().equals(group.getCode()))
.toList();
}
Set<Long> groupIds = currentUserGroupIds();
if (groupIds.isEmpty()) {
return List.of();
}
return sysGroupApplicationService.listGroupsByIds(new ArrayList<>(groupIds));
}
private List<User> visibleUsers(boolean platformAdmin, Set<Long> groupIds) {
if (platformAdmin) {
return userService.list().stream()
.filter(user -> user.getStatus() != User.Status.Deleted)
.toList();
}
return groupIds.stream()
.flatMap(groupId -> sysGroupApplicationService.getUserListByGroupId(groupId).stream())
.filter(user -> user.getStatus() != User.Status.Deleted)
.collect(Collectors.toMap(User::getId, user -> user, (a, b) -> a))
.values().stream().toList();
}
private void applySandboxConfigManageScope(SandboxConfigQueryDto queryDto) {
if (queryDto == null || isPlatformAdmin()) {
return;
@@ -172,13 +336,18 @@ public class SandboxConfigManageController {
}
private Set<Long> currentUserGroupIds() {
return sysGroupApplicationService.getEffectiveGroupListByUserId(getCurrentUserDto().getId()).stream()
return sysGroupApplicationService.getGroupListByUserId(getCurrentUserDto().getId()).stream()
.filter(group -> !GroupEnum.DEFAULT_GROUP.getCode().equals(group.getCode()))
.map(SysGroup::getId)
.collect(Collectors.toSet());
}
private boolean isPlatformAdmin() {
return getCurrentUserDto().getRole() == User.Role.Admin;
UserDto currentUser = getCurrentUserDto();
return currentUser.getRole() == User.Role.Admin
&& (currentUserGroupIds().isEmpty()
|| sysRoleApplicationService.getRoleListByUserId(currentUser.getId()).stream()
.anyMatch(role -> RoleEnum.SUPER_ADMIN.getCode().equals(role.getCode())));
}
private UserDto getCurrentUserDto() {