(w http.ResponseWriter, r *http.Request, id string)
| 2376 | accessToken, |
| 2377 | refreshToken, |
| 2378 | expiresAt, |
| 2379 | profileArn, |
| 2380 | ) |
| 2381 | return true, nil |
| 2382 | } |
| 2383 | |
| 2384 | // ensureValidToken 确保 token 有效 |
| 2385 | func (h *Handler) ensureValidToken(account *config.Account) error { |
| 2386 | if config.IsAPIKeyAccount(account) { |
| 2387 | if accountBearerToken(account) == "" { |
| 2388 | return fmt.Errorf("account %s has no kiroApiKey", account.ID) |
| 2389 | } |
| 2390 | return nil |
| 2391 | } |
| 2392 | if account.ExpiresAt == 0 || time.Now().Unix() < account.ExpiresAt-tokenRefreshSkewSeconds { |
| 2393 | return nil |
| 2394 | } |
| 2395 | |
| 2396 | _, err := h.refreshAccountToken(account, false) |
| 2397 | return err |
| 2398 | } |
| 2399 | |
| 2400 | // ==================== 管理 API ==================== |
| 2401 | |
| 2402 | func (h *Handler) handleAdminAPI(w http.ResponseWriter, r *http.Request) { |
| 2403 | // 验证密码 |
| 2404 | password := r.Header.Get("X-Admin-Password") |
| 2405 | if password == "" { |
| 2406 | cookie, _ := r.Cookie("admin_password") |
| 2407 | if cookie != nil { |
| 2408 | password = cookie.Value |
| 2409 | } |
| 2410 | } |
| 2411 | |
| 2412 | if password != config.GetPassword() { |
| 2413 | w.WriteHeader(401) |
| 2414 | json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"}) |
| 2415 | return |
| 2416 | } |
| 2417 | |
| 2418 | path := strings.TrimPrefix(r.URL.Path, "/admin/api") |
| 2419 | w.Header().Set("Content-Type", "application/json; charset=utf-8") |
| 2420 | |
| 2421 | switch { |
| 2422 | case path == "/accounts" && r.Method == "GET": |
| 2423 | h.apiGetAccounts(w, r) |
| 2424 | case path == "/accounts" && r.Method == "POST": |
| 2425 | h.apiAddAccount(w, r) |
| 2426 | case path == "/accounts/batch" && r.Method == "POST": |
| 2427 | h.apiBatchAccounts(w, r) |
| 2428 | // models/refresh 必须在通用 /refresh 前匹配,否则会被误拦截 |
| 2429 | case path == "/accounts/models/refresh" && r.Method == "POST": |
| 2430 | h.apiRefreshAllAccountsModels(w, r) |
| 2431 | case strings.HasPrefix(path, "/accounts/") && strings.HasSuffix(path, "/models/refresh") && r.Method == "POST": |
| 2432 | id := strings.TrimSuffix(strings.TrimPrefix(path, "/accounts/"), "/models/refresh") |
| 2433 | h.apiRefreshAccountModels(w, r, id) |
| 2434 | case strings.HasPrefix(path, "/accounts/") && strings.HasSuffix(path, "/refresh") && r.Method == "POST": |
| 2435 | id := strings.TrimSuffix(strings.TrimPrefix(path, "/accounts/"), "/refresh") |
no test coverage detected