Skip to content

Comments

feat: 优化认证错误和用户/密钥状态显示 (Issue #425)#440

Merged
ding113 merged 2 commits intodevfrom
feat/issue-425-auth-error-ui-optimization
Dec 24, 2025
Merged

feat: 优化认证错误和用户/密钥状态显示 (Issue #425)#440
ding113 merged 2 commits intodevfrom
feat/issue-425-auth-error-ui-optimization

Conversation

@NightYuYyy
Copy link
Collaborator

@NightYuYyy NightYuYyy commented Dec 24, 2025

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 个详细的中文错误场景

  • ✅ 未提供认证凭据
  • ✅ 提供了多个冲突的 API 密钥
  • ✅ API 密钥无效(不存在或已删除)
  • ✅ 用户账户已被禁用
  • ✅ 用户账户已过期(显示过期日期)

2. 用户列表 UI 优化 👥

文件: src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx

  • ✅ 添加用户状态徽章(正常/已过期/即将过期/禁用)
  • ✅ Provider Group 拆分显示为彩色徽章(最多 2 个 + "+N")
  • ✅ 用户标签以 [tag1, tag2] 格式显示
  • ✅ 改进过期时间验证逻辑(使用 Number.isFinite

3. 密钥状态优化 🔑

文件: src/app/[locale]/dashboard/_components/user/key-row-item.tsx

  • ✅ 添加密钥状态徽章
  • ✅ 修复 formatExpiry 函数重复定义问题
  • ✅ 正确处理 "永不过期" 等无法解析的日期文本
  • ✅ Provider Group 拆分显示(最多 1 个 + "+N")

4. 国际化支持 🌍

文件: messages/{zh-CN,en,ja,ru,zh-TW}/dashboard.json

  • ✅ 为 5 种语言添加状态翻译
  • ✅ 支持 active, expired, expiringSoon 状态

技术亮点 🔧

  • 72 小时过期预警: 距离过期小于 72 小时时显示 "即将过期"
  • 乐观 UI 更新: 立即更新 UI,失败时回滚
  • 安全的数字验证: 使用 Number.isFinite() 防止边界情况
  • 状态颜色编码: 🟢 正常 | 🔴 已过期 | 🟡 即将过期 | ⚪ 禁用

Changes

Core Changes

  • Enhanced ProxyAuthenticator with 5 specific error types and detailed messages
  • Added AuthState.errorResponse field for error propagation
  • Added status badge components for user and key expiry states
  • Added getExpiryStatus() and getKeyExpiryStatus() utility functions

Supporting Changes

  • Added i18n translations for active, expired, expiringSoon states in 5 locales
  • Fixed duplicate formatExpiry function definition
  • Added EXPIRING_SOON_MS constant (72 hours) for expiry warning threshold

Codex 审查 ✅

根据 Codex 代码审查修复:

  1. ✅ 删除重复的 formatExpiry 函数
  2. ✅ 改进过期状态验证逻辑
  3. ✅ 统一错误消息语言为中文

Testing

Automated Tests

  • TypeScript type check passed
  • Code formatting completed

Manual Testing

  1. Test authentication with invalid/missing API keys
  2. Verify user list shows correct status badges
  3. Check key status badges display correctly
  4. Verify i18n works across all 5 supported languages
  5. Test 72-hour expiry warning display

Checklist

  • Code follows project conventions
  • Self-review completed
  • Tests pass locally
  • Documentation updated (i18n files)

Description enhanced by Claude AI

NightYu and others added 2 commits December 24, 2025 17:37
主要改动:
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
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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

  • 认证错误优化: 为认证错误提供了 5 种详细的中文错误场景,替换了通用的错误消息,以便用户能更准确地了解问题所在。
  • 用户列表 UI 优化: 在用户列表中添加了用户状态徽章(正常/已过期/即将过期/禁用),将 Provider Group 拆分显示为彩色徽章(最多 2 个 + '+N'),并以 [tag1, tag2] 格式显示用户标签,同时改进了过期时间验证逻辑。
  • 密钥状态优化: 为密钥添加了状态徽章,修复了 formatExpiry 函数重复定义的问题,并正确处理了 '永不过期' 等无法解析的日期文本,Provider Group 也拆分显示(最多 1 个 + '+N')。
  • 国际化支持: 为 5 种语言(中文简体、英文、日文、俄文、中文繁体)添加了 activeexpiredexpiringSoon 等状态的翻译。
  • 技术亮点: 引入了 72 小时过期预警机制,支持乐观 UI 更新,使用 Number.isFinite() 进行安全的数字验证,并对不同状态进行了颜色编码。
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions github-actions bot added the size/M Medium PR (< 500 lines) label Dec 24, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

此拉取请求优化了认证错误消息和用户/密钥状态的 UI 显示,提供了更详细的错误信息和更直观的状态展示。主要改动包括在认证流程中返回 5 种详细的中文错误场景,以及在用户和密钥列表中添加了状态徽章、Provider Group 的彩色徽章显示和用户标签。这些改进显著提升了用户体验和问题排查效率。代码逻辑清晰,特别是对过期时间验证和乐观 UI 更新的处理。唯一需要改进的地方是部分辅助函数存在重复定义,建议进行统一管理。

};
}

const EXPIRING_SOON_MS = 72 * 60 * 60 * 1000; // 72小时
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

常量 EXPIRING_SOON_MSuser-key-table-row.tsx 中也有定义。为了避免重复和确保一致性,建议将其提取到一个共享的工具文件中(例如 src/lib/constants.tssrc/lib/utils/time.ts)。

Comment on lines 97 to 101
function splitGroups(value?: string | null): string[] {
return (value ?? "")
.split(",")
.map((g) => g.trim())
.filter(Boolean);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

函数 splitGroupsuser-key-table-row.tsx 中也有定义。为了避免重复和确保一致性,建议将其提取到一个共享的工具文件中(例如 src/lib/utils/array.tssrc/lib/utils/string.ts)。

}

const DEFAULT_GRID_COLUMNS_CLASS = "grid-cols-[minmax(260px,1fr)_120px_repeat(6,90px)_80px]";
const EXPIRING_SOON_MS = 72 * 60 * 60 * 1000; // 72小时
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

常量 EXPIRING_SOON_MSkey-row-item.tsx 中也有定义。为了避免重复和确保一致性,建议将其提取到一个共享的工具文件中(例如 src/lib/constants.tssrc/lib/utils/time.ts)。

Comment on lines +73 to +77
function splitGroups(value?: string | null): string[] {
return (value ?? "")
.split(",")
.map((g) => g.trim())
.filter(Boolean);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

函数 splitGroupskey-row-item.tsx 中也有定义。为了避免重复和确保一致性,建议将其提取到一个共享的工具文件中(例如 src/lib/utils/array.tssrc/lib/utils/string.ts)。

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

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

  1. Auth Error Handling (auth-guard.ts): The new errorResponse field in AuthState properly propagates detailed error messages. All error paths include logging and return appropriate 401 responses with specific error types.

  2. Expiry Status Logic (getExpiryStatus, getKeyExpiryStatus): Proper validation using Number.isFinite() to handle edge cases. The 72-hour warning threshold follows existing patterns in the codebase.

  3. i18n Completeness: All 5 locales (en, ja, ru, zh-CN, zh-TW) have been updated with the new status translations.

  4. 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 密钥。",
Copy link
Contributor

Choose a reason for hiding this comment

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

[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 密钥无效。提供的密钥不存在或已被删除。",
Copy link
Contributor

Choose a reason for hiding this comment

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

[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 = truekeys.expiresAt > now,因此密钥被禁用或已过期也会触发该分支,导致用户排查方向错误。

Suggested fix:

errorResponse: ProxyResponses.buildError(
  401,
  "API 密钥无效。提供的密钥不存在、已被删除、已被禁用或已过期。",
  "invalid_api_key"
),

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

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:63 Missing-credentials message doesn’t specify Authorization: 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

@ding113 ding113 merged commit 5a52c1f into dev Dec 24, 2025
18 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Dec 24, 2025
@NightYuYyy NightYuYyy deleted the feat/issue-425-auth-error-ui-optimization branch December 26, 2025 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n area:session area:UI enhancement New feature or request size/M Medium PR (< 500 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants