fix(groups): 校验协议变更后的用量注入配置

This commit is contained in:
tbphp committed 2026-08-01 10:45:22 +08:00
1 parent f74437d57f
commit 92ad16068a
2 files changed
+56 -4

No files matched your search

+17 -4
View File
@@ -246,13 +246,12 @@ func (s *Service) UpdateGroupSettings(
updates["weight_manual"] = normalized.weightManual
}
if normalized.overridesSet {
if _, injectUsageOptionsSet := normalized.overrides[state.SettingInjectUsageOptions]; injectUsageOptionsSet &&
!groupSupportsOpenAICompletions(group.Protocols) {
return app_errors.ErrValidation
}
group.Config = normalized.encodedOverrides
updates["config"] = group.Config
}
if err := validateGroupInjectUsageOptionsConstraint(group); err != nil {
return err
}
if err := validateGroupRowCandidate(ctx, tx, group); err != nil {
return app_errors.ErrValidation
}
@@ -280,6 +279,20 @@ func (s *Service) UpdateGroupSettings(
return result, nil
}
func validateGroupInjectUsageOptionsConstraint(group models.Group) error {
settings := make(config.Settings)
if len(group.Config) > 0 {
if err := decodeGroupDiscoveryJSON(group.Config, &settings); err != nil {
return app_errors.ErrValidation
}
}
if _, injectUsageOptionsSet := settings[state.SettingInjectUsageOptions]; injectUsageOptionsSet &&
!groupSupportsOpenAICompletions(group.Protocols) {
return app_errors.ErrValidation
}
return nil
}
func groupSupportsOpenAICompletions(raw models.JSON) bool {
var protocols []protocol.Protocol
if err := decodeGroupDiscoveryJSON(raw, &protocols); err != nil {
+39
View File
@@ -160,6 +160,45 @@ func TestUpdateGroupSettingsValidatesWeightInjectUsageAndUpstreamConfirmation(t
}
}
func TestUpdateGroupSettingsRejectsProtocolChangeThatLeavesInjectUsageOptionsOnNonOpenAIGroup(t *testing.T) {
fixture := newServiceFixture(t)
created, err := fixture.service.CreateGroup(t.Context(), GroupCreateRequest{
UpstreamURL: "https://settings-protocol-constraint.example.com/v1",
Protocols: []protocol.Protocol{protocol.OpenAICompletions},
Config: config.Settings{
state.SettingInjectUsageOptions: true,
},
Keys: "sk-settings-protocol-constraint",
})
if err != nil {
t.Fatalf("CreateGroup() error = %v", err)
}
var before models.Group
if err := fixture.db.First(&before, created.GroupID).Error; err != nil {
t.Fatal(err)
}
beforeRevision := fixture.manager.Current().Revision
_, err = fixture.service.UpdateGroupSettings(t.Context(), created.GroupID, GroupSettingsUpdateRequest{
Protocols: optionalField[[]protocol.Protocol]{
Set: true, Value: []protocol.Protocol{protocol.Anthropic},
},
})
if !errors.Is(err, app_errors.ErrValidation) {
t.Fatalf("UpdateGroupSettings() error = %v, want validation", err)
}
var after models.Group
if err := fixture.db.First(&after, created.GroupID).Error; err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(after, before) {
t.Fatalf("protocol constraint changed persisted group: got=%#v want=%#v", after, before)
}
if got := fixture.manager.Current().Revision; got != beforeRevision {
t.Fatalf("protocol constraint published revision %d, want %d", got, beforeRevision)
}
}
func TestGroupSettingsHTTPRejectsStrictJSONAndUnauthorizedWithoutMutation(t *testing.T) {
initControlI18n(t)
fixture := newServiceFixture(t)