package webui import ( "net/http" "net/http/httptest" "net/url" "strings" "testing" ) // TestLetsEncryptSaveBlankMeansKeepExisting confirms a secret field submitted blank // doesn't wipe a previously-saved credential, while a non-empty submission does // overwrite it — the whole reason this page has its own save handler instead of using // the generic settingsUpdate reflection. func TestLetsEncryptSaveBlankMeansKeepExisting(t *testing.T) { app := newTestApp(t) mux := app.Mux() cookie := loginSession(t, app) app.Cfg.Section("LetsEncrypt").Key("cloudflare_api_token").SetValue("original-secret-token") // Submit the form with the secret field blank (and a plain field changed). form := url.Values{ "enabled": {"true"}, "dns_provider": {"cloudflare"}, "domains": {"mail.example.com"}, "contact_email": {"admin@example.com"}, } req := httptest.NewRequest(http.MethodPost, Prefix+"/letsencrypt/save", strings.NewReader(form.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.AddCookie(cookie) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != http.StatusFound { t.Fatalf("expected redirect, got %d: %s", rec.Code, rec.Body.String()) } if got := app.Cfg.Section("LetsEncrypt").Key("cloudflare_api_token").String(); got != "original-secret-token" { t.Fatalf("expected the blank submission to keep the existing token, got %q", got) } if got := app.Cfg.Section("LetsEncrypt").Key("enabled").String(); got != "true" { t.Fatalf("expected the plain field to be updated, got %q", got) } // Now submit a real value for the secret field — it must overwrite. form.Set("cloudflare_api_token", "new-secret-token") req2 := httptest.NewRequest(http.MethodPost, Prefix+"/letsencrypt/save", strings.NewReader(form.Encode())) req2.Header.Set("Content-Type", "application/x-www-form-urlencoded") req2.AddCookie(cookie) rec2 := httptest.NewRecorder() mux.ServeHTTP(rec2, req2) if rec2.Code != http.StatusFound { t.Fatalf("expected redirect, got %d", rec2.Code) } if got := app.Cfg.Section("LetsEncrypt").Key("cloudflare_api_token").String(); got != "new-secret-token" { t.Fatalf("expected a non-empty submission to overwrite the token, got %q", got) } } // TestLetsEncryptPageNeverRendersSecrets confirms secret fields are always blank in // the rendered form, even when a value is stored. func TestLetsEncryptPageNeverRendersSecrets(t *testing.T) { app := newTestApp(t) mux := app.Mux() cookie := loginSession(t, app) app.Cfg.Section("LetsEncrypt").Key("cloudflare_api_token").SetValue("super-secret-value") req := httptest.NewRequest(http.MethodGet, Prefix+"/letsencrypt", nil) req.AddCookie(cookie) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("status = %d", rec.Code) } if strings.Contains(rec.Body.String(), "super-secret-value") { t.Fatal("expected the stored secret to never be rendered back into the page") } }