You've already forked caddy-opnsense-blocker
Refine requests log filter controls
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -113,6 +114,27 @@ func (s *Service) ListEvents(ctx context.Context, since time.Time, limit int, op
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (s *Service) ListSourceNames() []string {
|
||||
if s == nil || s.cfg == nil || len(s.cfg.Sources) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := make(map[string]struct{}, len(s.cfg.Sources))
|
||||
items := make([]string, 0, len(s.cfg.Sources))
|
||||
for _, source := range s.cfg.Sources {
|
||||
name := strings.TrimSpace(source.Name)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[name]; ok {
|
||||
continue
|
||||
}
|
||||
seen[name] = struct{}{}
|
||||
items = append(items, name)
|
||||
}
|
||||
sort.Strings(items)
|
||||
return items
|
||||
}
|
||||
|
||||
func (s *Service) ListIPs(ctx context.Context, limit int, state string) ([]model.IPState, error) {
|
||||
return s.store.ListIPStates(ctx, limit, state)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
type App interface {
|
||||
GetOverview(ctx context.Context, since time.Time, limit int, options model.OverviewOptions) (model.Overview, error)
|
||||
ListEvents(ctx context.Context, since time.Time, limit int, options model.EventListOptions) ([]model.Event, error)
|
||||
ListSourceNames() []string
|
||||
ListIPs(ctx context.Context, limit int, state string) ([]model.IPState, error)
|
||||
ListRecentIPs(ctx context.Context, since time.Time, limit int) ([]model.RecentIPRow, error)
|
||||
GetIPDetails(ctx context.Context, ip string) (model.IPDetails, error)
|
||||
@@ -38,6 +39,7 @@ type handler struct {
|
||||
type pageData struct {
|
||||
Title string
|
||||
IP string
|
||||
Sources []string
|
||||
}
|
||||
|
||||
type actionPayload struct {
|
||||
@@ -92,7 +94,7 @@ func (h *handler) handleQueryLogPage(w http.ResponseWriter, r *http.Request) {
|
||||
methodNotAllowed(w)
|
||||
return
|
||||
}
|
||||
renderTemplate(w, h.queryLogPage, pageData{Title: "Requests Log"})
|
||||
renderTemplate(w, h.queryLogPage, pageData{Title: "Requests Log", Sources: h.app.ListSourceNames()})
|
||||
}
|
||||
|
||||
func (h *handler) handleIPPage(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -1020,25 +1022,52 @@ const queryLogHTML = `<!doctype html>
|
||||
<form class="filters-grid" id="controls-form" onsubmit="applyFilters(event)">
|
||||
<div class="field">
|
||||
<label for="source-filter">Source</label>
|
||||
<input id="source-filter" type="text" placeholder="gitea">
|
||||
<select id="source-filter">
|
||||
<option value="">Any source</option>
|
||||
{{ range .Sources }}<option value="{{ . }}">{{ . }}</option>{{ end }}
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="method-filter">Method</label>
|
||||
<input id="method-filter" type="text" list="method-options" placeholder="GET">
|
||||
<datalist id="method-options">
|
||||
<option value="GET"></option>
|
||||
<option value="POST"></option>
|
||||
<option value="HEAD"></option>
|
||||
<option value="PUT"></option>
|
||||
<option value="DELETE"></option>
|
||||
<option value="PATCH"></option>
|
||||
<option value="OPTIONS"></option>
|
||||
<option value="OTHER"></option>
|
||||
</datalist>
|
||||
<select id="method-filter">
|
||||
<option value="">Any method</option>
|
||||
<option value="GET">GET</option>
|
||||
<option value="POST">POST</option>
|
||||
<option value="HEAD">HEAD</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="DELETE">DELETE</option>
|
||||
<option value="PATCH">PATCH</option>
|
||||
<option value="OPTIONS">OPTIONS</option>
|
||||
<option value="OTHER">OTHER</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="status-filter">HTTP status</label>
|
||||
<input id="status-filter" type="text" placeholder="404 or 4xx">
|
||||
<select id="status-filter">
|
||||
<option value="">Any status</option>
|
||||
<optgroup label="Status classes">
|
||||
<option value="2xx">2xx</option>
|
||||
<option value="3xx">3xx</option>
|
||||
<option value="4xx">4xx</option>
|
||||
<option value="5xx">5xx</option>
|
||||
</optgroup>
|
||||
<optgroup label="Common client errors">
|
||||
<option value="400">400</option>
|
||||
<option value="401">401</option>
|
||||
<option value="403">403</option>
|
||||
<option value="404">404</option>
|
||||
<option value="405">405</option>
|
||||
<option value="408">408</option>
|
||||
<option value="410">410</option>
|
||||
<option value="429">429</option>
|
||||
</optgroup>
|
||||
<optgroup label="Common server errors">
|
||||
<option value="500">500</option>
|
||||
<option value="502">502</option>
|
||||
<option value="503">503</option>
|
||||
<option value="504">504</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="state-filter">State</label>
|
||||
|
||||
@@ -169,6 +169,15 @@ func TestHandlerServesOverviewAndManualActions(t *testing.T) {
|
||||
if !strings.Contains(queryLogBody, "Filters, sorting, and pagination") {
|
||||
t.Fatalf("requests log page should expose the collapsible controls panel")
|
||||
}
|
||||
if !strings.Contains(queryLogBody, `<select id="source-filter">`) || !strings.Contains(queryLogBody, `<option value="main">main</option>`) {
|
||||
t.Fatalf("requests log page should expose a source dropdown with configured sources")
|
||||
}
|
||||
if !strings.Contains(queryLogBody, `<select id="method-filter">`) || !strings.Contains(queryLogBody, `<option value="POST">POST</option>`) {
|
||||
t.Fatalf("requests log page should expose a method dropdown")
|
||||
}
|
||||
if !strings.Contains(queryLogBody, `<select id="status-filter">`) || !strings.Contains(queryLogBody, `<option value="4xx">4xx</option>`) {
|
||||
t.Fatalf("requests log page should expose a structured HTTP status dropdown")
|
||||
}
|
||||
if !strings.Contains(queryLogBody, "Rows per page") {
|
||||
t.Fatalf("requests log page should expose pagination settings")
|
||||
}
|
||||
@@ -224,6 +233,10 @@ type stubApp struct {
|
||||
lastEventOptions model.EventListOptions
|
||||
}
|
||||
|
||||
func (s *stubApp) ListSourceNames() []string {
|
||||
return []string{"gitea", "main"}
|
||||
}
|
||||
|
||||
func (s *stubApp) GetOverview(_ context.Context, _ time.Time, _ int, options model.OverviewOptions) (model.Overview, error) {
|
||||
s.lastOverviewOptions = options
|
||||
now := time.Now().UTC()
|
||||
|
||||
Reference in New Issue
Block a user