feat: add minimal web dashboard with stats, top credentials, and sessions
Implements Phase 1.5 — an embedded web UI using Go templates, Pico CSS (dark theme), and htmx for auto-refreshing stats and active sessions. Adds read query methods to the Store interface (GetDashboardStats, GetTopUsernames, GetTopPasswords, GetTopIPs, GetRecentSessions) with implementations for both SQLite and MemoryStore. Introduces the internal/web package with server, handlers, templates, and tests. Web server is opt-in via [web] config section and runs alongside SSH with graceful shutdown. Bumps version to 0.2.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -222,6 +222,39 @@ custom_key = "value"
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWebDefaults(t *testing.T) {
|
||||
path := writeTemp(t, "")
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if cfg.Web.Enabled {
|
||||
t.Error("web should be disabled by default")
|
||||
}
|
||||
if cfg.Web.ListenAddr != ":8080" {
|
||||
t.Errorf("default web listen_addr = %q, want %q", cfg.Web.ListenAddr, ":8080")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWebConfig(t *testing.T) {
|
||||
content := `
|
||||
[web]
|
||||
enabled = true
|
||||
listen_addr = ":9090"
|
||||
`
|
||||
path := writeTemp(t, content)
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !cfg.Web.Enabled {
|
||||
t.Error("web should be enabled")
|
||||
}
|
||||
if cfg.Web.ListenAddr != ":9090" {
|
||||
t.Errorf("web listen_addr = %q, want %q", cfg.Web.ListenAddr, ":9090")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadMissingFile(t *testing.T) {
|
||||
_, err := Load("/nonexistent/path/config.toml")
|
||||
if err == nil {
|
||||
|
||||
Reference in New Issue
Block a user