Files
dip-ids/internal/api/handlers/stats.go
T
2026-04-12 22:26:26 +04:00

90 lines
1.9 KiB
Go

package handlers
import (
"net/http"
"strconv"
"dip-ids/internal/storage"
"github.com/gin-gonic/gin"
)
type StatsHandler struct {
db *storage.DB
}
func NewStatsHandler(db *storage.DB) *StatsHandler {
return &StatsHandler{db: db}
}
// GetSummary GET /api/stats/summary
func (h *StatsHandler) GetSummary(c *gin.Context) {
total, err := h.db.TotalAlerts()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
bySeverity, err := h.db.AlertsBySeverity()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
byType, err := h.db.AlertsByType()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Нормализуем данные по severity в удобный map
severityMap := map[string]int64{
"critical": 0, "high": 0, "medium": 0, "low": 0,
}
for _, s := range bySeverity {
severityMap[s.Severity] = s.Count
}
c.JSON(http.StatusOK, gin.H{
"total": total,
"by_severity": severityMap,
"by_type": byType,
})
}
// GetTimeline GET /api/stats/timeline?hours=24
func (h *StatsHandler) GetTimeline(c *gin.Context) {
hours := 24
if h := c.Query("hours"); h != "" {
if v, err := strconv.Atoi(h); err == nil && v > 0 {
hours = v
}
}
timeline, err := h.db.AlertsTimeline(hours)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": timeline, "hours": hours})
}
// GetTopIPs GET /api/stats/top-ips?limit=10
func (h *StatsHandler) GetTopIPs(c *gin.Context) {
limit := 10
if l := c.Query("limit"); l != "" {
if v, err := strconv.Atoi(l); err == nil && v > 0 {
limit = v
}
}
ips, err := h.db.TopSourceIPs(limit)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"data": ips})
}