fix(分组): 强化上下文分组可信校验
- 引入 Hydrated 标记限制复用来源 - 无效上下文分组允许被新值覆盖自愈 - 更新相关单测覆盖
This commit is contained in:
@@ -317,6 +317,7 @@ func groupEntityToService(g *dbent.Group) *service.Group {
|
|||||||
RateMultiplier: g.RateMultiplier,
|
RateMultiplier: g.RateMultiplier,
|
||||||
IsExclusive: g.IsExclusive,
|
IsExclusive: g.IsExclusive,
|
||||||
Status: g.Status,
|
Status: g.Status,
|
||||||
|
Hydrated: true,
|
||||||
SubscriptionType: g.SubscriptionType,
|
SubscriptionType: g.SubscriptionType,
|
||||||
DailyLimitUSD: g.DailyLimitUsd,
|
DailyLimitUSD: g.DailyLimitUsd,
|
||||||
WeeklyLimitUSD: g.WeeklyLimitUsd,
|
WeeklyLimitUSD: g.WeeklyLimitUsd,
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ func setGroupContext(c *gin.Context, group *service.Group) {
|
|||||||
if !service.IsGroupContextValid(group) {
|
if !service.IsGroupContextValid(group) {
|
||||||
return
|
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
|
return
|
||||||
}
|
}
|
||||||
ctx := context.WithValue(c.Request.Context(), ctxkey.Group, group)
|
ctx := context.WithValue(c.Request.Context(), ctxkey.Group, group)
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ func TestApiKeyAuthWithSubscriptionGoogleSetsGroupContext(t *testing.T) {
|
|||||||
Name: "g1",
|
Name: "g1",
|
||||||
Status: service.StatusActive,
|
Status: service.StatusActive,
|
||||||
Platform: service.PlatformGemini,
|
Platform: service.PlatformGemini,
|
||||||
|
Hydrated: true,
|
||||||
}
|
}
|
||||||
user := &service.User{
|
user := &service.User{
|
||||||
ID: 7,
|
ID: 7,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ func TestSimpleModeBypassesQuotaCheck(t *testing.T) {
|
|||||||
ID: 42,
|
ID: 42,
|
||||||
Name: "sub",
|
Name: "sub",
|
||||||
Status: service.StatusActive,
|
Status: service.StatusActive,
|
||||||
|
Hydrated: true,
|
||||||
SubscriptionType: service.SubscriptionTypeSubscription,
|
SubscriptionType: service.SubscriptionTypeSubscription,
|
||||||
DailyLimitUSD: &limit,
|
DailyLimitUSD: &limit,
|
||||||
}
|
}
|
||||||
@@ -119,6 +120,7 @@ func TestAPIKeyAuthSetsGroupContext(t *testing.T) {
|
|||||||
Name: "g1",
|
Name: "g1",
|
||||||
Status: service.StatusActive,
|
Status: service.StatusActive,
|
||||||
Platform: service.PlatformAnthropic,
|
Platform: service.PlatformAnthropic,
|
||||||
|
Hydrated: true,
|
||||||
}
|
}
|
||||||
user := &service.User{
|
user := &service.User{
|
||||||
ID: 7,
|
ID: 7,
|
||||||
|
|||||||
@@ -1072,6 +1072,7 @@ func TestGatewayService_GroupResolution_ReusesContextGroup(t *testing.T) {
|
|||||||
ID: groupID,
|
ID: groupID,
|
||||||
Platform: PlatformAnthropic,
|
Platform: PlatformAnthropic,
|
||||||
Status: StatusActive,
|
Status: StatusActive,
|
||||||
|
Hydrated: true,
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, ctxkey.Group, group)
|
ctx = context.WithValue(ctx, ctxkey.Group, group)
|
||||||
|
|
||||||
@@ -1106,8 +1107,9 @@ func TestGatewayService_GroupResolution_IgnoresInvalidContextGroup(t *testing.T)
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
groupID := int64(42)
|
groupID := int64(42)
|
||||||
ctxGroup := &Group{
|
ctxGroup := &Group{
|
||||||
ID: groupID,
|
ID: groupID,
|
||||||
Status: StatusActive,
|
Platform: PlatformAnthropic,
|
||||||
|
Status: StatusActive,
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, ctxkey.Group, ctxGroup)
|
ctx = context.WithValue(ctx, ctxkey.Group, ctxGroup)
|
||||||
|
|
||||||
@@ -1153,6 +1155,7 @@ func TestGatewayService_GroupResolution_FallbackUsesLiteOnce(t *testing.T) {
|
|||||||
Status: StatusActive,
|
Status: StatusActive,
|
||||||
ClaudeCodeOnly: true,
|
ClaudeCodeOnly: true,
|
||||||
FallbackGroupID: &fallbackID,
|
FallbackGroupID: &fallbackID,
|
||||||
|
Hydrated: true,
|
||||||
}
|
}
|
||||||
fallbackGroup := &Group{
|
fallbackGroup := &Group{
|
||||||
ID: fallbackID,
|
ID: fallbackID,
|
||||||
|
|||||||
@@ -643,7 +643,7 @@ func (s *GatewayService) withGroupContext(ctx context.Context, group *Group) con
|
|||||||
if !IsGroupContextValid(group) {
|
if !IsGroupContextValid(group) {
|
||||||
return ctx
|
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 ctx
|
||||||
}
|
}
|
||||||
return context.WithValue(ctx, ctxkey.Group, group)
|
return context.WithValue(ctx, ctxkey.Group, group)
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ func TestGeminiMessagesCompatService_GroupResolution_ReusesContextGroup(t *testi
|
|||||||
ID: groupID,
|
ID: groupID,
|
||||||
Platform: PlatformGemini,
|
Platform: PlatformGemini,
|
||||||
Status: StatusActive,
|
Status: StatusActive,
|
||||||
|
Hydrated: true,
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, ctxkey.Group, group)
|
ctx = context.WithValue(ctx, ctxkey.Group, group)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ type Group struct {
|
|||||||
RateMultiplier float64
|
RateMultiplier float64
|
||||||
IsExclusive bool
|
IsExclusive bool
|
||||||
Status string
|
Status string
|
||||||
|
Hydrated bool // indicates the group was loaded from a trusted repository source
|
||||||
|
|
||||||
SubscriptionType string
|
SubscriptionType string
|
||||||
DailyLimitUSD *float64
|
DailyLimitUSD *float64
|
||||||
@@ -81,6 +82,9 @@ func IsGroupContextValid(group *Group) bool {
|
|||||||
if group.ID <= 0 {
|
if group.ID <= 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !group.Hydrated {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if group.Platform == "" || group.Status == "" {
|
if group.Platform == "" || group.Status == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user