- 29 Dec, 2025 1 commit
-
-
yangjianbo authored
将仓储层/基础设施改为 Ent + 原生 SQL 执行路径,并移除 AutoMigrate 与 GORM 依赖。 重构内容包括: - 仓储层改用 Ent/SQL(含 usage_log/account 等复杂查询),统一错误映射 - 基础设施与 setup 初始化切换为 Ent + SQL migrations - 集成测试与 fixtures 迁移到 Ent 事务模型 - 清理遗留 GORM 模型/依赖,补充迁移与文档说明 - 增加根目录 Makefile 便于前后端编译 测试: - go test -tags unit ./... - go test -tags integration ./...
-
- 28 Dec, 2025 4 commits
-
-
yangjianbo authored
- apiKeyService.GetByKey(...) 返回的“找不到 API key”在这个项目里通常会被翻译成业务错误(比如 service.ErrApiKeyNotFound 这类 ApplicationError),而不是直接把 gorm.ErrRecordNotFound 透传到中 间件层。 - 因此你在中间件里用 errors.Is(err, gorm.ErrRecordNotFound) 去判断“无效 key”,很容易匹配不到(尤其 是:后面加 Redis 缓存、换存储实现、或测试里用 stub repo 时,根本不会出现 gorm 的错误)。 - 匹配不到时就会走到 500 Failed to validate API key,导致无效 API key 被错误地当成服务端故障返回 500(应该是 401)。 修复思路:中间件不要依赖 gorm 的错误,改成判断业务层错误,例如: if errors.Is(err, service.ErrApiKeyNotFound) { abortWithGoogleError(c, 401, "Invalid API key") return } 如果你把 GetByKey 的“not found”统一封装成业务错误,这样才不会被底层实现(gorm/redis/mock)影响。 -
shaw authored
问题:当分配订阅天数过大时,expires_at 年份可能超过 9999, 导致 time.Time JSON 序列化失败(RFC 3339 要求年份 <= 9999), 使后台无法显示和删除异常数据。 修复: - handler 层添加 validity_days 最大值验证(max=36500,即100年) - service 层添加 MaxValidityDays 和 MaxExpiresAt 双重保护 - 启动时自动修复已存在的异常数据(expires_at > 2099年)
-
shaw authored
-
noreply authored
Implement deferred batch update mechanism to reduce database load: - Add DeferredService for batching account last_used_at updates - Add TimingWheelService for efficient recurring task scheduling - Integrate with GatewayService and OpenAIGatewayService - Implement BatchUpdateLastUsed repository method using CASE...WHEN SQL - Fix golangci-lint error: Replace interface{} with any Benefits: - Reduces database writes by batching updates (10-second intervals) - Improves request throughput by deferring non-critical updates - Maintains accurate account usage tracking for scheduling
-
- 27 Dec, 2025 14 commits
-
-
shaw authored
-
shaw authored
-
IanShaw027 authored
- 在stubUsageLogRepo中实现GetUserStatsAggregated方法 - 根据userLogs计算统计数据而不是返回错误 - 修复类型转换问题(int转int64)
-
IanShaw027 authored
-
IanShaw027 authored
- 修复gofmt格式问题 - 为stubUsageLogRepo添加缺失的GetApiKeyStatsAggregated方法
-
IanShaw027 authored
- 优化使用统计处理逻辑 - 增强API密钥仓储层功能 - 改进账户使用服务 - 完善API契约测试覆盖
-
IanShaw027 authored
- 合并多个独立查询为单个SQL查询 - 减少数据库往返次数 - 提升仪表板统计数据获取效率
-
shaw authored
原逻辑先执行 Update 再验证 GroupIDs,如果验证失败会导致账号已更新但返回错误。 现改为先验证分组是否存在,再执行 Update 和 BindGroups。
-
IanShaw authored
-
shaw authored
-
daodao97 authored
-
daodao97 authored
-
IanShaw authored
* feat(frontend): 前端界面优化与使用统计功能增强 主要改动: 1. 表格布局统一优化 - 新增 TablePageLayout 通用布局组件 - 统一所有管理页面的表格样式和交互 - 优化 DataTable、Pagination、Select 等通用组件 2. 使用统计功能增强 - 管理端: 添加完整的筛选和显示功能 - 用户端: 完善 API Key 列显示 - 后端: 优化使用统计数据结构和查询 3. 账户组件优化 - 优化 AccountStatsModal、AccountUsageCell 等组件 - 统一进度条和统计显示样式 4. 其他改进 - 完善中英文国际化 - 统一页面样式和交互体验 - 优化各视图页面的响应式布局 * fix(test): 修复 stubUsageLogRepo.ListWithFilters 测试 stub 测试用例 GET /api/v1/usage 返回 500 是因为 stub 方法未实现, 现在正确返回基于 UserID 过滤的日志数据。 * feat(frontend): 统一日期时间显示格式 **主要改动**: 1. 增强 utils/format.ts: - 新增 formatDateOnly() - 格式: YYYY-MM-DD - 新增 formatDateTime() - 格式: YYYY-MM-DD HH:mm:ss 2. 全局替换视图中的格式化函数: - 移除各视图中的自定义 formatDate 函数 - 统一导入使用 @/utils/format 中的函数 - created_at/updated_at 使用 formatDateTime - expires_at 使用 formatDateOnly 3. 受影响的视图 (8个): - frontend/src/views/user/KeysView.vue - frontend/src/views/user/DashboardView.vue - frontend/src/views/user/UsageView.vue - frontend/src/views/user/RedeemView.vue - frontend/src/views/admin/UsersView.vue - frontend/src/views/admin/UsageView.vue - frontend/src/views/admin/RedeemView.vue - frontend/src/views/admin/SubscriptionsView.vue **效果**: - 日期统一显示为 YYYY-MM-DD - 时间统一显示为 YYYY-MM-DD HH:mm:ss - 提升可维护性,避免格式不一致 * fix(frontend): 补充遗漏的时间格式化统一 **补充修复**(基于 code review 发现的遗漏): 1. 增强 utils/format.ts: - 新增 formatTime() - 格式: HH:mm 2. 修复 4 个遗漏的文件: - src/views/admin/UsersView.vue * 删除 formatExpiresAt(),改用 formatDateTime() * 修复订阅过期时间 tooltip 显示格式不一致问题 - src/views/user/ProfileView.vue * 删除 formatMemberSince(),改用 formatDate(date, 'YYYY-MM') * 统一会员起始时间显示格式 - src/views/user/SubscriptionsView.vue * 修改 formatExpirationDate() 使用 formatDateOnly() * 保留天数计算逻辑 - src/components/account/AccountStatusIndicator.vue * 删除本地 formatTime(),改用 utils/format 中的统一函数 * 修复 rate limit 和 overload 重置时间显示 **验证**: - TypeScript 类型检查通过 ✓ - 前端构建成功 ✓ - 所有剩余的 toLocaleString() 都是数字格式化,属于正确用法 ✓ **效果**: - 订阅过期时间统一为 YYYY-MM-DD HH:mm:ss - 会员起始时间统一为 YYYY-MM - 重置时间统一为 HH:mm - 消除所有不规范的原生 locale 方法调用 -
IanShaw authored
* fix(middleware): 修复 Gemini API Key 认证中间件用户上下文类型错误 修复了 ApiKeyAuthWithSubscriptionGoogle 中间件中设置用户上下文时的类型错误。 **问题:** - 中间件直接设置 `apiKey.User` 对象到上下文 - 导致 handler 中获取 `AuthSubject` 时类型断言失败 - 所有 Gemini v1beta 端点返回 500 "User context not found" **修复:** - 改为设置 `AuthSubject` 结构体,与 `api_key_auth.go` 保持一致 - 添加 `ContextKeyUserRole` 设置以完整支持角色检查 **影响范围:** - Gemini v1beta API 端点 (generateContent, streamGenerateContent) - 使用 Google API Key 认证的所有请求 **测试:** - 验证 Gemini CLI 调用成功返回 200 - 确认用户上下文正确传递到 handler * fix(web): 修复 /responses 端点被前端中间件拦截的问题 - 将 /responses 路径添加到 API 白名单,防止其被当作前端路由处理 - 修复 /responses 端点返回 HTML 而非 API 响应的 BUG - 解决 codex CLI stream 在远程服务器上断开连接的问题 根本原因: 在 6c469b42 提交中添加了 /responses 路由,但未同步更新前端嵌入中间件 的 API 白名单,导致该路由被拦截并返回 index.html 而非 API 响应。
-
- 26 Dec, 2025 21 commits
-
-
IanShaw027 authored
添加对两种 Gemini 响应格式的支持: - AI Studio: `{"candidates": [...]}` - Gemini CLI: `{"response": {"candidates": [...]}}` 通过 unwrap 逻辑自动检测并适配两种格式,确保账号测试功能 对所有 Gemini 账号类型都能正常工作。 合并 PR #43 的剩余功能到 PR #37 -
IanShaw027 authored
修复 golangci-lint 检查失败的问题: - gemini_token_provider.go: 删除 import 后多余空行 - gemini_token_refresher.go: 删除 import 后多余空行 Fixes CI golangci-lint check for PR #37
-
IanShaw027 authored
根据 Gemini CLI 代码审查建议: ## 修改内容 - 将 Gemini OAuth 同步中的 `mergeJSONB` 调用替换为 `mergeMap` - 删除不再使用的 `mergeJSONB` 函数定义 ## 原因 - 其他平台(OpenAI、Anthropic)的账户同步都使用 `mergeMap` - `mergeJSONB` 是为旧的 `model.JSONB` 类型设计,与重构后的架构不一致 - 统一函数命名提高代码可读性和可维护性 ## 影响范围 - backend/internal/service/crs_sync_service.go (4处替换) - backend/internal/service/account.go (删除 mergeJSONB 函数) ## 验证 ✓ 编译通过 ✓ 功能逻辑无变化(mergeMap 和 mergeJSONB 实现相同)
-
IanShaw027 authored
## 主要修改 1. **移除 model 包引用** - 删除所有 `internal/model` 包的 import - 使用 service 包中的类型定义(Account, Platform常量等) 2. **修复类型转换** - JSONB → map[string]any - 添加 mergeJSONB 辅助函数 - 添加 Account.IsGemini() 方法 3. **更新中间件调用** - GetUserFromContext → GetAuthSubjectFromContext - 适配新的并发控制签名(传递 ID 和 Concurrency 而不是完整对象) 4. **修复 handler 层** - 更新 gemini_v1beta_handler.go - 修正 billing 检查和 usage 记录 ## 影响范围 - backend/internal/service/gemini_*.go - backend/internal/service/account_test_service.go - backend/internal/service/crs_sync_service.go - backend/internal/handler/gemini_v1beta_handler.go - backend/internal/handler/gateway_handler.go - backend/internal/handler/admin/account_handler.go
-
shaw authored
修复 PR #36 合并后部分 admin handler 直接返回 service 层对象导致 JSON 字段名为 PascalCase 而非期望的 snake_case 问题。 修复内容: - account_handler: Refresh 接口添加 dto.AccountFromService - openai_oauth_handler: RefreshAccountToken/CreateAccountFromOAuth 添加 dto 转换 - subscription_handler: BulkAssign 添加 dto.BulkAssignResultFromService - usage_handler: List 接口添加 dto.UsageLogFromService 转换 - 新增 dto.BulkAssignResult 类型和对应的 mapper 函数
-
ianshaw authored
部分上游 API 返回的 SSE 格式不符合标准规范: - 标准格式: `data: {...}`(冒号后有空格) - 非标准格式: `data:{...}`(冒号后无空格) 使用预编译正则 `^data:\s*` 统一处理两种格式。 -
Forest authored
-
Forest authored
-
ianshaw authored
- 更新 middleware import 路径到 internal/server/middleware - 修复 api_key_auth_google.go 使用正确的 service 类型 - 更新 router.go 和 http.go 支持 Gemini v1beta 路由 - 在 routes/gateway.go 中添加 Gemini v1beta API 端点 - 在 routes/admin.go 中添加 Gemini OAuth 路由 - 更新 wire.go 添加 GeminiOAuthService cleanup - 重新生成 wire_gen.go
-
ianshaw authored
-
ianshaw authored
Handler 改进: - 添加 GET /api/v1/admin/gemini/oauth/capabilities 接口 - 简化 GenerateAuthURL,redirect_uri 由服务层决定 Repository 改进: - ExchangeCode/RefreshToken 根据 oauthType 选择正确的 OAuth 客户端 - Code Assist 始终使用内置客户端,AI Studio 使用用户配置的客户端
-
ianshaw authored
OAuth 服务改进: - 添加 GetOAuthConfig 返回 AI Studio OAuth 可用性 - Code Assist 强制使用内置 Gemini CLI 客户端 - AI Studio OAuth 要求用户配置自定义 OAuth 客户端 - ExchangeCode/RefreshToken 接口添加 oauthType 参数 - 添加 unauthorized_client 错误的向后兼容重试逻辑 兼容层改进: - 403 重试逻辑仅对 Code Assist OAuth 生效 - 添加 insufficient-scope 错误检测,避免无效重试 - 上游错误消息脱敏处理(隐藏 API key 等敏感信息) - 改进错误提示,显示更多上游错误详情
-
ianshaw authored
- 添加 GeminiCLIOAuthClientID/Secret 常量(Gemini CLI 公开 OAuth 客户端) - 更新 DefaultAIStudioScopes 使用 generative-language.retriever(符合 Google 文档) - EffectiveOAuthConfig 支持自动回退到内置客户端 - 内置客户端自动过滤受限 scope(如 generative-language) - 添加 scope 向后兼容性处理
-
ianshaw authored
适配 main 分支的 ports 目录删除重构: - 将 ports 包中的接口移至 service 包 - 更新 repository 层的导入路径
-
ianshaw authored
- gofmt: 修复 account_handler.go, models.go, gemini_messages_compat_service.go 的格式 - staticcheck ST1005: 将 error strings 改为小写开头
-
ianshaw authored
- gofmt: 修复代码格式问题 - errcheck: 处理 WriteString 和 Close 返回值 - staticcheck: 错误信息改为小写开头 - staticcheck: 移除无效的 nil 检查 - staticcheck: 使用 append 替换循环 - staticcheck: 使用无条件的 TrimPrefix - ineffassign: 移除无效赋值 - unused: 移除未使用的 geminiOAuthService 字段 - 重新生成 wire_gen.go
-
ianshaw authored
- 新增 gemini_v1beta_handler.go: 代理原生 Google API 格式 - 更新 gemini_oauth_handler.go: 移除 redirectUri,新增 oauthType - 更新 account_handler.go: 账户 Handler 增强 - 更新 router.go: 注册 v1beta 路由 - 更新 config.go: Gemini OAuth 通过环境变量配置 - 更新 wire_gen.go: 依赖注入
-
ianshaw authored
- gemini_oauth_service.go: 新增 AI Studio OAuth 类型支持 - gemini_token_provider.go: Token 提供器增强 - gemini_messages_compat_service.go: 支持 AI Studio 端点 - account_test_service.go: Gemini 账户可用性检测 - gateway_service.go: 网关服务适配 - openai_gateway_service.go: OpenAI 兼容层调整
-
ianshaw authored
- 更新 gemini_oauth_client.go: 支持 AI Studio OAuth 客户端 - 更新 geminicli_codeassist_client.go: 适配新的认证流程
-
ianshaw authored
- 新增 api_key_auth_google.go: 支持 x-goog-api-key 格式认证 - 更新 api_key_auth.go: 适配 Gemini 原生 API 格式
-
ianshaw authored
- 新增 pkg/gemini: 模型定义与回退列表 - 新增 pkg/googleapi: Google API 错误状态处理 - 新增 pkg/geminicli/models.go: CLI 模型结构 - 更新 constants.go: AI Studio 相关常量 - 更新 oauth.go: 支持 AI Studio OAuth 流程,凭据通过环境变量配置
-