Conversation
主要改动: 1. 认证错误优化 (auth-guard.ts, session.ts) - 替换通用错误为5个详细场景的中文错误消息 - 添加 errorResponse 字段用于传递详细错误 - 错误场景:未提供凭据、冲突密钥、密钥无效、用户禁用、用户过期 2. 用户列表 UI 优化 (user-key-table-row.tsx) - 添加用户状态徽章(正常/已过期/即将过期/禁用) - Provider Group 拆分显示为彩色徽章(最多2个 + "+N") - 用户标签以 [tag1, tag2] 格式显示 - 改进过期时间验证逻辑(使用 Number.isFinite) 3. 密钥状态优化 (key-row-item.tsx) - 添加密钥状态徽章 - 修复 formatExpiry 函数重复定义问题 - 正确处理"永不过期"等无法解析的日期文本 - Provider Group 拆分显示(最多1个 + "+N") 4. 国际化支持 (dashboard.json) - 为 zh-CN, en, ja, ru, zh-TW 添加 keyStatus 和 userStatus 翻译 - 添加 active, expired, expiringSoon 状态翻译 技术改进: - 72小时过期预警阈值 - 乐观 UI 更新模式 - 更安全的数字验证(Number.isFinite) - 统一错误消息语言(中文) Closes #425
Summary of ChangesHello @NightYuYyy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求旨在通过提供更详细的认证错误信息和更直观的用户/密钥状态显示来优化用户体验。它改进了后端认证逻辑,使其能返回具体的错误原因,并对前端 UI 进行了增强,包括状态徽章、彩色分组显示和国际化支持,从而使管理界面更加清晰和易用。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🧪 测试结果
总体结果: ✅ 所有测试通过 |
| }; | ||
| } | ||
|
|
||
| const EXPIRING_SOON_MS = 72 * 60 * 60 * 1000; // 72小时 |
| function splitGroups(value?: string | null): string[] { | ||
| return (value ?? "") | ||
| .split(",") | ||
| .map((g) => g.trim()) | ||
| .filter(Boolean); |
| } | ||
|
|
||
| const DEFAULT_GRID_COLUMNS_CLASS = "grid-cols-[minmax(260px,1fr)_120px_repeat(6,90px)_80px]"; | ||
| const EXPIRING_SOON_MS = 72 * 60 * 60 * 1000; // 72小时 |
| function splitGroups(value?: string | null): string[] { | ||
| return (value ?? "") | ||
| .split(",") | ||
| .map((g) => g.trim()) | ||
| .filter(Boolean); |
There was a problem hiding this comment.
Code Review Summary
This PR enhances authentication error messages and user/key status UI display. The implementation is clean with proper error handling, user feedback, and i18n support across all 5 locales.
PR Size: M
- Lines changed: 228 (204 additions, 24 deletions)
- Files changed: 9
Issues Found
| Category | Critical | High | Medium | Low |
|---|---|---|---|---|
| Logic/Bugs | 0 | 0 | 0 | 0 |
| Security | 0 | 0 | 0 | 0 |
| Error Handling | 0 | 0 | 0 | 0 |
| Types | 0 | 0 | 0 | 0 |
| Comments/Docs | 0 | 0 | 0 | 0 |
| Tests | 0 | 0 | 0 | 0 |
| Simplification | 0 | 0 | 0 | 0 |
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean (all auth errors properly logged and return detailed responses)
- Type safety - Clean (proper type annotations with explicit return types)
- Documentation accuracy - Clean
- Test coverage - Adequate (core auth functionality has existing test coverage)
- Code clarity - Good
Notable Implementation Details
-
Auth Error Handling (
auth-guard.ts): The newerrorResponsefield inAuthStateproperly propagates detailed error messages. All error paths include logging and return appropriate 401 responses with specific error types. -
Expiry Status Logic (
getExpiryStatus,getKeyExpiryStatus): Proper validation usingNumber.isFinite()to handle edge cases. The 72-hour warning threshold follows existing patterns in the codebase. -
i18n Completeness: All 5 locales (en, ja, ru, zh-CN, zh-TW) have been updated with the new status translations.
-
Optimistic Updates: UI components properly implement optimistic updates with rollback on failure, maintaining good UX.
Automated review by Claude AI
| success: false, | ||
| errorResponse: ProxyResponses.buildError( | ||
| 401, | ||
| "未提供认证凭据。请在 Authorization 头部、x-api-key 头部或 x-goog-api-key 头部中包含 API 密钥。", |
There was a problem hiding this comment.
[MEDIUM] [ERROR-NO-USER-FEEDBACK] 认证失败提示缺少 Bearer 格式,容易误导用户
Why this is a problem: 在 src/app/v1/_lib/proxy/auth-guard.ts:63 新增的错误信息只说“在 Authorization 头部…包含 API 密钥”,但该文件的 extractKeyFromAuthorization() 只接受 Authorization: Bearer <key>(/^Bearer\s+(.+)$/i)。用户按提示直接填 Authorization: <key> 会仍然被判定为“未提供认证凭据”。
Suggested fix:
errorResponse: ProxyResponses.buildError(
401,
"未提供认证凭据。请使用 Authorization: Bearer <API_KEY>,或 x-api-key / x-goog-api-key(Gemini 也支持 ?key=<API_KEY>)。",
"authentication_error"
),| success: false, | ||
| errorResponse: ProxyResponses.buildError( | ||
| 401, | ||
| "API 密钥无效。提供的密钥不存在或已被删除。", |
There was a problem hiding this comment.
[MEDIUM] [COMMENT-INACCURATE] “API 密钥无效”提示与真实失败原因不一致(禁用/过期也会走这里)
Why this is a problem: 在 src/app/v1/_lib/proxy/auth-guard.ts:105 新增的错误信息写的是“密钥不存在或已被删除”,但 validateApiKeyAndGetUser()(src/repository/key.ts:472-480)同时过滤了 keys.isEnabled = true 和 keys.expiresAt > now,因此密钥被禁用或已过期也会触发该分支,导致用户排查方向错误。
Suggested fix:
errorResponse: ProxyResponses.buildError(
401,
"API 密钥无效。提供的密钥不存在、已被删除、已被禁用或已过期。",
"invalid_api_key"
),There was a problem hiding this comment.
Code Review Summary
This PR changes proxy authentication error responses and adds UI status badges for users/keys. The main concerns are two new auth error messages that are misleading/incomplete, which will slow client debugging and increase support load.
PR Size: M
- Lines changed: 228
- Files changed: 9
Issues Found
| Category | Critical | High | Medium | Low |
|---|---|---|---|---|
| Logic/Bugs | 0 | 0 | 0 | 0 |
| Security | 0 | 0 | 0 | 0 |
| Error Handling | 0 | 0 | 2 | 0 |
| Types | 0 | 0 | 0 | 0 |
| Comments/Docs | 0 | 0 | 0 | 0 |
| Tests | 0 | 0 | 0 | 0 |
| Simplification | 0 | 0 | 0 | 0 |
Critical Issues (Must Fix)
- None.
High Priority Issues (Should Fix)
src/app/v1/_lib/proxy/auth-guard.ts:63Missing-credentials message doesn’t specifyAuthorization: Bearer <API_KEY>(Gemini also supports?key=).src/app/v1/_lib/proxy/auth-guard.ts:105“Invalid API key” message claims only non-existent/deleted but backend also treats disabled/expired keys as invalid.
Review Coverage
- Logic and correctness
- Security (OWASP Top 10)
- Error handling
- Type safety
- Documentation accuracy
- Test coverage
- Code clarity
Automated review by Codex AI
Summary
Optimizes authentication error messages and user/key status UI display, providing more detailed error information and intuitive status presentation.
Fixes #425 - Implements user expiry display optimization and provider group visibility
概述
优化了认证错误消息和用户/密钥状态的 UI 显示,提供更详细的错误信息和更直观的状态展示。
主要改动
1. 认证错误优化 🔒
文件:
src/app/v1/_lib/proxy/auth-guard.ts,src/app/v1/_lib/proxy/session.ts替换通用错误为 5 个详细的中文错误场景:
2. 用户列表 UI 优化 👥
文件:
src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx[tag1, tag2]格式显示Number.isFinite)3. 密钥状态优化 🔑
文件:
src/app/[locale]/dashboard/_components/user/key-row-item.tsxformatExpiry函数重复定义问题4. 国际化支持 🌍
文件:
messages/{zh-CN,en,ja,ru,zh-TW}/dashboard.jsonactive,expired,expiringSoon状态技术亮点 🔧
Number.isFinite()防止边界情况Changes
Core Changes
ProxyAuthenticatorwith 5 specific error types and detailed messagesAuthState.errorResponsefield for error propagationgetExpiryStatus()andgetKeyExpiryStatus()utility functionsSupporting Changes
active,expired,expiringSoonstates in 5 localesformatExpiryfunction definitionEXPIRING_SOON_MSconstant (72 hours) for expiry warning thresholdCodex 审查 ✅
根据 Codex 代码审查修复:
formatExpiry函数Testing
Automated Tests
Manual Testing
Checklist
Description enhanced by Claude AI