mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-07-14 07:57:26 +02:00
Add files via upload
This commit is contained in:
+112
-9
@@ -120,9 +120,22 @@ func (h *MonitorHandler) Monitor(c *gin.Context) {
|
||||
// 解析工具筛选参数(兼容 mcp__tool 与内部 mcp::tool)
|
||||
toolName := normalizeToolNameFilter(c.Query("tool"))
|
||||
|
||||
executions, total := h.loadExecutionListWithPagination(page, pageSize, status, toolName)
|
||||
access := notificationAccessFromContext(c)
|
||||
executions, total := h.loadExecutionListWithPagination(page, pageSize, status, toolName, access)
|
||||
h.enrichExecutionsConversationID(executions)
|
||||
summary, topTools := h.loadStatsSummary(monitorPageTopTools)
|
||||
var summary *MonitorStatsSummary
|
||||
var topTools []*mcp.ToolStats
|
||||
if access.Scope == database.RBACScopeAll {
|
||||
summary, topTools = h.loadStatsSummary(monitorPageTopTools)
|
||||
} else if h.db != nil {
|
||||
if scoped, err := h.db.LoadToolStatsSummaryForAccess(monitorPageTopTools, access); err == nil {
|
||||
summary, topTools = dbStatsSummaryToMonitor(scoped), scoped.TopTools
|
||||
} else {
|
||||
summary, topTools = summarizeAccessibleExecutionPage(executions, monitorPageTopTools)
|
||||
}
|
||||
} else {
|
||||
summary, topTools = summarizeAccessibleExecutionPage(executions, monitorPageTopTools)
|
||||
}
|
||||
|
||||
totalPages := (total + pageSize - 1) / pageSize
|
||||
if totalPages == 0 {
|
||||
@@ -142,6 +155,31 @@ func (h *MonitorHandler) Monitor(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func summarizeAccessibleExecutionPage(executions []*mcp.ToolExecution, topN int) (*MonitorStatsSummary, []*mcp.ToolStats) {
|
||||
stats := map[string]*mcp.ToolStats{}
|
||||
for _, exec := range executions {
|
||||
if exec == nil {
|
||||
continue
|
||||
}
|
||||
stat := stats[exec.ToolName]
|
||||
if stat == nil {
|
||||
stat = &mcp.ToolStats{ToolName: exec.ToolName}
|
||||
stats[exec.ToolName] = stat
|
||||
}
|
||||
stat.TotalCalls++
|
||||
if exec.Status == "failed" || exec.Status == "cancelled" {
|
||||
stat.FailedCalls++
|
||||
} else if exec.Status == "completed" {
|
||||
stat.SuccessCalls++
|
||||
}
|
||||
started := exec.StartTime
|
||||
if stat.LastCallTime == nil || started.After(*stat.LastCallTime) {
|
||||
stat.LastCallTime = &started
|
||||
}
|
||||
}
|
||||
return summarizeToolStats(stats, topN)
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) monitorRetentionDays() int {
|
||||
if h.monitorRetention != nil {
|
||||
return h.monitorRetention.RetentionDays()
|
||||
@@ -154,9 +192,9 @@ func (h *MonitorHandler) loadExecutions() []*mcp.ToolExecution {
|
||||
return executions
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) loadExecutionListWithPagination(page, pageSize int, status, toolName string) ([]*mcp.ToolExecution, int) {
|
||||
func (h *MonitorHandler) loadExecutionListWithPagination(page, pageSize int, status, toolName string, access database.RBACListAccess) ([]*mcp.ToolExecution, int) {
|
||||
if h.db == nil {
|
||||
allExecutions := h.mcpServer.GetAllExecutions()
|
||||
allExecutions := filterToolExecutionsForAccess(h.mcpServer.GetAllExecutions(), access, h.db)
|
||||
if status != "" || toolName != "" {
|
||||
filtered := make([]*mcp.ToolExecution, 0)
|
||||
for _, exec := range allExecutions {
|
||||
@@ -189,13 +227,13 @@ func (h *MonitorHandler) loadExecutionListWithPagination(page, pageSize int, sta
|
||||
}
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
executions, err := h.db.LoadToolExecutionListPage(offset, pageSize, status, toolName)
|
||||
executions, err := h.db.LoadToolExecutionListPageForAccess(offset, pageSize, status, toolName, access)
|
||||
if err != nil {
|
||||
h.logger.Warn("从数据库加载执行记录列表失败,回退到内存数据", zap.Error(err))
|
||||
return h.loadExecutionListWithPaginationFromMemory(page, pageSize, status, toolName)
|
||||
return h.loadExecutionListWithPaginationFromMemory(page, pageSize, status, toolName, access)
|
||||
}
|
||||
|
||||
total, err := h.db.CountToolExecutions(status, toolName)
|
||||
total, err := h.db.CountToolExecutionsForAccess(status, toolName, access)
|
||||
if err != nil {
|
||||
h.logger.Warn("获取执行记录总数失败", zap.Error(err))
|
||||
total = offset + len(executions)
|
||||
@@ -207,8 +245,8 @@ func (h *MonitorHandler) loadExecutionListWithPagination(page, pageSize int, sta
|
||||
return executions, total
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) loadExecutionListWithPaginationFromMemory(page, pageSize int, status, toolName string) ([]*mcp.ToolExecution, int) {
|
||||
allExecutions := h.mcpServer.GetAllExecutions()
|
||||
func (h *MonitorHandler) loadExecutionListWithPaginationFromMemory(page, pageSize int, status, toolName string, access database.RBACListAccess) ([]*mcp.ToolExecution, int) {
|
||||
allExecutions := filterToolExecutionsForAccess(h.mcpServer.GetAllExecutions(), access, h.db)
|
||||
if status != "" || toolName != "" {
|
||||
filtered := make([]*mcp.ToolExecution, 0)
|
||||
for _, exec := range allExecutions {
|
||||
@@ -260,6 +298,50 @@ func slimToolExecution(exec *mcp.ToolExecution) *mcp.ToolExecution {
|
||||
return slim
|
||||
}
|
||||
|
||||
func filterToolExecutionsForAccess(executions []*mcp.ToolExecution, access database.RBACListAccess, db *database.DB) []*mcp.ToolExecution {
|
||||
if access.Scope == database.RBACScopeAll {
|
||||
return executions
|
||||
}
|
||||
out := make([]*mcp.ToolExecution, 0, len(executions))
|
||||
for _, exec := range executions {
|
||||
if toolExecutionVisible(exec, access, db) {
|
||||
out = append(out, exec)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func toolExecutionVisible(exec *mcp.ToolExecution, access database.RBACListAccess, db *database.DB) bool {
|
||||
if exec == nil || strings.TrimSpace(access.UserID) == "" {
|
||||
return false
|
||||
}
|
||||
if access.Scope == database.RBACScopeAll || strings.TrimSpace(exec.OwnerUserID) == strings.TrimSpace(access.UserID) {
|
||||
return true
|
||||
}
|
||||
conversationID := strings.TrimSpace(exec.ConversationID)
|
||||
return conversationID != "" && db != nil && db.UserCanAccessResource(access.UserID, access.Scope, "conversation", conversationID)
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) monitorExecutionAllowed(c *gin.Context, id string) bool {
|
||||
access := notificationAccessFromContext(c)
|
||||
if access.Scope == database.RBACScopeAll {
|
||||
return true
|
||||
}
|
||||
id = strings.TrimSpace(id)
|
||||
if id == "" {
|
||||
return false
|
||||
}
|
||||
if exec, ok := h.mcpServer.GetExecution(id); ok {
|
||||
return toolExecutionVisible(exec, access, h.db)
|
||||
}
|
||||
if h.externalMCPMgr != nil {
|
||||
if exec, ok := h.externalMCPMgr.GetExecution(id); ok {
|
||||
return toolExecutionVisible(exec, access, h.db)
|
||||
}
|
||||
}
|
||||
return h.db != nil && h.db.UserCanAccessToolExecution(access.UserID, access.Scope, id)
|
||||
}
|
||||
|
||||
func (h *MonitorHandler) loadExecutionsWithPagination(page, pageSize int, status, toolName string) ([]*mcp.ToolExecution, int) {
|
||||
if h.db == nil {
|
||||
allExecutions := h.mcpServer.GetAllExecutions()
|
||||
@@ -453,6 +535,10 @@ func (h *MonitorHandler) loadStatsMap() map[string]*mcp.ToolStats {
|
||||
// GetExecution 获取特定执行记录
|
||||
func (h *MonitorHandler) GetExecution(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if !h.monitorExecutionAllowed(c, id) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "无权访问该资源"})
|
||||
return
|
||||
}
|
||||
|
||||
// 先从内部MCP服务器查找
|
||||
exec, exists := h.mcpServer.GetExecution(id)
|
||||
@@ -493,6 +579,10 @@ func (h *MonitorHandler) CancelExecution(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "执行记录ID不能为空"})
|
||||
return
|
||||
}
|
||||
if !h.monitorExecutionAllowed(c, id) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "无权访问该资源"})
|
||||
return
|
||||
}
|
||||
note := ""
|
||||
dec := json.NewDecoder(c.Request.Body)
|
||||
var body struct {
|
||||
@@ -592,6 +682,9 @@ func (h *MonitorHandler) BatchGetToolNames(c *gin.Context) {
|
||||
|
||||
result := make(map[string]executionSummary, len(req.IDs))
|
||||
for _, id := range req.IDs {
|
||||
if !h.monitorExecutionAllowed(c, id) {
|
||||
continue
|
||||
}
|
||||
// 先从内部MCP服务器查找
|
||||
if exec, exists := h.mcpServer.GetExecution(id); exists {
|
||||
result[id] = executionSummary{ToolName: exec.ToolName, Status: exec.Status}
|
||||
@@ -755,6 +848,10 @@ func (h *MonitorHandler) DeleteExecution(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "执行记录ID不能为空"})
|
||||
return
|
||||
}
|
||||
if !h.monitorExecutionAllowed(c, id) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "无权访问该资源"})
|
||||
return
|
||||
}
|
||||
|
||||
// 如果使用数据库,先获取执行记录信息,然后删除并更新统计
|
||||
if h.db != nil {
|
||||
@@ -823,6 +920,12 @@ func (h *MonitorHandler) DeleteExecutions(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "执行记录ID列表不能为空"})
|
||||
return
|
||||
}
|
||||
for _, id := range request.IDs {
|
||||
if !h.monitorExecutionAllowed(c, id) {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "无权访问一个或多个执行记录"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 如果使用数据库,先获取执行记录信息,然后删除并更新统计
|
||||
if h.db != nil {
|
||||
|
||||
Reference in New Issue
Block a user