fix: validate canLoginWebUi permission in middleware#4
Merged
Conversation
修复 key 不允许登陆 web 面板的设置无效的问题 **问题描述**: - 登录接口正确检查了 canLoginWebUi 权限 - 但中间件只检查 cookie 是否存在,没有重新验证 key 的权限 - 导致用户登录后,管理员修改 canLoginWebUi=false 时,用户仍可访问 dashboard **修复方案**: - 在 middleware 中调用 validateKey() 验证完整权限 - 包括 canLoginWebUi、isEnabled、expiresAt 等检查 - 如果验证失败,清除 cookie 并重定向到登录页 Fixes #3 Co-authored-by: Ding <ding113@users.noreply.github.com>
Contributor
|
Claude finished @ding113's task —— View job 代码审查完成 ✅任务清单
审查结果:✅ 批准合并这个 PR 很好地解决了 Issue #3 中描述的安全漏洞。代码质量高,逻辑清晰,修复方案完善。 优点
技术细节验证我已验证以下关键点:
建议(可选)虽然当前实现已经很好,但如果考虑性能优化,未来可以:
测试建议建议手动测试以下场景:
总结这是一个高质量的安全修复 PR,建议立即合并。修复方案简洁有效,没有引入不必要的复杂性,同时解决了多个相关的权限实时性问题。 |
Merged
This was referenced Jan 1, 2026
3 tasks
4 tasks
ding113
added a commit
that referenced
this pull request
May 2, 2026
…1149) * fix: keys:reveal endpoint, redirect fallback regression test, bill-on-failure toggle Bundles four fixes raised against dev: 1. **keys:reveal endpoint (Issue #1)** — Add `GET /api/v1/keys/{id}:reveal` mirroring the provider key:reveal pattern (audit log, no-store cache, admin-only). Rewire dashboard key row + key list to fetch the unmasked key on click instead of pre-loading it in user-list payloads. Removes `fullKey` from `UserKeyDisplay` and replaces it with a `canReveal` permission flag — unmasked keys never leave the server unless explicitly requested. 2. **Model redirect fallback regression test (Issue #2)** — Pin the contract: when fallback occurs, the next provider's redirect rules MUST match against the user-requested model (not the model the previous provider rewrote it to). Static analysis + 4 new test scenarios confirm the existing `ModelRedirector.apply` already implements the contract. Test file now guards against future regression. 3. **499 frequency investigation (Issue #3)** — Read-only audit of the recent abort-listener cleanup commits (bcba5d0, 8968a42). Conclusion: no regression — those commits only fixed listener leaks in normal- completion paths. The user's log (Codex CLI cancelling stream at ~3s) is genuine and correctly classified as 499. No code change for this issue; the new bill-on-failure toggle (#4) gives operators a way to recover token billing for these cases. 4. **billNonSuccessfulRequests toggle (Issue #4)** — New system setting (default OFF). When ON, requests with non-2xx status that received positive token usage from the upstream (e.g., 499 mid-stream client abort with partial usage) are billed normally. The existing fake-200 detector still skips billing for fake-success error payloads regardless of toggle state. Schema migration + cache + UI toggle (5 locales) + unit tests. Tests added: - `tests/unit/actions/keys-reveal.test.ts` — admin/auth/404 paths and audit redaction for the new action. - `tests/unit/proxy/model-redirect-fallback.test.ts` — 4 scenarios for fallback redirect behavior. - `tests/unit/proxy/response-handler-bill-non-success.test.ts` — toggle semantics, fake-200 still skipped, setting-read failure fail-closed. Migration: 0102_useful_lionheart.sql adds `bill_non_successful_requests boolean default false not null` to `system_settings` (idempotent ADD COLUMN IF NOT EXISTS). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(pr-review): address review feedback on keys:reveal Resolves feedback from CodeRabbit, Greptile, gemini-code-assist, and chatgpt-codex on PR #1149: 1. **Allow key owner to reveal their own key (HIGH)** — `canExposeFullKey` already marks an owner's keys as `canReveal: true` in list payloads, but the new `getUnmaskedKey` action and v1 router gated everything behind admin, causing a 403 regression for self-service users. - `getUnmaskedKey`: replace admin-only check with admin-OR-owner. - v1 `:reveal` route: relax `requireAuth("admin")` -> `requireAuth("read")`, update OpenAPI `x-required-access` to `admin | owner` and the description to reflect that ownership is checked at the action layer. - Test: replace "rejects non-admin" with two cases — owner allowed, non-owner rejected. 2. **Toast feedback on reveal/copy failure in key-list.tsx (HIGH)** — `fetchUnmaskedKey` was silently returning null. Mirror the key-row-item pattern: import `toast` from sonner and surface failures via `tCommon("copyFailed")`. 3. **Drop stale revealedKey cache when row identity changes (MAJOR)** — two call sites: - `key-row-item.tsx`: `useEffect` resets `revealedKey` and closes the dialog whenever `keyData.id` or `keyData.maskedKey` changes (parent may reuse the same component instance for a different row). - `key-list.tsx`: prune `revealedKeys` and `visibleKeyIds` whenever the incoming `keys` set changes so removed/replaced ids cannot leak their cached plaintext onto a new row. 4. **Missing assertion in model-redirect-fallback test 3 (MINOR)** — the "no rules" reset path must rewrite both `request.model` and `request.message.model`. Add the missing `request.message.model` check to guard against half-reset regressions. Tests: 16/16 pass (3 files), typecheck clean, lint clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(pr-review): align keys:reveal x-required-access with the contract enum CI on commit 12bc4d2 failed two checks: - openapi-contract: 'admin | owner' is not in the allowed enum (public/read/admin) for x-required-access. - openapi-types-drift: generated types out of date because the route description / annotation changed. Fix: keep the auth tier as 'read' (already what `requireAuth("read")` applies on the route) and document the admin-OR-owner contract in the OpenAPI 'description' field instead. Regenerate openapi-types.gen.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
修复 Bug: key 不允许登陆 web 面板的设置无效
问题描述
canLoginWebUi权限canLoginWebUi=false时,用户仍可访问 dashboard修复方案
validateKey()验证完整权限canLoginWebUi、isEnabled、expiresAt等检查Fixes #3
🤖 Generated with Claude Code