fix settings auth source default persistence
This commit is contained in:
@@ -1011,10 +1011,6 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}(),
|
||||
}
|
||||
|
||||
if err := h.settingService.UpdateSettings(c.Request.Context(), settings); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
authSourceDefaults := &service.AuthSourceDefaultSettings{
|
||||
Email: service.ProviderDefaultGrantSettings{
|
||||
Balance: float64ValueOrDefault(req.AuthSourceDefaultEmailBalance, previousAuthSourceDefaults.Email.Balance),
|
||||
@@ -1046,7 +1042,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
},
|
||||
ForceEmailOnThirdPartySignup: boolValueOrDefault(req.ForceEmailOnThirdPartySignup, previousAuthSourceDefaults.ForceEmailOnThirdPartySignup),
|
||||
}
|
||||
if err := h.settingService.UpdateAuthSourceDefaultSettings(c.Request.Context(), authSourceDefaults); err != nil {
|
||||
if err := h.settingService.UpdateSettingsWithAuthSourceDefaults(c.Request.Context(), settings, authSourceDefaults); err != nil {
|
||||
response.ErrorFrom(c, err)
|
||||
return
|
||||
}
|
||||
@@ -1086,7 +1082,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
h.auditSettingsUpdate(c, previousSettings, settings, req)
|
||||
h.auditSettingsUpdate(c, previousSettings, settings, previousAuthSourceDefaults, authSourceDefaults, req)
|
||||
|
||||
// 重新获取设置返回
|
||||
updatedSettings, err := h.settingService.GetAllSettings(c.Request.Context())
|
||||
@@ -1245,12 +1241,12 @@ func hasPaymentFields(req UpdateSettingsRequest) bool {
|
||||
req.PaymentCancelRateLimitUnit != nil || req.PaymentCancelRateLimitMode != nil
|
||||
}
|
||||
|
||||
func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) {
|
||||
func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.SystemSettings, after *service.SystemSettings, beforeAuthSourceDefaults *service.AuthSourceDefaultSettings, afterAuthSourceDefaults *service.AuthSourceDefaultSettings, req UpdateSettingsRequest) {
|
||||
if before == nil || after == nil {
|
||||
return
|
||||
}
|
||||
|
||||
changed := diffSettings(before, after, req)
|
||||
changed := diffSettings(before, after, beforeAuthSourceDefaults, afterAuthSourceDefaults, req)
|
||||
if len(changed) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -1265,7 +1261,7 @@ func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.Sys
|
||||
)
|
||||
}
|
||||
|
||||
func diffSettings(before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) []string {
|
||||
func diffSettings(before *service.SystemSettings, after *service.SystemSettings, beforeAuthSourceDefaults *service.AuthSourceDefaultSettings, afterAuthSourceDefaults *service.AuthSourceDefaultSettings, req UpdateSettingsRequest) []string {
|
||||
changed := make([]string, 0, 20)
|
||||
if before.RegistrationEnabled != after.RegistrationEnabled {
|
||||
changed = append(changed, "registration_enabled")
|
||||
@@ -1535,6 +1531,50 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
|
||||
if !equalNotifyEmailEntries(before.AccountQuotaNotifyEmails, after.AccountQuotaNotifyEmails) {
|
||||
changed = append(changed, "account_quota_notify_emails")
|
||||
}
|
||||
changed = appendAuthSourceDefaultChanges(changed, beforeAuthSourceDefaults, afterAuthSourceDefaults)
|
||||
return changed
|
||||
}
|
||||
|
||||
func appendAuthSourceDefaultChanges(changed []string, before *service.AuthSourceDefaultSettings, after *service.AuthSourceDefaultSettings) []string {
|
||||
if before == nil {
|
||||
before = &service.AuthSourceDefaultSettings{}
|
||||
}
|
||||
if after == nil {
|
||||
after = &service.AuthSourceDefaultSettings{}
|
||||
}
|
||||
|
||||
type providerDefaultGrantField struct {
|
||||
name string
|
||||
before service.ProviderDefaultGrantSettings
|
||||
after service.ProviderDefaultGrantSettings
|
||||
}
|
||||
|
||||
fields := []providerDefaultGrantField{
|
||||
{name: "email", before: before.Email, after: after.Email},
|
||||
{name: "linuxdo", before: before.LinuxDo, after: after.LinuxDo},
|
||||
{name: "oidc", before: before.OIDC, after: after.OIDC},
|
||||
{name: "wechat", before: before.WeChat, after: after.WeChat},
|
||||
}
|
||||
for _, field := range fields {
|
||||
if field.before.Balance != field.after.Balance {
|
||||
changed = append(changed, "auth_source_default_"+field.name+"_balance")
|
||||
}
|
||||
if field.before.Concurrency != field.after.Concurrency {
|
||||
changed = append(changed, "auth_source_default_"+field.name+"_concurrency")
|
||||
}
|
||||
if !equalDefaultSubscriptions(field.before.Subscriptions, field.after.Subscriptions) {
|
||||
changed = append(changed, "auth_source_default_"+field.name+"_subscriptions")
|
||||
}
|
||||
if field.before.GrantOnSignup != field.after.GrantOnSignup {
|
||||
changed = append(changed, "auth_source_default_"+field.name+"_grant_on_signup")
|
||||
}
|
||||
if field.before.GrantOnFirstBind != field.after.GrantOnFirstBind {
|
||||
changed = append(changed, "auth_source_default_"+field.name+"_grant_on_first_bind")
|
||||
}
|
||||
}
|
||||
if before.ForceEmailOnThirdPartySignup != after.ForceEmailOnThirdPartySignup {
|
||||
changed = append(changed, "force_email_on_third_party_signup")
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -66,6 +67,58 @@ func (s *settingHandlerRepoStub) Delete(ctx context.Context, key string) error {
|
||||
panic("unexpected Delete call")
|
||||
}
|
||||
|
||||
type failingAuthSourceSettingsRepoStub struct {
|
||||
values map[string]string
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Get(ctx context.Context, key string) (*service.Setting, error) {
|
||||
panic("unexpected Get call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetValue(ctx context.Context, key string) (string, error) {
|
||||
panic("unexpected GetValue call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Set(ctx context.Context, key, value string) error {
|
||||
panic("unexpected Set call")
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetMultiple(ctx context.Context, keys []string) (map[string]string, error) {
|
||||
out := make(map[string]string, len(keys))
|
||||
for _, key := range keys {
|
||||
if value, ok := s.values[key]; ok {
|
||||
out[key] = value
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) SetMultiple(ctx context.Context, settings map[string]string) error {
|
||||
if _, ok := settings[service.SettingKeyAuthSourceDefaultEmailBalance]; ok {
|
||||
return s.err
|
||||
}
|
||||
for key, value := range settings {
|
||||
if s.values == nil {
|
||||
s.values = map[string]string{}
|
||||
}
|
||||
s.values[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) GetAll(ctx context.Context) (map[string]string, error) {
|
||||
out := make(map[string]string, len(s.values))
|
||||
for key, value := range s.values {
|
||||
out[key] = value
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *failingAuthSourceSettingsRepoStub) Delete(ctx context.Context, key string) error {
|
||||
panic("unexpected Delete call")
|
||||
}
|
||||
|
||||
func TestSettingHandler_GetSettings_InjectsAuthSourceDefaults(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &settingHandlerRepoStub{
|
||||
@@ -221,3 +274,73 @@ func TestSettingHandler_UpdateSettings_RejectsInvalidPaymentVisibleMethodSource(
|
||||
require.Equal(t, http.StatusBadRequest, rec.Code)
|
||||
require.NotContains(t, repo.values, service.SettingPaymentVisibleMethodAlipaySource)
|
||||
}
|
||||
|
||||
func TestSettingHandler_UpdateSettings_DoesNotPersistPartialSystemSettingsWhenAuthSourceDefaultsFail(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
repo := &failingAuthSourceSettingsRepoStub{
|
||||
values: map[string]string{
|
||||
service.SettingKeyRegistrationEnabled: "false",
|
||||
service.SettingKeyPromoCodeEnabled: "true",
|
||||
service.SettingKeyAuthSourceDefaultEmailBalance: "9.5",
|
||||
service.SettingKeyAuthSourceDefaultEmailConcurrency: "8",
|
||||
service.SettingKeyAuthSourceDefaultEmailSubscriptions: `[{"group_id":31,"validity_days":15}]`,
|
||||
},
|
||||
err: errors.New("write auth source defaults failed"),
|
||||
}
|
||||
svc := service.NewSettingService(repo, &config.Config{Default: config.DefaultConfig{UserConcurrency: 5}})
|
||||
handler := NewSettingHandler(svc, nil, nil, nil, nil, nil)
|
||||
|
||||
body := map[string]any{
|
||||
"registration_enabled": true,
|
||||
"promo_code_enabled": true,
|
||||
"auth_source_default_email_balance": 12.75,
|
||||
}
|
||||
rawBody, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(rec)
|
||||
c.Request = httptest.NewRequest(http.MethodPut, "/api/v1/admin/settings", bytes.NewReader(rawBody))
|
||||
c.Request.Header.Set("Content-Type", "application/json")
|
||||
|
||||
handler.UpdateSettings(c)
|
||||
|
||||
require.Equal(t, http.StatusInternalServerError, rec.Code)
|
||||
require.Equal(t, "false", repo.values[service.SettingKeyRegistrationEnabled])
|
||||
require.Equal(t, "9.5", repo.values[service.SettingKeyAuthSourceDefaultEmailBalance])
|
||||
}
|
||||
|
||||
func TestDiffSettings_IncludesAuthSourceDefaultsAndForceEmail(t *testing.T) {
|
||||
changed := diffSettings(
|
||||
&service.SystemSettings{},
|
||||
&service.SystemSettings{},
|
||||
&service.AuthSourceDefaultSettings{
|
||||
Email: service.ProviderDefaultGrantSettings{
|
||||
Balance: 0,
|
||||
Concurrency: 5,
|
||||
Subscriptions: nil,
|
||||
GrantOnSignup: true,
|
||||
GrantOnFirstBind: false,
|
||||
},
|
||||
ForceEmailOnThirdPartySignup: false,
|
||||
},
|
||||
&service.AuthSourceDefaultSettings{
|
||||
Email: service.ProviderDefaultGrantSettings{
|
||||
Balance: 12.5,
|
||||
Concurrency: 7,
|
||||
Subscriptions: []service.DefaultSubscriptionSetting{{GroupID: 21, ValidityDays: 30}},
|
||||
GrantOnSignup: false,
|
||||
GrantOnFirstBind: true,
|
||||
},
|
||||
ForceEmailOnThirdPartySignup: true,
|
||||
},
|
||||
UpdateSettingsRequest{},
|
||||
)
|
||||
|
||||
require.Contains(t, changed, "auth_source_default_email_balance")
|
||||
require.Contains(t, changed, "auth_source_default_email_concurrency")
|
||||
require.Contains(t, changed, "auth_source_default_email_subscriptions")
|
||||
require.Contains(t, changed, "auth_source_default_email_grant_on_signup")
|
||||
require.Contains(t, changed, "auth_source_default_email_grant_on_first_bind")
|
||||
require.Contains(t, changed, "force_email_on_third_party_signup")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user