Skip to content

fix: handle paginated API key search response#5014

Open
yyhhyyyyyy wants to merge 2 commits into
QuantumNous:mainfrom
yyhhyyyyyy:fix/api-key-search-pagination
Open

fix: handle paginated API key search response#5014
yyhhyyyyyy wants to merge 2 commits into
QuantumNous:mainfrom
yyhhyyyyyy:fix/api-key-search-pagination

Conversation

@yyhhyyyyyy
Copy link
Copy Markdown
Contributor

@yyhhyyyyyy yyhhyyyyyy commented May 21, 2026

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
修复default 前端 API Key 搜索结果解析逻辑。/api/token/search 返回的是分页结构 data.items / data.total,之前按数组读取data,导致搜索后列表为空或分页异常。现在搜索接口类型与列表接口保持一致,并统一从分页字段读取数据和总数。
同时将名称搜索与密钥搜索交给后端处理,避免前端再用已脱敏的 key 做二次过滤,从而保证按真实 API Key 搜索时后端命中的结果能正常展示。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
image

Summary by CodeRabbit

  • New Features

    • Added a URL-synced, debounced token filter for API keys with an additional search input and updated search placeholder.
  • Improvements

    • Searches now include token + keyword together and use server-backed pagination for results.
    • Updated filter labels across supported languages to distinguish name, ID, and API key searches.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 692ba6d3-8901-4fe9-9cf7-da5e9b4db85a

📥 Commits

Reviewing files that changed from the base of the PR and between 3afa480 and 8b6709f.

📒 Files selected for processing (1)
  • web/default/src/features/keys/components/api-keys-table.tsx

Walkthrough

Adds a debounced, URL-synced token filter to the API Keys table; updates searchApiKeys return type to GetApiKeysResponse; switches table to server-side searching when keyword or token present; makes pagination use data.total; adds optional token route param and updates i18n filter labels.

Changes

API Keys Search and Token Filter

Layer / File(s) Summary
API Response Type Contract
web/default/src/features/keys/api.ts
searchApiKeys return type updated to Promise<GetApiKeysResponse> to match backend paginated response.
Table Data Handling and Token Filter Implementation
web/default/src/features/keys/components/api-keys-table.tsx
Adds debounced token filter synced to URL state, adds tokenFilter to React Query key, uses searchApiKeys when keyword or token present, reads results from data.items/data.total, replaces client-side globalFilterFn with a no-op, and always uses manual pagination. Also updates toolbar UI with an additional token input.
Route Validation Schema
web/default/src/routes/_authenticated/keys/index.tsx
Adds optional token string parameter to apiKeySearchSchema with .catch('') fallback.
Internationalization Filter Labels
web/default/src/i18n/locales/{en,fr,ja,ru,vi,zh}.json
Introduces "Filter by API key..." label and replaces "Filter by name or key..." with "Filter by name..." across locales.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ApiKeysTable
  participant ReactQuery
  participant ApiService
  User->>ApiKeysTable: Type keyword or token
  ApiKeysTable->>ApiKeysTable: Debounce token input
  ApiKeysTable->>ApiKeysTable: Update URL _tokenSearch
  ApiKeysTable->>ReactQuery: Fetch (queryKey includes keyword, token)
  ReactQuery->>ApiService: Call searchApiKeys(keyword, token) or getApiKeys()
  ApiService-->>ReactQuery: Return { items, total, page, page_size }
  ReactQuery-->>ApiKeysTable: Provide data.items and data.total
  ApiKeysTable->>ApiKeysTable: Render rows and pagination
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • seefs001
  • Calcium-Ion

Poem

A rabbit taps the search and hums, 🐇
Debounced tokens, URL drums,
Tables fill where silence was,
Items count and pages buzz—
Keys return, the UI hums. 🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: handle paginated API key search response' directly addresses the main change: fixing API key search parsing to handle paginated responses with items/total fields instead of treating response.data as an array.
Linked Issues check ✅ Passed All coding objectives from issue #5010 are met: searchApiKeys return type changed to GetApiKeysResponse [#5010], result.data?.items and result.data?.total are read in both list and search flows [#5010], token parameter added to search schema [#5010], and name/key filtering delegated to backend via keyword and token parameters [#5010].
Out of Scope Changes check ✅ Passed All changes are in scope for fixing the paginated API key search bug: API type updates, component filtering logic, URL state management, backend parameter passing, and i18n filter labels for the new token filter input.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/default/src/features/keys/components/api-keys-table.tsx`:
- Around line 213-216: Remove the sensitive "_tokenSearch" entry from the
URL-synced columnFilters and stop persisting it to route/query params; instead
keep the token search value in local component state within the ApiKeysTable
component and pass that local value into the data-fetch/query function (where
columnFilters or searchKey 'token' is consumed) so filtering still works without
writing the token to the URL or router state; search the file for
"_tokenSearch", the columnFilters array and any code that syncs column state to
query params and remove/replace those URL syncs so only non-sensitive filters
remain in columnFilters.
- Around line 336-341: The token filter Input (value={tokenFilterInput},
onChange={e => setTokenFilterInput(e.target.value)}) lacks an accessible name;
add either a visible <label> associated with this input or provide an aria-label
(e.g., aria-label="Filter API keys") on the Input component so screen readers
can identify it, and ensure the label text is localized via t(...) if
applicable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d90d54c3-cccb-4747-8761-29aed9478955

📥 Commits

Reviewing files that changed from the base of the PR and between 006e801 and 3afa480.

📒 Files selected for processing (9)
  • web/default/src/features/keys/api.ts
  • web/default/src/features/keys/components/api-keys-table.tsx
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json
  • web/default/src/routes/_authenticated/keys/index.tsx

Comment on lines +213 to +216
columnFilters: [
{ columnId: 'status', searchKey: 'status', type: 'array' },
{ columnId: '_tokenSearch', searchKey: 'token', type: 'string' },
],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid persisting API key token filters in URL state.

Syncing _tokenSearch to URL query params can leak sensitive API key fragments via browser history, shared links, and referrer logs. Keep token search input in local component state only, and pass it to the query function without route synchronization.

Suggested change
   columnFilters: [
     { columnId: 'status', searchKey: 'status', type: 'array' },
-    { columnId: '_tokenSearch', searchKey: 'token', type: 'string' },
   ],

-  const tokenFilterFromUrl =
-    (columnFilters.find((f) => f.id === '_tokenSearch')?.value as string) || ''
-  const [tokenFilterInput, setTokenFilterInput] = useState(tokenFilterFromUrl)
+  const [tokenFilterInput, setTokenFilterInput] = useState('')
   const debouncedTokenFilter = useDebounce(tokenFilterInput, 500)

-  useEffect(() => {
-    setTokenFilterInput(tokenFilterFromUrl)
-  }, [tokenFilterFromUrl])
-
-  useEffect(() => {
-    if (debouncedTokenFilter !== tokenFilterFromUrl) {
-      onColumnFiltersChange((prev) => {
-        const filtered = prev.filter((f) => f.id !== '_tokenSearch')
-        return debouncedTokenFilter
-          ? [...filtered, { id: '_tokenSearch', value: debouncedTokenFilter }]
-          : filtered
-      })
-    }
-  }, [debouncedTokenFilter, tokenFilterFromUrl, onColumnFiltersChange])
-
-  const tokenFilter = tokenFilterFromUrl
+  const tokenFilter = debouncedTokenFilter.trim()

As per coding guidelines, "do not store sensitive information in frontend".

Also applies to: 219-237

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/features/keys/components/api-keys-table.tsx` around lines 213
- 216, Remove the sensitive "_tokenSearch" entry from the URL-synced
columnFilters and stop persisting it to route/query params; instead keep the
token search value in local component state within the ApiKeysTable component
and pass that local value into the data-fetch/query function (where
columnFilters or searchKey 'token' is consumed) so filtering still works without
writing the token to the URL or router state; search the file for
"_tokenSearch", the columnFilters array and any code that syncs column state to
query params and remove/replace those URL syncs so only non-sensitive filters
remain in columnFilters.

Comment thread web/default/src/features/keys/components/api-keys-table.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

新版前端API密钥搜索不到数据

1 participant