You've already forked caddy-opnsense-blocker
Simplify the dashboard recent IP view
This commit is contained in:
@@ -475,6 +475,75 @@ func (s *Store) ListIPStates(ctx context.Context, limit int, stateFilter string)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListRecentIPRows(ctx context.Context, since time.Time, limit int) ([]model.RecentIPRow, error) {
|
||||
if limit <= 0 {
|
||||
limit = 200
|
||||
}
|
||||
rows, err := s.db.QueryContext(ctx, `
|
||||
WITH recent AS (
|
||||
SELECT client_ip, COUNT(*) AS event_count, MAX(occurred_at) AS last_seen_at
|
||||
FROM events
|
||||
WHERE occurred_at >= ?
|
||||
GROUP BY client_ip
|
||||
)
|
||||
SELECT s.ip,
|
||||
COALESCE((
|
||||
SELECT e.source_name
|
||||
FROM events e
|
||||
WHERE e.client_ip = s.ip AND e.occurred_at >= ?
|
||||
ORDER BY e.occurred_at DESC, e.id DESC
|
||||
LIMIT 1
|
||||
), s.last_source_name) AS source_name,
|
||||
s.state,
|
||||
recent.event_count,
|
||||
recent.last_seen_at,
|
||||
s.state_reason,
|
||||
s.manual_override
|
||||
FROM recent
|
||||
JOIN ip_state s ON s.ip = recent.client_ip
|
||||
ORDER BY recent.event_count DESC, recent.last_seen_at DESC, s.ip ASC
|
||||
LIMIT ?`,
|
||||
formatTime(since),
|
||||
formatTime(since),
|
||||
limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list recent ip rows: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
items := make([]model.RecentIPRow, 0, limit)
|
||||
for rows.Next() {
|
||||
var item model.RecentIPRow
|
||||
var state string
|
||||
var lastSeenAt string
|
||||
var manualOverride string
|
||||
if err := rows.Scan(
|
||||
&item.IP,
|
||||
&item.SourceName,
|
||||
&state,
|
||||
&item.Events,
|
||||
&lastSeenAt,
|
||||
&item.Reason,
|
||||
&manualOverride,
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("scan recent ip row: %w", err)
|
||||
}
|
||||
parsedLastSeenAt, err := parseTime(lastSeenAt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse recent ip row last_seen_at: %w", err)
|
||||
}
|
||||
item.State = model.IPStateStatus(state)
|
||||
item.LastSeenAt = parsedLastSeenAt
|
||||
item.ManualOverride = model.ManualOverride(manualOverride)
|
||||
items = append(items, item)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("iterate recent ip rows: %w", err)
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetIPDetails(ctx context.Context, ip string, eventLimit, decisionLimit, actionLimit int) (model.IPDetails, error) {
|
||||
state, _, err := s.GetIPState(ctx, ip)
|
||||
if err != nil {
|
||||
|
||||
@@ -106,6 +106,16 @@ func TestStoreRecordsEventsAndState(t *testing.T) {
|
||||
if overview.TotalEvents != 1 || overview.TotalIPs != 1 {
|
||||
t.Fatalf("unexpected overview counters: %+v", overview)
|
||||
}
|
||||
recentIPs, err := db.ListRecentIPRows(ctx, occurredAt.Add(-time.Hour), 10)
|
||||
if err != nil {
|
||||
t.Fatalf("list recent ip rows: %v", err)
|
||||
}
|
||||
if len(recentIPs) != 1 {
|
||||
t.Fatalf("unexpected recent ip rows count: %d", len(recentIPs))
|
||||
}
|
||||
if recentIPs[0].IP != event.ClientIP || recentIPs[0].SourceName != event.SourceName || recentIPs[0].Events != 1 {
|
||||
t.Fatalf("unexpected recent ip row: %+v", recentIPs[0])
|
||||
}
|
||||
details, err := db.GetIPDetails(ctx, event.ClientIP, 10, 10, 10)
|
||||
if err != nil {
|
||||
t.Fatalf("get ip details: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user