api_key_auth_cache.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package service
  2. import "time"
  3. // APIKeyAuthSnapshot API Key 认证缓存快照(仅包含认证所需字段)
  4. type APIKeyAuthSnapshot struct {
  5. Version int `json:"version"`
  6. APIKeyID int64 `json:"api_key_id"`
  7. UserID int64 `json:"user_id"`
  8. GroupID *int64 `json:"group_id,omitempty"`
  9. Name string `json:"name"`
  10. Status string `json:"status"`
  11. IPWhitelist []string `json:"ip_whitelist,omitempty"`
  12. IPBlacklist []string `json:"ip_blacklist,omitempty"`
  13. User APIKeyAuthUserSnapshot `json:"user"`
  14. Group *APIKeyAuthGroupSnapshot `json:"group,omitempty"`
  15. // Quota fields for API Key independent quota feature
  16. Quota float64 `json:"quota"` // Quota limit in USD (0 = unlimited)
  17. QuotaUsed float64 `json:"quota_used"` // Used quota amount
  18. // Expiration field for API Key expiration feature
  19. ExpiresAt *time.Time `json:"expires_at,omitempty"` // Expiration time (nil = never expires)
  20. // Rate limit configuration (only limits, not usage - usage read from Redis at check time)
  21. RateLimit5h float64 `json:"rate_limit_5h"`
  22. RateLimit1d float64 `json:"rate_limit_1d"`
  23. RateLimit7d float64 `json:"rate_limit_7d"`
  24. }
  25. // APIKeyAuthUserSnapshot 用户快照
  26. type APIKeyAuthUserSnapshot struct {
  27. ID int64 `json:"id"`
  28. Status string `json:"status"`
  29. Role string `json:"role"`
  30. Balance float64 `json:"balance"`
  31. Concurrency int `json:"concurrency"`
  32. AllowedGroups []int64 `json:"allowed_groups,omitempty"`
  33. // Balance notification fields (required for CheckBalanceAfterDeduction)
  34. Email string `json:"email"`
  35. Username string `json:"username"`
  36. BalanceNotifyEnabled bool `json:"balance_notify_enabled"`
  37. RestrictPublicGroups bool `json:"restrict_public_groups"`
  38. BalanceNotifyThresholdType string `json:"balance_notify_threshold_type"`
  39. BalanceNotifyThreshold *float64 `json:"balance_notify_threshold,omitempty"`
  40. BalanceNotifyExtraEmails []NotifyEmailEntry `json:"balance_notify_extra_emails,omitempty"`
  41. TotalRecharged float64 `json:"total_recharged"`
  42. // RPMLimit 用户级每分钟请求数上限(0 = 不限制);用于 billing_cache_service.checkRPM 兜底判断。
  43. RPMLimit int `json:"rpm_limit"`
  44. // UserGroupRPMOverride 该 API Key 对应的 (user, group) 专属 RPM 覆盖值。
  45. // nil = 无 override(回退到 group/user 级);0 = 不限流;>0 = 专属上限。
  46. UserGroupRPMOverride *int `json:"user_group_rpm_override,omitempty"`
  47. }
  48. // APIKeyAuthGroupSnapshot 分组快照
  49. type APIKeyAuthGroupSnapshot struct {
  50. SecurityPolicyEnabled bool `json:"security_policy_enabled"`
  51. SecurityPolicyMode string `json:"security_policy_mode"`
  52. SecurityPolicyEmailEnabled bool `json:"security_policy_email_enabled"`
  53. ID int64 `json:"id"`
  54. Name string `json:"name"`
  55. Platform string `json:"platform"`
  56. IsExclusive bool `json:"is_exclusive"`
  57. Status string `json:"status"`
  58. SubscriptionType string `json:"subscription_type"`
  59. RateMultiplier float64 `json:"rate_multiplier"`
  60. DailyLimitUSD *float64 `json:"daily_limit_usd,omitempty"`
  61. WeeklyLimitUSD *float64 `json:"weekly_limit_usd,omitempty"`
  62. MonthlyLimitUSD *float64 `json:"monthly_limit_usd,omitempty"`
  63. AllowImageGeneration bool `json:"allow_image_generation"`
  64. AllowBatchImageGeneration bool `json:"allow_batch_image_generation"`
  65. ImageRateIndependent bool `json:"image_rate_independent"`
  66. ImageRateMultiplier float64 `json:"image_rate_multiplier"`
  67. ImagePrice1K *float64 `json:"image_price_1k,omitempty"`
  68. ImagePrice2K *float64 `json:"image_price_2k,omitempty"`
  69. ImagePrice4K *float64 `json:"image_price_4k,omitempty"`
  70. VideoRateIndependent bool `json:"video_rate_independent"`
  71. VideoRateMultiplier float64 `json:"video_rate_multiplier"`
  72. VideoPrice480P *float64 `json:"video_price_480p,omitempty"`
  73. VideoPrice720P *float64 `json:"video_price_720p,omitempty"`
  74. VideoPrice1080P *float64 `json:"video_price_1080p,omitempty"`
  75. VideoModelPrices map[string]map[string]float64 `json:"video_model_prices,omitempty"`
  76. WebSearchPricePerCall *float64 `json:"web_search_price_per_call,omitempty"`
  77. SearchPricePer1k *float64 `json:"search_price_per_1k,omitempty"`
  78. AudioRealtimePricePerMin *float64 `json:"audio_realtime_price_per_min,omitempty"`
  79. AudioTTSPricePerMillionChars *float64 `json:"audio_tts_price_per_million_chars,omitempty"`
  80. AudioSTTPricePerHour *float64 `json:"audio_stt_price_per_hour,omitempty"`
  81. LongContextPricingEnabled bool `json:"long_context_pricing_enabled"`
  82. ModelPricing []ChannelModelPricing `json:"model_pricing,omitempty"`
  83. ClaudeCodeOnly bool `json:"claude_code_only"`
  84. FallbackGroupID *int64 `json:"fallback_group_id,omitempty"`
  85. FallbackGroupIDOnInvalidRequest *int64 `json:"fallback_group_id_on_invalid_request,omitempty"`
  86. // Model routing is used by gateway account selection, so it must be part of auth cache snapshot.
  87. // Only anthropic groups use these fields; others may leave them empty.
  88. ModelRouting map[string][]int64 `json:"model_routing,omitempty"`
  89. ModelRoutingEnabled bool `json:"model_routing_enabled"`
  90. MCPXMLInject bool `json:"mcp_xml_inject"`
  91. // 支持的模型系列(仅 antigravity 平台使用)
  92. SupportedModelScopes []string `json:"supported_model_scopes,omitempty"`
  93. // OpenAI Messages 调度配置(仅 openai 平台使用)
  94. AllowMessagesDispatch bool `json:"allow_messages_dispatch"`
  95. AllowLive bool `json:"allow_live"`
  96. ForceOpenAIFast bool `json:"force_openai_fast"`
  97. FreeOpenAIFast bool `json:"free_openai_fast"`
  98. DefaultMappedModel string `json:"default_mapped_model,omitempty"`
  99. MessagesDispatchModelConfig OpenAIMessagesDispatchModelConfig `json:"messages_dispatch_model_config,omitempty"`
  100. ModelAllowlist GroupModelAllowlist `json:"model_allowlist,omitempty"`
  101. // CodexModelsManifestConfig 与 ModelAllowlist 一样在认证快照分组里透传,
  102. // Codex /models handler 直接读认证分组对象。
  103. CodexModelsManifestConfig GroupCodexModelsManifestConfig `json:"codex_models_manifest_config,omitempty"`
  104. // RPMLimit 分组级每分钟请求数上限(0 = 不限制);用于 billing_cache_service.checkRPM 级联判断。
  105. RPMLimit int `json:"rpm_limit"`
  106. // MaxReasoningEffort Anthropic/OpenAI 请求的推理强度上限,空字符串表示不限制。
  107. MaxReasoningEffort string `json:"max_reasoning_effort,omitempty"`
  108. // MaxReasoningEffortOverLimit 超过上限时的访问控制:downgrade(默认)或 deny。
  109. MaxReasoningEffortOverLimit string `json:"max_reasoning_effort_over_limit,omitempty"`
  110. // ReasoningEffortMappings rewrites explicit effort values before the ceiling.
  111. ReasoningEffortMappings []ReasoningEffortMapping `json:"reasoning_effort_mappings"`
  112. // 高峰时段倍率:PeakRateEnabled 为 true 且请求时刻处于 [PeakStart, PeakEnd) 时,
  113. // token 计费倍率额外乘以 PeakRateMultiplier(详见 Group.PeakMultiplierAt)。
  114. // 必须随快照缓存,否则扣费路径拿到的 apiKey.Group 缺字段、高峰倍率失效。
  115. PeakRateEnabled bool `json:"peak_rate_enabled"`
  116. PeakStart string `json:"peak_start"`
  117. PeakEnd string `json:"peak_end"`
  118. PeakRateMultiplier float64 `json:"peak_rate_multiplier"`
  119. // 分组利润控制:调度准入门在直连热路径上读的就是这份快照——门解析
  120. // (resolveOpenAIProfitControlGate / resolveProfitControlGroup)优先取
  121. // 认证中间件放入 ctx 的 Group,而它正是本快照物化出来的对象,生产绝大
  122. // 多数流量走的都是这条路;只有 composite/模型路由等被调度分组与认证分组
  123. // 不一致时才回源 schedulerSnapshot。
  124. // 因此这三个字段与 GetByKeyForAuth 的投影都不得删减:漏掉任何一个,
  125. // 门会拿到零值 ProfitControlEnabled=false 而静默失效(有集成测试兜底)。
  126. ProfitControlEnabled bool `json:"profit_control_enabled"`
  127. ProfitMinMargin float64 `json:"profit_min_margin"`
  128. ProfitSafetyBuffer float64 `json:"profit_safety_buffer"`
  129. }
  130. // APIKeyAuthCacheEntry 缓存条目,支持负缓存
  131. type APIKeyAuthCacheEntry struct {
  132. NotFound bool `json:"not_found"`
  133. Snapshot *APIKeyAuthSnapshot `json:"snapshot,omitempty"`
  134. }