- Go service with its own multi-stage Dockerfile and docker-compose.yml; runs as container webrestrict-control on port 8791. - SQLite schema for the full AGENTS.md §7 data model via versioned migrations (PRAGMA user_version); audit log is append-only. - Configuration from the process environment; the real env file is gitignored and a template is committed. No secrets in the repo. - Separate session login (signed HMAC cookie + CSRF) for Sam. - GET /health; HTMX + server-rendered dashboard styled with the Family Home Lab tokens.css (copied) and Inter fonts; dark mode; phone-friendly. - Caddy vhost for webrestrict.lab.audasmedia.com.au applied on .35 (Let's Encrypt cert issued); route recorded in deploy/caddy/webrestrict.caddy. - Unit tests for config, auth and store. Co-Authored-By: Paperclip <noreply@paperclip.ing>
53 lines
1.3 KiB
Go
53 lines
1.3 KiB
Go
package config
|
|
|
|
import (
|
|
"log/slog"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLoadDefaultsAndValidation(t *testing.T) {
|
|
t.Setenv("CONTROL_SESSION_SECRET", "0123456789abcdef")
|
|
t.Setenv("CONTROL_ADMIN_PASSWORD", "hunter2")
|
|
t.Setenv("CONTROL_ADDR", "")
|
|
t.Setenv("CONTROL_DB_PATH", "")
|
|
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatalf("Load: %v", err)
|
|
}
|
|
if cfg.Addr != ":8791" {
|
|
t.Errorf("Addr = %q, want :8791", cfg.Addr)
|
|
}
|
|
if cfg.DBPath != "/data/control.db" {
|
|
t.Errorf("DBPath = %q, want /data/control.db", cfg.DBPath)
|
|
}
|
|
if cfg.AdminUsername != "sam" {
|
|
t.Errorf("AdminUsername = %q, want sam", cfg.AdminUsername)
|
|
}
|
|
if cfg.SessionTTL != 12*time.Hour {
|
|
t.Errorf("SessionTTL = %v, want 12h", cfg.SessionTTL)
|
|
}
|
|
if cfg.LogLevel != slog.LevelInfo {
|
|
t.Errorf("LogLevel = %v, want info", cfg.LogLevel)
|
|
}
|
|
if !cfg.CookieSecure {
|
|
t.Error("CookieSecure = false, want true by default")
|
|
}
|
|
}
|
|
|
|
func TestLoadRequiresSecretAndPassword(t *testing.T) {
|
|
t.Setenv("CONTROL_SESSION_SECRET", "")
|
|
t.Setenv("CONTROL_ADMIN_PASSWORD", "hunter2")
|
|
if _, err := Load(); err == nil {
|
|
t.Error("expected error when session secret is missing")
|
|
}
|
|
|
|
t.Setenv("CONTROL_SESSION_SECRET", "0123456789abcdef")
|
|
t.Setenv("CONTROL_ADMIN_PASSWORD", "")
|
|
t.Setenv("CONTROL_ADMIN_PASSWORD_HASH", "")
|
|
if _, err := Load(); err == nil {
|
|
t.Error("expected error when no admin password is set")
|
|
}
|
|
}
|