package v1 import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "testing" "github.com/wild-cloud/wild-central/internal/storage" "gopkg.in/yaml.v3" ) func TestGetGlobalConfig_ReturnsWrappedResponse(t *testing.T) { api, tmpDir := setupTestAPI(t) // Write a config with a central domain cfg := map[string]any{ "cloud": map[string]any{ "central": map[string]any{ "domain": "central.example.com", }, }, "operator": map[string]any{ "email": "test@example.com", }, } data, _ := yaml.Marshal(cfg) storage.WriteFile(filepath.Join(tmpDir, "state.yaml"), data, 0644) req := httptest.NewRequest("GET", "/api/v1/config", nil) w := httptest.NewRecorder() api.GetGlobalConfig(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) // Must have "configured" and "config" keys if resp["configured"] != true { t.Errorf("expected configured=true, got %v", resp["configured"]) } config, ok := resp["config"].(map[string]any) if !ok { t.Fatalf("expected config to be a map, got %T", resp["config"]) } // Verify nested structure is preserved cloud, _ := config["cloud"].(map[string]any) central, _ := cloud["central"].(map[string]any) if central["domain"] != "central.example.com" { t.Errorf("expected domain central.example.com, got %v", central["domain"]) } } func TestGetGlobalConfig_EmptyReturnsNotConfigured(t *testing.T) { api, tmpDir := setupTestAPI(t) // Ensure no state file exists os.Remove(filepath.Join(tmpDir, "state.yaml")) req := httptest.NewRequest("GET", "/api/v1/config", nil) w := httptest.NewRecorder() api.GetGlobalConfig(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["configured"] != false { t.Errorf("expected configured=false, got %v", resp["configured"]) } } 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) // Top-level leaf should be redacted if resp["topLevelSecret"] != "********" { t.Errorf("expected topLevelSecret redacted, got %v", resp["topLevelSecret"]) } // Nested map structure should be preserved 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"]) } if cf["zoneId"] != "********" { t.Errorf("expected zoneId redacted, got %v", cf["zoneId"]) } } 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 TestUpdateGlobalConfig(t *testing.T) { api, tmpDir := setupTestAPI(t) update := map[string]any{ "cloud": map[string]any{ "central": map[string]any{ "domain": "new.example.com", }, }, } body, _ := json.Marshal(update) req := httptest.NewRequest("PUT", "/api/v1/config", bytes.NewReader(body)) w := httptest.NewRecorder() api.UpdateGlobalConfig(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) } // Verify file was written data, _ := os.ReadFile(filepath.Join(tmpDir, "state.yaml")) var cfg map[string]any yaml.Unmarshal(data, &cfg) cloud := cfg["cloud"].(map[string]any) central := cloud["central"].(map[string]any) if central["domain"] != "new.example.com" { t.Errorf("expected domain new.example.com, got %v", central["domain"]) } } 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"]) } }