check / check (push) Waiting to run
The page at /settings, behind the login and linked from the navigation bar, lists every field of the configuration the server started with: each by its environment variable name, with the README's description and the value in effect. METRICS_PASSWORD and SENTRY_DSN show only as set or not set; their values never reach the template. The handlers now take the loaded Config from the dependency graph. Model: opus-5-5
152 lines
4.0 KiB
Go
152 lines
4.0 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"context"
|
|
"html"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/netip"
|
|
"regexp"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/config"
|
|
"sneak.berlin/go/webhooker/internal/handlers"
|
|
"sneak.berlin/go/webhooker/internal/session"
|
|
)
|
|
|
|
// settingsShown renders the Settings page over cfg as a logged-in user
|
|
// and returns the value it shows for each variable name, plus the
|
|
// whole page.
|
|
func settingsShown(
|
|
t *testing.T, cfg *config.Config,
|
|
) (map[string]string, string) {
|
|
t.Helper()
|
|
|
|
var h *handlers.Handlers
|
|
|
|
var sess *session.Session
|
|
|
|
app := newTestAppWithConfig(t, cfg, &h, &sess)
|
|
app.RequireStart()
|
|
|
|
t.Cleanup(app.RequireStop)
|
|
|
|
req := httptest.NewRequestWithContext(
|
|
context.Background(), http.MethodGet, "/settings", nil,
|
|
)
|
|
for _, c := range authenticatedCookies(t, sess, "id", "admin") {
|
|
req.AddCookie(c)
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
h.HandleSettings().ServeHTTP(w, req)
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
|
|
body := w.Body.String()
|
|
|
|
row := regexp.MustCompile(
|
|
`<code[^>]*>([A-Z_]+)</code>\s*<code[^>]*>([^<]*)</code>`,
|
|
)
|
|
|
|
shown := map[string]string{}
|
|
for _, match := range row.FindAllStringSubmatch(body, -1) {
|
|
shown[match[1]] = html.UnescapeString(match[2])
|
|
}
|
|
|
|
return shown, body
|
|
}
|
|
|
|
func TestSettingsPageShowsLoadedConfiguration(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// DEBUG and MAINTENANCE_MODE get opposite values, and each of
|
|
// METRICS_USERNAME, METRICS_PASSWORD and SENTRY_DSN is the only one
|
|
// of the three set in one of the content tests, so each row is
|
|
// checked against its own field.
|
|
cfg := &config.Config{
|
|
DataDir: t.TempDir(),
|
|
Debug: true,
|
|
MaintenanceMode: false,
|
|
Environment: config.EnvironmentDev,
|
|
MetricsUsername: "scraper",
|
|
MetricsPassword: "",
|
|
Port: 9123,
|
|
SentryDSN: "",
|
|
BindAddress: "192.0.2.10",
|
|
RetentionSweepInterval: 17 * time.Minute,
|
|
SessionIdleTimeout: 3 * time.Hour,
|
|
ReceiverRateLimit: 77,
|
|
TrustedProxies: []netip.Prefix{
|
|
netip.MustParsePrefix("10.1.0.0/16"),
|
|
},
|
|
AllowedEgressCIDRs: []netip.Prefix{
|
|
netip.MustParsePrefix("192.168.5.0/24"),
|
|
netip.MustParsePrefix("fd00::/8"),
|
|
},
|
|
}
|
|
|
|
shown, body := settingsShown(t, cfg)
|
|
|
|
assert.Equal(t, map[string]string{
|
|
"WEBHOOKER_ENVIRONMENT": "dev",
|
|
"PORT": "9123",
|
|
"BIND_ADDRESS": "192.0.2.10",
|
|
"DATA_DIR": cfg.DataDir,
|
|
"DEBUG": "true",
|
|
"MAINTENANCE_MODE": "false",
|
|
"METRICS_USERNAME": "scraper",
|
|
"METRICS_PASSWORD": "not set",
|
|
"SENTRY_DSN": "not set",
|
|
"RETENTION_SWEEP_INTERVAL": "17m0s",
|
|
"SESSION_IDLE_TIMEOUT": "3h0m0s",
|
|
"RECEIVER_RATE_LIMIT": "77",
|
|
"TRUSTED_PROXIES": "10.1.0.0/16",
|
|
"ALLOWED_EGRESS_CIDRS": "192.168.5.0/24, fd00::/8",
|
|
}, shown)
|
|
|
|
assert.Contains(
|
|
t, body, `href="/settings"`,
|
|
"the navigation bar links to the page",
|
|
)
|
|
}
|
|
|
|
func TestSettingsPageShowsUnsetValues(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const metricsPassword = "metrics-password-1f9a"
|
|
|
|
shown, body := settingsShown(t, &config.Config{
|
|
DataDir: t.TempDir(),
|
|
MetricsPassword: metricsPassword,
|
|
})
|
|
|
|
assert.Equal(t, "not set", shown["METRICS_USERNAME"])
|
|
assert.Equal(t, "set", shown["METRICS_PASSWORD"])
|
|
assert.Equal(t, "not set", shown["SENTRY_DSN"])
|
|
assert.NotContains(t, body, metricsPassword)
|
|
assert.Equal(t, "none", shown["TRUSTED_PROXIES"])
|
|
assert.Equal(t, "none", shown["ALLOWED_EGRESS_CIDRS"])
|
|
}
|
|
|
|
func TestSettingsPageShowsSentryDSNOnlyAsSet(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const (
|
|
sentryKey = "dsnkey7c2e"
|
|
sentryDSN = "https://" + sentryKey + "@errors.example.com/42"
|
|
)
|
|
|
|
shown, body := settingsShown(t, &config.Config{
|
|
DataDir: t.TempDir(),
|
|
SentryDSN: sentryDSN,
|
|
})
|
|
|
|
assert.Equal(t, "not set", shown["METRICS_USERNAME"])
|
|
assert.Equal(t, "not set", shown["METRICS_PASSWORD"])
|
|
assert.Equal(t, "set", shown["SENTRY_DSN"])
|
|
assert.NotContains(t, body, sentryKey)
|
|
}
|