mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-08-25 09:02:29 +02:00
198 lines
5.1 KiB
Go
198 lines
5.1 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/j3ssie/osmedeus/v5/internal/parser"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
// SystemStats contains aggregated system statistics
|
|
type SystemStats struct {
|
|
Workflows WorkflowStats `json:"workflows"`
|
|
Runs RunStats `json:"runs"`
|
|
Workspaces WorkspaceStats `json:"workspaces"`
|
|
Assets AssetStats `json:"assets"`
|
|
Vulnerabilities VulnerabilityStats `json:"vulnerabilities"`
|
|
Schedules ScheduleStats `json:"schedules"`
|
|
}
|
|
|
|
// WorkflowStats contains workflow counts
|
|
type WorkflowStats struct {
|
|
Total int `json:"total"`
|
|
Flows int `json:"flows"`
|
|
Modules int `json:"modules"`
|
|
}
|
|
|
|
// RunStats contains run counts by status
|
|
type RunStats struct {
|
|
Total int `json:"total"`
|
|
Completed int `json:"completed"`
|
|
Running int `json:"running"`
|
|
Failed int `json:"failed"`
|
|
Pending int `json:"pending"`
|
|
}
|
|
|
|
// WorkspaceStats contains workspace counts
|
|
type WorkspaceStats struct {
|
|
Total int `json:"total"`
|
|
}
|
|
|
|
// AssetStats contains asset counts
|
|
type AssetStats struct {
|
|
Total int `json:"total"`
|
|
}
|
|
|
|
// VulnerabilityStats contains vulnerability counts by severity
|
|
type VulnerabilityStats struct {
|
|
Total int `json:"total"`
|
|
Critical int `json:"critical"`
|
|
High int `json:"high"`
|
|
Medium int `json:"medium"`
|
|
Low int `json:"low"`
|
|
}
|
|
|
|
// ScheduleStats contains schedule counts
|
|
type ScheduleStats struct {
|
|
Total int `json:"total"`
|
|
Enabled int `json:"enabled"`
|
|
}
|
|
|
|
// GetSystemStats retrieves aggregated system statistics from the database and workflows
|
|
func GetSystemStats(ctx context.Context, workflowsPath string) (*SystemStats, error) {
|
|
db := GetDB()
|
|
stats := &SystemStats{}
|
|
|
|
// Get workflow stats from loader
|
|
if workflowsPath != "" {
|
|
loader := parser.NewLoader(workflowsPath)
|
|
flows, modules, err := loader.ListAllWorkflows()
|
|
if err == nil {
|
|
stats.Workflows = WorkflowStats{
|
|
Total: len(flows) + len(modules),
|
|
Flows: len(flows),
|
|
Modules: len(modules),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get run stats
|
|
runStats, err := getRunStats(ctx, db)
|
|
if err == nil {
|
|
stats.Runs = runStats
|
|
}
|
|
|
|
// Get workspace stats
|
|
workspaceCount, err := db.NewSelect().Model((*Workspace)(nil)).Count(ctx)
|
|
if err == nil {
|
|
stats.Workspaces = WorkspaceStats{Total: workspaceCount}
|
|
}
|
|
|
|
// Get asset stats
|
|
assetCount, err := db.NewSelect().Model((*Asset)(nil)).Count(ctx)
|
|
if err == nil {
|
|
stats.Assets = AssetStats{Total: assetCount}
|
|
}
|
|
|
|
// Get vulnerability stats (aggregated from workspaces)
|
|
vulnStats, err := getVulnerabilityStats(ctx, db)
|
|
if err == nil {
|
|
stats.Vulnerabilities = vulnStats
|
|
}
|
|
|
|
// Get schedule stats
|
|
scheduleStats, err := getScheduleStats(ctx, db)
|
|
if err == nil {
|
|
stats.Schedules = scheduleStats
|
|
}
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
// getRunStats retrieves run counts grouped by status in a single query
|
|
func getRunStats(ctx context.Context, db *bun.DB) (RunStats, error) {
|
|
var result struct {
|
|
Total int `bun:"total"`
|
|
Completed int `bun:"completed"`
|
|
Running int `bun:"running"`
|
|
Failed int `bun:"failed"`
|
|
Pending int `bun:"pending"`
|
|
}
|
|
|
|
err := db.NewSelect().
|
|
Model((*Run)(nil)).
|
|
ColumnExpr("COUNT(*) AS total").
|
|
ColumnExpr("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed").
|
|
ColumnExpr("SUM(CASE WHEN status = 'running' THEN 1 ELSE 0 END) AS running").
|
|
ColumnExpr("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed").
|
|
ColumnExpr("SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending").
|
|
Scan(ctx, &result)
|
|
|
|
if err != nil {
|
|
return RunStats{}, err
|
|
}
|
|
|
|
return RunStats{
|
|
Total: result.Total,
|
|
Completed: result.Completed,
|
|
Running: result.Running,
|
|
Failed: result.Failed,
|
|
Pending: result.Pending,
|
|
}, nil
|
|
}
|
|
|
|
// getVulnerabilityStats retrieves aggregated vulnerability counts from workspaces
|
|
func getVulnerabilityStats(ctx context.Context, db *bun.DB) (VulnerabilityStats, error) {
|
|
stats := VulnerabilityStats{}
|
|
|
|
var result struct {
|
|
Critical int `bun:"critical"`
|
|
High int `bun:"high"`
|
|
Medium int `bun:"medium"`
|
|
Low int `bun:"low"`
|
|
}
|
|
|
|
err := db.NewSelect().
|
|
Model((*Workspace)(nil)).
|
|
ColumnExpr("COALESCE(SUM(vuln_critical), 0) AS critical").
|
|
ColumnExpr("COALESCE(SUM(vuln_high), 0) AS high").
|
|
ColumnExpr("COALESCE(SUM(vuln_medium), 0) AS medium").
|
|
ColumnExpr("COALESCE(SUM(vuln_low), 0) AS low").
|
|
Scan(ctx, &result)
|
|
|
|
if err != nil {
|
|
return stats, err
|
|
}
|
|
|
|
stats.Critical = result.Critical
|
|
stats.High = result.High
|
|
stats.Medium = result.Medium
|
|
stats.Low = result.Low
|
|
stats.Total = result.Critical + result.High + result.Medium + result.Low
|
|
|
|
return stats, nil
|
|
}
|
|
|
|
// getScheduleStats retrieves schedule counts in a single query
|
|
func getScheduleStats(ctx context.Context, db *bun.DB) (ScheduleStats, error) {
|
|
var result struct {
|
|
Total int `bun:"total"`
|
|
Enabled int `bun:"enabled"`
|
|
}
|
|
|
|
err := db.NewSelect().
|
|
Model((*Schedule)(nil)).
|
|
ColumnExpr("COUNT(*) AS total").
|
|
ColumnExpr("SUM(CASE WHEN is_enabled = true THEN 1 ELSE 0 END) AS enabled").
|
|
Scan(ctx, &result)
|
|
|
|
if err != nil {
|
|
return ScheduleStats{}, err
|
|
}
|
|
|
|
return ScheduleStats{
|
|
Total: result.Total,
|
|
Enabled: result.Enabled,
|
|
}, nil
|
|
}
|