From 11701e9b5e4e76b4440839f702b2ef2fce3cc9e2 Mon Sep 17 00:00:00 2001 From: erio Date: Tue, 7 Apr 2026 03:05:26 +0800 Subject: [PATCH] fix: guard against accidental payment config wipe + cleanup from review - Skip UpdatePaymentConfig when no payment fields provided (prevents wipe) - Remove unused defaultMinRechargeAmount/defaultMaxRechargeAmount constants - Fix mergeConfig comment to match actual behavior --- backend/cmd/server/VERSION | 2 +- .../internal/handler/admin/setting_handler.go | 16 ++++++++++++++-- .../internal/service/payment_config_service.go | 11 +++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index 9b6805df17..05528b437f 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.108.60 +0.1.108.61 diff --git a/backend/internal/handler/admin/setting_handler.go b/backend/internal/handler/admin/setting_handler.go index 90ef8397e8..634f9e2336 100644 --- a/backend/internal/handler/admin/setting_handler.go +++ b/backend/internal/handler/admin/setting_handler.go @@ -660,8 +660,9 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) { return } - // Update payment configuration (integrated into system settings) - if h.paymentConfigService != nil { + // Update payment configuration (integrated into system settings). + // Skip if no payment fields were provided (prevents accidental wipe). + if h.paymentConfigService != nil && hasPaymentFields(req) { paymentReq := service.UpdatePaymentConfigRequest{ Enabled: req.PaymentEnabled, MinAmount: req.PaymentMinAmount, @@ -780,6 +781,17 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) { }) } +// hasPaymentFields returns true if any payment-related field was explicitly provided. +func hasPaymentFields(req UpdateSettingsRequest) bool { + return req.PaymentEnabled != nil || req.PaymentMinAmount != nil || + req.PaymentMaxAmount != nil || req.PaymentDailyLimit != nil || + req.PaymentOrderTimeoutMin != nil || req.PaymentMaxPendingOrders != nil || + req.PaymentEnabledTypes != nil || req.PaymentBalanceDisabled != nil || + req.PaymentLoadBalanceStrat != nil || req.PaymentProductNamePrefix != nil || + req.PaymentProductNameSuffix != nil || req.PaymentHelpImageURL != nil || + req.PaymentHelpText != nil +} + func (h *SettingHandler) auditSettingsUpdate(c *gin.Context, before *service.SystemSettings, after *service.SystemSettings, req UpdateSettingsRequest) { if before == nil || after == nil { return diff --git a/backend/internal/service/payment_config_service.go b/backend/internal/service/payment_config_service.go index 6a6822b037..674a8e8190 100644 --- a/backend/internal/service/payment_config_service.go +++ b/backend/internal/service/payment_config_service.go @@ -38,10 +38,8 @@ const ( // Default values for payment configuration settings. const ( - defaultMinRechargeAmount = 1 - defaultMaxRechargeAmount = 99999999.99 - defaultOrderTimeoutMin = 30 - defaultMaxPendingOrders = 3 + defaultOrderTimeoutMin = 30 + defaultMaxPendingOrders = 3 ) // PaymentConfig holds the payment system configuration. @@ -464,8 +462,9 @@ func (s *PaymentConfigService) UpdateProviderInstance(ctx context.Context, id in return u.Save(ctx) } -// mergeConfig merges new config with existing config, preserving sensitive -// fields that were not re-submitted (frontend skips masked ••••••••). +// mergeConfig merges new config with existing config. All keys from newConfig +// overwrite existing values (including empty strings to clear a field). +// Keys not present in newConfig are preserved from existing config. func (s *PaymentConfigService) mergeConfig(ctx context.Context, id int64, newConfig map[string]string) (map[string]string, error) { inst, err := s.entClient.PaymentProviderInstance.Get(ctx, id) if err != nil {