package v1 import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "gopkg.in/yaml.v3" ) func TestGetOperator(t *testing.T) { api, tmpDir := setupTestAPI(t) // Write state with operator email state := map[string]any{ "operator": map[string]any{"email": "test@example.com"}, } data, _ := yaml.Marshal(state) os.WriteFile(filepath.Join(tmpDir, "state.yaml"), data, 0644) req := httptest.NewRequest("GET", "/api/v1/operator", nil) w := httptest.NewRecorder() api.GetOperator(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) } var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) if resp["email"] != "test@example.com" { t.Errorf("expected email test@example.com, got %v", resp["email"]) } } func TestUpdateOperator(t *testing.T) { api, tmpDir := setupTestAPI(t) body, _ := json.Marshal(map[string]string{"email": "new@example.com"}) req := httptest.NewRequest("PUT", "/api/v1/operator", bytes.NewReader(body)) w := httptest.NewRecorder() api.UpdateOperator(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) } // Verify persisted data, _ := os.ReadFile(filepath.Join(tmpDir, "state.yaml")) var state map[string]any yaml.Unmarshal(data, &state) op := state["operator"].(map[string]any) if op["email"] != "new@example.com" { t.Errorf("expected email new@example.com, got %v", op["email"]) } } func TestGetCentralDomain(t *testing.T) { api, tmpDir := setupTestAPI(t) state := map[string]any{ "cloud": map[string]any{ "central": map[string]any{"domain": "central.example.com"}, }, } data, _ := yaml.Marshal(state) os.WriteFile(filepath.Join(tmpDir, "state.yaml"), data, 0644) req := httptest.NewRequest("GET", "/api/v1/central-domain", nil) w := httptest.NewRecorder() api.GetCentralDomain(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d", w.Code) } var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) if resp["domain"] != "central.example.com" { t.Errorf("expected domain central.example.com, got %v", resp["domain"]) } } func TestUpdateCentralDomain(t *testing.T) { api, _ := setupTestAPI(t) body, _ := json.Marshal(map[string]string{"domain": "new.example.com"}) req := httptest.NewRequest("PUT", "/api/v1/central-domain", bytes.NewReader(body)) w := httptest.NewRecorder() api.UpdateCentralDomain(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) } var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) if resp["domain"] != "new.example.com" { t.Errorf("expected domain new.example.com, got %v", resp["domain"]) } } func TestGetGlobalSecrets_RedactsLeafValues(t *testing.T) { api, tmpDir := setupTestAPI(t) secrets := map[string]any{ "cloudflare": map[string]any{ "apiToken": "super-secret-token", "zoneId": "zone-123", }, "topLevelSecret": "another-secret", } data, _ := yaml.Marshal(secrets) os.WriteFile(filepath.Join(tmpDir, "secrets.yaml"), data, 0600) req := httptest.NewRequest("GET", "/api/v1/secrets", nil) w := httptest.NewRecorder() api.GetGlobalSecrets(w, req) var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) if resp["topLevelSecret"] != "********" { t.Errorf("expected topLevelSecret redacted, got %v", resp["topLevelSecret"]) } cf, ok := resp["cloudflare"].(map[string]any) if !ok { t.Fatalf("expected cloudflare to be a map, got %T", resp["cloudflare"]) } if cf["apiToken"] != "********" { t.Errorf("expected apiToken redacted, got %v", cf["apiToken"]) } } func TestGetGlobalSecrets_RawShowsValues(t *testing.T) { api, tmpDir := setupTestAPI(t) secrets := map[string]any{ "cloudflare": map[string]any{ "apiToken": "my-token", }, } data, _ := yaml.Marshal(secrets) os.WriteFile(filepath.Join(tmpDir, "secrets.yaml"), data, 0600) req := httptest.NewRequest("GET", "/api/v1/secrets?raw=true", nil) w := httptest.NewRecorder() api.GetGlobalSecrets(w, req) var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) cf := resp["cloudflare"].(map[string]any) if cf["apiToken"] != "my-token" { t.Errorf("expected raw apiToken, got %v", cf["apiToken"]) } } func TestCloudflareVerify_NoToken(t *testing.T) { api, _ := setupTestAPI(t) req := httptest.NewRequest("GET", "/api/v1/cloudflare/verify", nil) w := httptest.NewRecorder() api.CloudflareVerify(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d", w.Code) } var resp map[string]any json.Unmarshal(w.Body.Bytes(), &resp) if resp["tokenConfigured"] != false { t.Errorf("expected tokenConfigured=false with no secrets, got %v", resp["tokenConfigured"]) } }