From 72f78f8a5641156b004b52c4e7878d13b8c217ad Mon Sep 17 00:00:00 2001 From: yangjianbo Date: Sat, 10 Jan 2026 08:40:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=88=86=E7=BB=84):=20=E5=BC=BA=E5=8C=96?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E6=96=87=E5=88=86=E7=BB=84=E5=8F=AF=E4=BF=A1?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 Hydrated 标记限制复用来源 - 无效上下文分组允许被新值覆盖自愈 - 更新相关单测覆盖 --- backend/internal/repository/api_key_repo.go | 1 + backend/internal/server/middleware/api_key_auth.go | 2 +- .../internal/server/middleware/api_key_auth_google_test.go | 1 + backend/internal/server/middleware/api_key_auth_test.go | 2 ++ backend/internal/service/gateway_multiplatform_test.go | 7 +++++-- backend/internal/service/gateway_service.go | 2 +- backend/internal/service/gemini_multiplatform_test.go | 1 + backend/internal/service/group.go | 4 ++++ 8 files changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/internal/repository/api_key_repo.go b/backend/internal/repository/api_key_repo.go index f3b07616..c89b5f0d 100644 --- a/backend/internal/repository/api_key_repo.go +++ b/backend/internal/repository/api_key_repo.go @@ -317,6 +317,7 @@ func groupEntityToService(g *dbent.Group) *service.Group { RateMultiplier: g.RateMultiplier, IsExclusive: g.IsExclusive, Status: g.Status, + Hydrated: true, SubscriptionType: g.SubscriptionType, DailyLimitUSD: g.DailyLimitUsd, WeeklyLimitUSD: g.WeeklyLimitUsd, diff --git a/backend/internal/server/middleware/api_key_auth.go b/backend/internal/server/middleware/api_key_auth.go index bb4f549a..7e5d9747 100644 --- a/backend/internal/server/middleware/api_key_auth.go +++ b/backend/internal/server/middleware/api_key_auth.go @@ -182,7 +182,7 @@ func setGroupContext(c *gin.Context, group *service.Group) { if !service.IsGroupContextValid(group) { return } - if existing, ok := c.Request.Context().Value(ctxkey.Group).(*service.Group); ok && existing != nil && existing.ID == group.ID { + if existing, ok := c.Request.Context().Value(ctxkey.Group).(*service.Group); ok && existing != nil && existing.ID == group.ID && service.IsGroupContextValid(existing) { return } ctx := context.WithValue(c.Request.Context(), ctxkey.Group, group) diff --git a/backend/internal/server/middleware/api_key_auth_google_test.go b/backend/internal/server/middleware/api_key_auth_google_test.go index 6d6ab0fc..07b8e370 100644 --- a/backend/internal/server/middleware/api_key_auth_google_test.go +++ b/backend/internal/server/middleware/api_key_auth_google_test.go @@ -142,6 +142,7 @@ func TestApiKeyAuthWithSubscriptionGoogleSetsGroupContext(t *testing.T) { Name: "g1", Status: service.StatusActive, Platform: service.PlatformGemini, + Hydrated: true, } user := &service.User{ ID: 7, diff --git a/backend/internal/server/middleware/api_key_auth_test.go b/backend/internal/server/middleware/api_key_auth_test.go index 719b5d99..47167cf2 100644 --- a/backend/internal/server/middleware/api_key_auth_test.go +++ b/backend/internal/server/middleware/api_key_auth_test.go @@ -26,6 +26,7 @@ func TestSimpleModeBypassesQuotaCheck(t *testing.T) { ID: 42, Name: "sub", Status: service.StatusActive, + Hydrated: true, SubscriptionType: service.SubscriptionTypeSubscription, DailyLimitUSD: &limit, } @@ -119,6 +120,7 @@ func TestAPIKeyAuthSetsGroupContext(t *testing.T) { Name: "g1", Status: service.StatusActive, Platform: service.PlatformAnthropic, + Hydrated: true, } user := &service.User{ ID: 7, diff --git a/backend/internal/service/gateway_multiplatform_test.go b/backend/internal/service/gateway_multiplatform_test.go index 0b5729fe..5520f78e 100644 --- a/backend/internal/service/gateway_multiplatform_test.go +++ b/backend/internal/service/gateway_multiplatform_test.go @@ -1072,6 +1072,7 @@ func TestGatewayService_GroupResolution_ReusesContextGroup(t *testing.T) { ID: groupID, Platform: PlatformAnthropic, Status: StatusActive, + Hydrated: true, } ctx = context.WithValue(ctx, ctxkey.Group, group) @@ -1106,8 +1107,9 @@ func TestGatewayService_GroupResolution_IgnoresInvalidContextGroup(t *testing.T) ctx := context.Background() groupID := int64(42) ctxGroup := &Group{ - ID: groupID, - Status: StatusActive, + ID: groupID, + Platform: PlatformAnthropic, + Status: StatusActive, } ctx = context.WithValue(ctx, ctxkey.Group, ctxGroup) @@ -1153,6 +1155,7 @@ func TestGatewayService_GroupResolution_FallbackUsesLiteOnce(t *testing.T) { Status: StatusActive, ClaudeCodeOnly: true, FallbackGroupID: &fallbackID, + Hydrated: true, } fallbackGroup := &Group{ ID: fallbackID, diff --git a/backend/internal/service/gateway_service.go b/backend/internal/service/gateway_service.go index 3ab42c3e..7756f1da 100644 --- a/backend/internal/service/gateway_service.go +++ b/backend/internal/service/gateway_service.go @@ -643,7 +643,7 @@ func (s *GatewayService) withGroupContext(ctx context.Context, group *Group) con if !IsGroupContextValid(group) { return ctx } - if existing, ok := ctx.Value(ctxkey.Group).(*Group); ok && existing != nil && existing.ID == group.ID { + if existing, ok := ctx.Value(ctxkey.Group).(*Group); ok && existing != nil && existing.ID == group.ID && IsGroupContextValid(existing) { return ctx } return context.WithValue(ctx, ctxkey.Group, group) diff --git a/backend/internal/service/gemini_multiplatform_test.go b/backend/internal/service/gemini_multiplatform_test.go index 897f3129..9373a8f6 100644 --- a/backend/internal/service/gemini_multiplatform_test.go +++ b/backend/internal/service/gemini_multiplatform_test.go @@ -261,6 +261,7 @@ func TestGeminiMessagesCompatService_GroupResolution_ReusesContextGroup(t *testi ID: groupID, Platform: PlatformGemini, Status: StatusActive, + Hydrated: true, } ctx = context.WithValue(ctx, ctxkey.Group, group) diff --git a/backend/internal/service/group.go b/backend/internal/service/group.go index e148ea00..8e8d47d6 100644 --- a/backend/internal/service/group.go +++ b/backend/internal/service/group.go @@ -10,6 +10,7 @@ type Group struct { RateMultiplier float64 IsExclusive bool Status string + Hydrated bool // indicates the group was loaded from a trusted repository source SubscriptionType string DailyLimitUSD *float64 @@ -81,6 +82,9 @@ func IsGroupContextValid(group *Group) bool { if group.ID <= 0 { return false } + if !group.Hydrated { + return false + } if group.Platform == "" || group.Status == "" { return false }