| 216 | } |
| 217 | |
| 218 | func TestRotateAPIKey_InvalidatesCache(t *testing.T) { |
| 219 | ctx := context.Background() |
| 220 | |
| 221 | // Use a dedicated test user so we don't mutate the shared userAPIKey |
| 222 | rotateUserAPIKey := "rotate-test-api-key" |
| 223 | rotateUserID := "rotate-test-user-id" |
| 224 | |
| 225 | // 1) Confirm the dedicated user's API key works and warm the cache |
| 226 | meURL := apiBaseURL + "/v1/users/me" |
| 227 | req, err := http.NewRequestWithContext(ctx, http.MethodGet, meURL, nil) |
| 228 | require.NoError(t, err) |
| 229 | req.Header.Set("x-api-key", rotateUserAPIKey) |
| 230 | |
| 231 | resp, err := http.DefaultClient.Do(req) |
| 232 | require.NoError(t, err) |
| 233 | defer resp.Body.Close() |
| 234 | |
| 235 | body, err := io.ReadAll(resp.Body) |
| 236 | require.NoError(t, err) |
| 237 | require.Equal(t, http.StatusOK, resp.StatusCode, "initial auth failed: %s", string(body)) |
| 238 | |
| 239 | // Parse the current API key from the response |
| 240 | var meResp struct { |
| 241 | Data struct { |
| 242 | ID string `json:"id"` |
| 243 | APIKey string `json:"api_key"` |
| 244 | } `json:"data"` |
| 245 | } |
| 246 | require.NoError(t, json.Unmarshal(body, &meResp)) |
| 247 | require.Equal(t, rotateUserID, meResp.Data.ID) |
| 248 | oldAPIKey := meResp.Data.APIKey |
| 249 | require.NotEmpty(t, oldAPIKey) |
| 250 | t.Logf("user ID: %s, old API key prefix: %s...", rotateUserID, oldAPIKey[:10]) |
| 251 | |
| 252 | // 2) Rotate the API key |
| 253 | rotateURL := fmt.Sprintf("%s/v1/users/%s/api-keys", apiBaseURL, rotateUserID) |
| 254 | req, err = http.NewRequestWithContext(ctx, http.MethodDelete, rotateURL, nil) |
| 255 | require.NoError(t, err) |
| 256 | req.Header.Set("x-api-key", rotateUserAPIKey) |
| 257 | |
| 258 | resp, err = http.DefaultClient.Do(req) |
| 259 | require.NoError(t, err) |
| 260 | defer resp.Body.Close() |
| 261 | |
| 262 | body, err = io.ReadAll(resp.Body) |
| 263 | require.NoError(t, err) |
| 264 | require.Equal(t, http.StatusOK, resp.StatusCode, "rotate failed: %s", string(body)) |
| 265 | |
| 266 | // Parse new API key from rotate response |
| 267 | var rotateResp struct { |
| 268 | Data struct { |
| 269 | APIKey string `json:"api_key"` |
| 270 | } `json:"data"` |
| 271 | } |
| 272 | require.NoError(t, json.Unmarshal(body, &rotateResp)) |
| 273 | newAPIKey := rotateResp.Data.APIKey |
| 274 | require.NotEmpty(t, newAPIKey) |
| 275 | require.NotEqual(t, oldAPIKey, newAPIKey, "API key should have changed after rotation") |