@@ -2,6 +2,7 @@ package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -40,7 +41,7 @@ func (s *Store) DashboardOverview(limit int) (map[string]any, error) {
|
||||
}
|
||||
|
||||
func (s *Store) RecentSourceChecks(limit int) ([]map[string]any, error) {
|
||||
rows, err := s.query(`SELECT h.id, e.source_id, e.name, h.status, h.latency_ms, h.error, h.checked_at
|
||||
rows, err := s.query(`SELECT h.id, h.source_db_id, COALESCE(e.source_id, ''), COALESCE(e.name, ''), h.status, h.latency_ms, h.error, h.checked_at
|
||||
FROM endpoint_health_checks h LEFT JOIN source_endpoints e ON e.id = h.source_db_id
|
||||
ORDER BY h.checked_at DESC, h.id DESC LIMIT ?`, limit)
|
||||
if err != nil {
|
||||
@@ -49,13 +50,19 @@ func (s *Store) RecentSourceChecks(limit int) ([]map[string]any, error) {
|
||||
defer rows.Close()
|
||||
items := []map[string]any{}
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
var id, sourceDBID int64
|
||||
var sourceID, name, status, message, checkedAt string
|
||||
var latency int
|
||||
if err := rows.Scan(&id, &sourceID, &name, &status, &latency, &message, &checkedAt); err != nil {
|
||||
if err := rows.Scan(&id, &sourceDBID, &sourceID, &name, &status, &latency, &message, &checkedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, map[string]any{"id": id, "sourceId": sourceID, "name": name, "status": status, "latencyMs": latency, "error": message, "checkedAt": checkedAt})
|
||||
if sourceID == "" {
|
||||
sourceID = fmt.Sprintf("deleted-%d", sourceDBID)
|
||||
}
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("已删除接口 #%d", sourceDBID)
|
||||
}
|
||||
items = append(items, map[string]any{"id": id, "sourceDbId": sourceDBID, "sourceId": sourceID, "name": name, "status": status, "latencyMs": latency, "error": message, "checkedAt": checkedAt})
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
@@ -100,6 +107,59 @@ func (s *Store) ListAuditLogs(limit int) ([]AuditLog, error) {
|
||||
return scanAuditRows(rows)
|
||||
}
|
||||
|
||||
func (s *Store) ListAuditLogsPage(filters AuditFilters) (AuditPage, error) {
|
||||
page := filters.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
perPage := filters.PerPage
|
||||
if perPage <= 0 {
|
||||
perPage = 35
|
||||
}
|
||||
if perPage > 100 {
|
||||
perPage = 100
|
||||
}
|
||||
where, args := auditWhere(filters)
|
||||
var total int
|
||||
if err := s.queryRow(`SELECT COUNT(*) FROM audit_logs`+where, args...).Scan(&total); err != nil {
|
||||
return AuditPage{}, err
|
||||
}
|
||||
offset := (page - 1) * perPage
|
||||
queryArgs := append(append([]any{}, args...), perPage, offset)
|
||||
rows, err := s.query(`SELECT id, actor, type, target, message, ip, user_agent, created_at FROM audit_logs`+where+` ORDER BY id DESC LIMIT ? OFFSET ?`, queryArgs...)
|
||||
if err != nil {
|
||||
return AuditPage{}, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items, err := scanAuditRows(rows)
|
||||
if err != nil {
|
||||
return AuditPage{}, err
|
||||
}
|
||||
return AuditPage{Items: items, Total: total, Page: page, PerPage: perPage}, nil
|
||||
}
|
||||
|
||||
func auditWhere(filters AuditFilters) (string, []any) {
|
||||
clauses := []string{}
|
||||
args := []any{}
|
||||
if value := strings.TrimSpace(filters.Type); value != "" {
|
||||
clauses = append(clauses, "type = ?")
|
||||
args = append(args, sanitize(value))
|
||||
}
|
||||
if value := strings.TrimSpace(filters.Target); value != "" {
|
||||
clauses = append(clauses, "target = ?")
|
||||
args = append(args, sanitize(value))
|
||||
}
|
||||
if value := strings.TrimSpace(filters.Query); value != "" {
|
||||
clauses = append(clauses, "(actor LIKE ? OR type LIKE ? OR target LIKE ? OR message LIKE ? OR ip LIKE ?)")
|
||||
like := "%" + sanitize(value) + "%"
|
||||
args = append(args, like, like, like, like, like)
|
||||
}
|
||||
if len(clauses) == 0 {
|
||||
return "", args
|
||||
}
|
||||
return " WHERE " + strings.Join(clauses, " AND "), args
|
||||
}
|
||||
|
||||
func (s *Store) ListAuditLogsForTarget(target string, limit int) ([]AuditLog, error) {
|
||||
if limit <= 0 || limit > 200 {
|
||||
limit = 100
|
||||
|
||||
Reference in New Issue
Block a user