Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
2cebb0dc
Commit
2cebb0dc
authored
Apr 21, 2026
by
IanShaw027
Browse files
feat(settings): support dual-mode wechat oauth defaults
parent
17c6348b
Changes
15
Hide whitespace changes
Inline
Side-by-side
backend/internal/handler/admin/setting_handler.go
View file @
2cebb0dc
...
@@ -125,6 +125,8 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
...
@@ -125,6 +125,8 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
WeChatConnectEnabled
:
settings
.
WeChatConnectEnabled
,
WeChatConnectEnabled
:
settings
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
settings
.
WeChatConnectAppID
,
WeChatConnectAppID
:
settings
.
WeChatConnectAppID
,
WeChatConnectAppSecretConfigured
:
settings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectAppSecretConfigured
:
settings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectOpenEnabled
:
settings
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
settings
.
WeChatConnectMPEnabled
,
WeChatConnectMode
:
settings
.
WeChatConnectMode
,
WeChatConnectMode
:
settings
.
WeChatConnectMode
,
WeChatConnectScopes
:
settings
.
WeChatConnectScopes
,
WeChatConnectScopes
:
settings
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
settings
.
WeChatConnectRedirectURL
,
WeChatConnectRedirectURL
:
settings
.
WeChatConnectRedirectURL
,
...
@@ -257,6 +259,8 @@ type UpdateSettingsRequest struct {
...
@@ -257,6 +259,8 @@ type UpdateSettingsRequest struct {
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppSecret
string
`json:"wechat_connect_app_secret"`
WeChatConnectAppSecret
string
`json:"wechat_connect_app_secret"`
WeChatConnectOpenEnabled
bool
`json:"wechat_connect_open_enabled"`
WeChatConnectMPEnabled
bool
`json:"wechat_connect_mp_enabled"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
...
@@ -544,17 +548,35 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
...
@@ -544,17 +548,35 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
}
}
req
.
WeChatConnectAppSecret
=
previousSettings
.
WeChatConnectAppSecret
req
.
WeChatConnectAppSecret
=
previousSettings
.
WeChatConnectAppSecret
}
}
if
req
.
WeChatConnectMode
==
""
{
if
req
.
WeChatConnectMode
!=
""
{
req
.
WeChatConnectMode
=
"open"
switch
req
.
WeChatConnectMode
{
case
"open"
,
"mp"
:
default
:
response
.
BadRequest
(
c
,
"WeChat mode must be open or mp"
)
return
}
}
}
switch
req
.
WeChatConnectMode
{
if
!
req
.
WeChatConnectOpenEnabled
&&
!
req
.
WeChatConnectMPEnabled
{
case
"open"
,
"mp"
:
switch
req
.
WeChatConnectMode
{
default
:
case
"mp"
:
response
.
BadRequest
(
c
,
"WeChat mode must be open or mp"
)
req
.
WeChatConnectMPEnabled
=
true
return
default
:
req
.
WeChatConnectOpenEnabled
=
true
}
}
if
req
.
WeChatConnectMode
==
""
{
if
req
.
WeChatConnectMPEnabled
{
req
.
WeChatConnectMode
=
"mp"
}
else
{
req
.
WeChatConnectMode
=
"open"
}
}
}
if
req
.
WeChatConnectScopes
==
""
{
if
req
.
WeChatConnectScopes
==
""
{
req
.
WeChatConnectScopes
=
service
.
DefaultWeChatConnectScopesForMode
(
req
.
WeChatConnectMode
)
if
req
.
WeChatConnectMPEnabled
{
req
.
WeChatConnectScopes
=
service
.
DefaultWeChatConnectScopesForMode
(
"mp"
)
}
else
{
req
.
WeChatConnectScopes
=
service
.
DefaultWeChatConnectScopesForMode
(
req
.
WeChatConnectMode
)
}
}
}
if
req
.
WeChatConnectRedirectURL
==
""
{
if
req
.
WeChatConnectRedirectURL
==
""
{
response
.
BadRequest
(
c
,
"WeChat Redirect URL is required when enabled"
)
response
.
BadRequest
(
c
,
"WeChat Redirect URL is required when enabled"
)
...
@@ -924,6 +946,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
...
@@ -924,6 +946,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
WeChatConnectEnabled
:
req
.
WeChatConnectEnabled
,
WeChatConnectEnabled
:
req
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
req
.
WeChatConnectAppID
,
WeChatConnectAppID
:
req
.
WeChatConnectAppID
,
WeChatConnectAppSecret
:
req
.
WeChatConnectAppSecret
,
WeChatConnectAppSecret
:
req
.
WeChatConnectAppSecret
,
WeChatConnectOpenEnabled
:
req
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
req
.
WeChatConnectMPEnabled
,
WeChatConnectMode
:
req
.
WeChatConnectMode
,
WeChatConnectMode
:
req
.
WeChatConnectMode
,
WeChatConnectScopes
:
req
.
WeChatConnectScopes
,
WeChatConnectScopes
:
req
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
req
.
WeChatConnectRedirectURL
,
WeChatConnectRedirectURL
:
req
.
WeChatConnectRedirectURL
,
...
@@ -1210,6 +1234,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
...
@@ -1210,6 +1234,8 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
WeChatConnectEnabled
:
updatedSettings
.
WeChatConnectEnabled
,
WeChatConnectEnabled
:
updatedSettings
.
WeChatConnectEnabled
,
WeChatConnectAppID
:
updatedSettings
.
WeChatConnectAppID
,
WeChatConnectAppID
:
updatedSettings
.
WeChatConnectAppID
,
WeChatConnectAppSecretConfigured
:
updatedSettings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectAppSecretConfigured
:
updatedSettings
.
WeChatConnectAppSecretConfigured
,
WeChatConnectOpenEnabled
:
updatedSettings
.
WeChatConnectOpenEnabled
,
WeChatConnectMPEnabled
:
updatedSettings
.
WeChatConnectMPEnabled
,
WeChatConnectMode
:
updatedSettings
.
WeChatConnectMode
,
WeChatConnectMode
:
updatedSettings
.
WeChatConnectMode
,
WeChatConnectScopes
:
updatedSettings
.
WeChatConnectScopes
,
WeChatConnectScopes
:
updatedSettings
.
WeChatConnectScopes
,
WeChatConnectRedirectURL
:
updatedSettings
.
WeChatConnectRedirectURL
,
WeChatConnectRedirectURL
:
updatedSettings
.
WeChatConnectRedirectURL
,
...
@@ -1416,6 +1442,12 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
...
@@ -1416,6 +1442,12 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
if
req
.
WeChatConnectAppSecret
!=
""
{
if
req
.
WeChatConnectAppSecret
!=
""
{
changed
=
append
(
changed
,
"wechat_connect_app_secret"
)
changed
=
append
(
changed
,
"wechat_connect_app_secret"
)
}
}
if
before
.
WeChatConnectOpenEnabled
!=
after
.
WeChatConnectOpenEnabled
{
changed
=
append
(
changed
,
"wechat_connect_open_enabled"
)
}
if
before
.
WeChatConnectMPEnabled
!=
after
.
WeChatConnectMPEnabled
{
changed
=
append
(
changed
,
"wechat_connect_mp_enabled"
)
}
if
before
.
WeChatConnectMode
!=
after
.
WeChatConnectMode
{
if
before
.
WeChatConnectMode
!=
after
.
WeChatConnectMode
{
changed
=
append
(
changed
,
"wechat_connect_mode"
)
changed
=
append
(
changed
,
"wechat_connect_mode"
)
}
}
...
...
backend/internal/handler/dto/settings.go
View file @
2cebb0dc
...
@@ -54,6 +54,8 @@ type SystemSettings struct {
...
@@ -54,6 +54,8 @@ type SystemSettings struct {
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectEnabled
bool
`json:"wechat_connect_enabled"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppID
string
`json:"wechat_connect_app_id"`
WeChatConnectAppSecretConfigured
bool
`json:"wechat_connect_app_secret_configured"`
WeChatConnectAppSecretConfigured
bool
`json:"wechat_connect_app_secret_configured"`
WeChatConnectOpenEnabled
bool
`json:"wechat_connect_open_enabled"`
WeChatConnectMPEnabled
bool
`json:"wechat_connect_mp_enabled"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectMode
string
`json:"wechat_connect_mode"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectScopes
string
`json:"wechat_connect_scopes"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
WeChatConnectRedirectURL
string
`json:"wechat_connect_redirect_url"`
...
...
backend/internal/handler/setting_handler_public_test.go
View file @
2cebb0dc
...
@@ -91,6 +91,8 @@ func TestSettingHandler_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
...
@@ -91,6 +91,8 @@ func TestSettingHandler_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
service
.
SettingKeyWeChatConnectAppSecret
:
"wx-mp-secret"
,
service
.
SettingKeyWeChatConnectAppSecret
:
"wx-mp-secret"
,
service
.
SettingKeyWeChatConnectMode
:
"mp"
,
service
.
SettingKeyWeChatConnectMode
:
"mp"
,
service
.
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
service
.
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
service
.
SettingKeyWeChatConnectOpenEnabled
:
"true"
,
service
.
SettingKeyWeChatConnectMPEnabled
:
"true"
,
service
.
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
service
.
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
service
.
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
service
.
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
},
},
...
@@ -115,6 +117,6 @@ func TestSettingHandler_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
...
@@ -115,6 +117,6 @@ func TestSettingHandler_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
require
.
NoError
(
t
,
json
.
Unmarshal
(
recorder
.
Body
.
Bytes
(),
&
resp
))
require
.
NoError
(
t
,
json
.
Unmarshal
(
recorder
.
Body
.
Bytes
(),
&
resp
))
require
.
Equal
(
t
,
0
,
resp
.
Code
)
require
.
Equal
(
t
,
0
,
resp
.
Code
)
require
.
True
(
t
,
resp
.
Data
.
WeChatOAuthEnabled
)
require
.
True
(
t
,
resp
.
Data
.
WeChatOAuthEnabled
)
require
.
Fals
e
(
t
,
resp
.
Data
.
WeChatOAuthOpenEnabled
)
require
.
Tru
e
(
t
,
resp
.
Data
.
WeChatOAuthOpenEnabled
)
require
.
True
(
t
,
resp
.
Data
.
WeChatOAuthMPEnabled
)
require
.
True
(
t
,
resp
.
Data
.
WeChatOAuthMPEnabled
)
}
}
backend/internal/service/domain_constants.go
View file @
2cebb0dc
...
@@ -115,6 +115,8 @@ const (
...
@@ -115,6 +115,8 @@ const (
SettingKeyWeChatConnectEnabled
=
"wechat_connect_enabled"
SettingKeyWeChatConnectEnabled
=
"wechat_connect_enabled"
SettingKeyWeChatConnectAppID
=
"wechat_connect_app_id"
SettingKeyWeChatConnectAppID
=
"wechat_connect_app_id"
SettingKeyWeChatConnectAppSecret
=
"wechat_connect_app_secret"
SettingKeyWeChatConnectAppSecret
=
"wechat_connect_app_secret"
SettingKeyWeChatConnectOpenEnabled
=
"wechat_connect_open_enabled"
SettingKeyWeChatConnectMPEnabled
=
"wechat_connect_mp_enabled"
SettingKeyWeChatConnectMode
=
"wechat_connect_mode"
SettingKeyWeChatConnectMode
=
"wechat_connect_mode"
SettingKeyWeChatConnectScopes
=
"wechat_connect_scopes"
SettingKeyWeChatConnectScopes
=
"wechat_connect_scopes"
SettingKeyWeChatConnectRedirectURL
=
"wechat_connect_redirect_url"
SettingKeyWeChatConnectRedirectURL
=
"wechat_connect_redirect_url"
...
...
backend/internal/service/payment_order.go
View file @
2cebb0dc
...
@@ -519,7 +519,7 @@ func (s *PaymentService) getWeChatPaymentOAuthCredential(ctx context.Context) (s
...
@@ -519,7 +519,7 @@ func (s *PaymentService) getWeChatPaymentOAuthCredential(ctx context.Context) (s
)
)
}
}
cfg
,
err
:=
(
&
SettingService
{
settingRepo
:
s
.
configService
.
settingRepo
})
.
GetWeChatConnectOAuthConfig
(
ctx
)
cfg
,
err
:=
(
&
SettingService
{
settingRepo
:
s
.
configService
.
settingRepo
})
.
GetWeChatConnectOAuthConfig
(
ctx
)
if
err
!=
nil
||
cfg
.
Mode
!=
"mp"
||
strings
.
TrimSpace
(
cfg
.
AppID
)
==
""
||
strings
.
TrimSpace
(
cfg
.
AppSecret
)
==
""
{
if
err
!=
nil
||
!
cfg
.
SupportsMode
(
"mp"
)
||
strings
.
TrimSpace
(
cfg
.
AppID
)
==
""
||
strings
.
TrimSpace
(
cfg
.
AppSecret
)
==
""
{
return
""
,
""
,
infraerrors
.
ServiceUnavailable
(
return
""
,
""
,
infraerrors
.
ServiceUnavailable
(
"WECHAT_PAYMENT_MP_NOT_CONFIGURED"
,
"WECHAT_PAYMENT_MP_NOT_CONFIGURED"
,
"wechat in-app payment requires a complete WeChat MP OAuth credential"
,
"wechat in-app payment requires a complete WeChat MP OAuth credential"
,
...
...
backend/internal/service/setting_service.go
View file @
2cebb0dc
...
@@ -209,6 +209,39 @@ func normalizeWeChatConnectScopeSetting(raw, mode string) string {
...
@@ -209,6 +209,39 @@ func normalizeWeChatConnectScopeSetting(raw, mode string) string {
}
}
}
}
func
parseWeChatConnectCapabilitySettings
(
settings
map
[
string
]
string
,
enabled
bool
,
mode
string
)
(
bool
,
bool
)
{
mode
=
normalizeWeChatConnectModeSetting
(
mode
)
rawOpen
,
hasOpen
:=
settings
[
SettingKeyWeChatConnectOpenEnabled
]
rawMP
,
hasMP
:=
settings
[
SettingKeyWeChatConnectMPEnabled
]
openConfigured
:=
hasOpen
&&
strings
.
TrimSpace
(
rawOpen
)
!=
""
mpConfigured
:=
hasMP
&&
strings
.
TrimSpace
(
rawMP
)
!=
""
if
openConfigured
||
mpConfigured
{
openEnabled
:=
strings
.
TrimSpace
(
rawOpen
)
==
"true"
mpEnabled
:=
strings
.
TrimSpace
(
rawMP
)
==
"true"
return
openEnabled
,
mpEnabled
}
if
!
enabled
{
return
false
,
false
}
if
mode
==
"mp"
{
return
false
,
true
}
return
true
,
false
}
func
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
bool
,
mode
string
)
string
{
switch
{
case
mpEnabled
:
return
"mp"
case
openEnabled
:
return
"open"
default
:
return
normalizeWeChatConnectModeSetting
(
mode
)
}
}
// NewSettingService 创建系统设置服务实例
// NewSettingService 创建系统设置服务实例
func
NewSettingService
(
settingRepo
SettingRepository
,
cfg
*
config
.
Config
)
*
SettingService
{
func
NewSettingService
(
settingRepo
SettingRepository
,
cfg
*
config
.
Config
)
*
SettingService
{
return
&
SettingService
{
return
&
SettingService
{
...
@@ -277,6 +310,8 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
...
@@ -277,6 +310,8 @@ func (s *SettingService) GetPublicSettings(ctx context.Context) (*PublicSettings
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectOpenEnabled
,
SettingKeyWeChatConnectMPEnabled
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectRedirectURL
,
SettingKeyWeChatConnectRedirectURL
,
...
@@ -475,12 +510,19 @@ func DefaultWeChatConnectScopesForMode(mode string) string {
...
@@ -475,12 +510,19 @@ func DefaultWeChatConnectScopesForMode(mode string) string {
}
}
func
(
s
*
SettingService
)
parseWeChatConnectOAuthConfig
(
settings
map
[
string
]
string
)
(
WeChatConnectOAuthConfig
,
error
)
{
func
(
s
*
SettingService
)
parseWeChatConnectOAuthConfig
(
settings
map
[
string
]
string
)
(
WeChatConnectOAuthConfig
,
error
)
{
enabled
:=
settings
[
SettingKeyWeChatConnectEnabled
]
==
"true"
mode
:=
normalizeWeChatConnectModeSetting
(
settings
[
SettingKeyWeChatConnectMode
])
openEnabled
,
mpEnabled
:=
parseWeChatConnectCapabilitySettings
(
settings
,
enabled
,
mode
)
mode
=
normalizeWeChatConnectStoredMode
(
openEnabled
,
mpEnabled
,
mode
)
cfg
:=
WeChatConnectOAuthConfig
{
cfg
:=
WeChatConnectOAuthConfig
{
Enabled
:
settings
[
SettingKeyWeChatConnectEnabled
]
==
"true"
,
Enabled
:
enabled
,
AppID
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
]),
AppID
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
]),
AppSecret
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
]),
AppSecret
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
]),
Mode
:
normalizeWeChatConnectModeSetting
(
settings
[
SettingKeyWeChatConnectMode
]),
OpenEnabled
:
openEnabled
,
Scopes
:
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
settings
[
SettingKeyWeChatConnectMode
]),
MPEnabled
:
mpEnabled
,
Mode
:
mode
,
Scopes
:
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
mode
),
RedirectURL
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
]),
RedirectURL
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
]),
FrontendRedirectURL
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectFrontendRedirectURL
]),
FrontendRedirectURL
:
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectFrontendRedirectURL
]),
}
}
...
@@ -488,7 +530,7 @@ func (s *SettingService) parseWeChatConnectOAuthConfig(settings map[string]strin
...
@@ -488,7 +530,7 @@ func (s *SettingService) parseWeChatConnectOAuthConfig(settings map[string]strin
cfg
.
FrontendRedirectURL
=
defaultWeChatConnectFrontend
cfg
.
FrontendRedirectURL
=
defaultWeChatConnectFrontend
}
}
if
!
cfg
.
Enabled
{
if
!
cfg
.
Enabled
||
(
!
cfg
.
OpenEnabled
&&
!
cfg
.
MPEnabled
)
{
return
WeChatConnectOAuthConfig
{},
infraerrors
.
NotFound
(
"OAUTH_DISABLED"
,
"wechat oauth is disabled"
)
return
WeChatConnectOAuthConfig
{},
infraerrors
.
NotFound
(
"OAUTH_DISABLED"
,
"wechat oauth is disabled"
)
}
}
if
cfg
.
AppID
==
""
{
if
cfg
.
AppID
==
""
{
...
@@ -517,7 +559,7 @@ func (s *SettingService) weChatOAuthCapabilitiesFromSettings(settings map[string
...
@@ -517,7 +559,7 @@ func (s *SettingService) weChatOAuthCapabilitiesFromSettings(settings map[string
if
err
!=
nil
{
if
err
!=
nil
{
return
false
,
false
,
false
return
false
,
false
,
false
}
}
return
true
,
cfg
.
Mode
==
"open"
,
cfg
.
Mode
==
"mp"
return
true
,
cfg
.
OpenEnabled
,
cfg
.
MPEnabled
}
}
// filterUserVisibleMenuItems filters out admin-only menu items from a raw JSON
// filterUserVisibleMenuItems filters out admin-only menu items from a raw JSON
...
@@ -702,7 +744,11 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
...
@@ -702,7 +744,11 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
settings
.
PaymentVisibleMethodWxpaySource
=
wxpaySource
settings
.
PaymentVisibleMethodWxpaySource
=
wxpaySource
settings
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppID
)
settings
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppID
)
settings
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppSecret
)
settings
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
.
WeChatConnectAppSecret
)
settings
.
WeChatConnectMode
=
normalizeWeChatConnectModeSetting
(
settings
.
WeChatConnectMode
)
settings
.
WeChatConnectMode
=
normalizeWeChatConnectStoredMode
(
settings
.
WeChatConnectOpenEnabled
,
settings
.
WeChatConnectMPEnabled
,
settings
.
WeChatConnectMode
,
)
settings
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
.
WeChatConnectScopes
,
settings
.
WeChatConnectMode
)
settings
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
.
WeChatConnectScopes
,
settings
.
WeChatConnectMode
)
settings
.
WeChatConnectRedirectURL
=
strings
.
TrimSpace
(
settings
.
WeChatConnectRedirectURL
)
settings
.
WeChatConnectRedirectURL
=
strings
.
TrimSpace
(
settings
.
WeChatConnectRedirectURL
)
settings
.
WeChatConnectFrontendRedirectURL
=
strings
.
TrimSpace
(
settings
.
WeChatConnectFrontendRedirectURL
)
settings
.
WeChatConnectFrontendRedirectURL
=
strings
.
TrimSpace
(
settings
.
WeChatConnectFrontendRedirectURL
)
...
@@ -781,6 +827,8 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
...
@@ -781,6 +827,8 @@ func (s *SettingService) buildSystemSettingsUpdates(ctx context.Context, setting
// WeChat Connect OAuth 登录
// WeChat Connect OAuth 登录
updates
[
SettingKeyWeChatConnectEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectEnabled
)
updates
[
SettingKeyWeChatConnectEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectEnabled
)
updates
[
SettingKeyWeChatConnectAppID
]
=
settings
.
WeChatConnectAppID
updates
[
SettingKeyWeChatConnectAppID
]
=
settings
.
WeChatConnectAppID
updates
[
SettingKeyWeChatConnectOpenEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectOpenEnabled
)
updates
[
SettingKeyWeChatConnectMPEnabled
]
=
strconv
.
FormatBool
(
settings
.
WeChatConnectMPEnabled
)
updates
[
SettingKeyWeChatConnectMode
]
=
settings
.
WeChatConnectMode
updates
[
SettingKeyWeChatConnectMode
]
=
settings
.
WeChatConnectMode
updates
[
SettingKeyWeChatConnectScopes
]
=
settings
.
WeChatConnectScopes
updates
[
SettingKeyWeChatConnectScopes
]
=
settings
.
WeChatConnectScopes
updates
[
SettingKeyWeChatConnectRedirectURL
]
=
settings
.
WeChatConnectRedirectURL
updates
[
SettingKeyWeChatConnectRedirectURL
]
=
settings
.
WeChatConnectRedirectURL
...
@@ -1296,6 +1344,8 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
...
@@ -1296,6 +1344,8 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
SettingKeyCustomMenuItems
:
"[]"
,
SettingKeyCustomMenuItems
:
"[]"
,
SettingKeyCustomEndpoints
:
"[]"
,
SettingKeyCustomEndpoints
:
"[]"
,
SettingKeyWeChatConnectEnabled
:
"false"
,
SettingKeyWeChatConnectEnabled
:
"false"
,
SettingKeyWeChatConnectOpenEnabled
:
"false"
,
SettingKeyWeChatConnectMPEnabled
:
"false"
,
SettingKeyWeChatConnectMode
:
"open"
,
SettingKeyWeChatConnectMode
:
"open"
,
SettingKeyWeChatConnectScopes
:
"snsapi_login"
,
SettingKeyWeChatConnectScopes
:
"snsapi_login"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
defaultWeChatConnectFrontend
,
SettingKeyWeChatConnectFrontendRedirectURL
:
defaultWeChatConnectFrontend
,
...
@@ -1307,22 +1357,22 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
...
@@ -1307,22 +1357,22 @@ func (s *SettingService) InitializeDefaultSettings(ctx context.Context) error {
SettingKeyAuthSourceDefaultEmailBalance
:
"0"
,
SettingKeyAuthSourceDefaultEmailBalance
:
"0"
,
SettingKeyAuthSourceDefaultEmailConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultEmailConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultEmailSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultEmailSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultEmailGrantOnSignup
:
"
tru
e"
,
SettingKeyAuthSourceDefaultEmailGrantOnSignup
:
"
fals
e"
,
SettingKeyAuthSourceDefaultEmailGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultEmailGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultLinuxDoBalance
:
"0"
,
SettingKeyAuthSourceDefaultLinuxDoBalance
:
"0"
,
SettingKeyAuthSourceDefaultLinuxDoConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultLinuxDoConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultLinuxDoSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultLinuxDoSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultLinuxDoGrantOnSignup
:
"
tru
e"
,
SettingKeyAuthSourceDefaultLinuxDoGrantOnSignup
:
"
fals
e"
,
SettingKeyAuthSourceDefaultLinuxDoGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultLinuxDoGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultOIDCBalance
:
"0"
,
SettingKeyAuthSourceDefaultOIDCBalance
:
"0"
,
SettingKeyAuthSourceDefaultOIDCConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultOIDCConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultOIDCSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultOIDCSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultOIDCGrantOnSignup
:
"
tru
e"
,
SettingKeyAuthSourceDefaultOIDCGrantOnSignup
:
"
fals
e"
,
SettingKeyAuthSourceDefaultOIDCGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultOIDCGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultWeChatBalance
:
"0"
,
SettingKeyAuthSourceDefaultWeChatBalance
:
"0"
,
SettingKeyAuthSourceDefaultWeChatConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultWeChatConcurrency
:
"5"
,
SettingKeyAuthSourceDefaultWeChatSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultWeChatSubscriptions
:
"[]"
,
SettingKeyAuthSourceDefaultWeChatGrantOnSignup
:
"
tru
e"
,
SettingKeyAuthSourceDefaultWeChatGrantOnSignup
:
"
fals
e"
,
SettingKeyAuthSourceDefaultWeChatGrantOnFirstBind
:
"false"
,
SettingKeyAuthSourceDefaultWeChatGrantOnFirstBind
:
"false"
,
SettingKeyForceEmailOnThirdPartySignup
:
"false"
,
SettingKeyForceEmailOnThirdPartySignup
:
"false"
,
SettingKeySMTPPort
:
"587"
,
SettingKeySMTPPort
:
"587"
,
...
@@ -1595,8 +1645,17 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
...
@@ -1595,8 +1645,17 @@ func (s *SettingService) parseSettings(settings map[string]string) *SystemSettin
result
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
])
result
.
WeChatConnectAppID
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppID
])
result
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
])
result
.
WeChatConnectAppSecret
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectAppSecret
])
result
.
WeChatConnectAppSecretConfigured
=
result
.
WeChatConnectAppSecret
!=
""
result
.
WeChatConnectAppSecretConfigured
=
result
.
WeChatConnectAppSecret
!=
""
result
.
WeChatConnectMode
=
normalizeWeChatConnectModeSetting
(
settings
[
SettingKeyWeChatConnectMode
])
result
.
WeChatConnectOpenEnabled
,
result
.
WeChatConnectMPEnabled
=
parseWeChatConnectCapabilitySettings
(
result
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
settings
[
SettingKeyWeChatConnectMode
])
settings
,
result
.
WeChatConnectEnabled
,
settings
[
SettingKeyWeChatConnectMode
],
)
result
.
WeChatConnectMode
=
normalizeWeChatConnectStoredMode
(
result
.
WeChatConnectOpenEnabled
,
result
.
WeChatConnectMPEnabled
,
settings
[
SettingKeyWeChatConnectMode
],
)
result
.
WeChatConnectScopes
=
normalizeWeChatConnectScopeSetting
(
settings
[
SettingKeyWeChatConnectScopes
],
result
.
WeChatConnectMode
)
result
.
WeChatConnectRedirectURL
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
])
result
.
WeChatConnectRedirectURL
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectRedirectURL
])
result
.
WeChatConnectFrontendRedirectURL
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectFrontendRedirectURL
])
result
.
WeChatConnectFrontendRedirectURL
=
strings
.
TrimSpace
(
settings
[
SettingKeyWeChatConnectFrontendRedirectURL
])
if
result
.
WeChatConnectFrontendRedirectURL
==
""
{
if
result
.
WeChatConnectFrontendRedirectURL
==
""
{
...
@@ -1744,7 +1803,7 @@ func parseProviderDefaultGrantSettings(settings map[string]string, keys authSour
...
@@ -1744,7 +1803,7 @@ func parseProviderDefaultGrantSettings(settings map[string]string, keys authSour
Balance
:
defaultAuthSourceBalance
,
Balance
:
defaultAuthSourceBalance
,
Concurrency
:
defaultAuthSourceConcurrency
,
Concurrency
:
defaultAuthSourceConcurrency
,
Subscriptions
:
[]
DefaultSubscriptionSetting
{},
Subscriptions
:
[]
DefaultSubscriptionSetting
{},
GrantOnSignup
:
tru
e
,
GrantOnSignup
:
fals
e
,
GrantOnFirstBind
:
false
,
GrantOnFirstBind
:
false
,
}
}
...
@@ -2092,6 +2151,8 @@ func (s *SettingService) GetWeChatConnectOAuthConfig(ctx context.Context) (WeCha
...
@@ -2092,6 +2151,8 @@ func (s *SettingService) GetWeChatConnectOAuthConfig(ctx context.Context) (WeCha
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectEnabled
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppID
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectAppSecret
,
SettingKeyWeChatConnectOpenEnabled
,
SettingKeyWeChatConnectMPEnabled
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectMode
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectScopes
,
SettingKeyWeChatConnectRedirectURL
,
SettingKeyWeChatConnectRedirectURL
,
...
...
backend/internal/service/setting_service_auth_source_defaults_test.go
View file @
2cebb0dc
...
@@ -81,10 +81,12 @@ func TestSettingService_GetAuthSourceDefaultSettings_ParsesValuesAndDefaults(t *
...
@@ -81,10 +81,12 @@ func TestSettingService_GetAuthSourceDefaultSettings_ParsesValuesAndDefaults(t *
require
.
Equal
(
t
,
0.0
,
got
.
LinuxDo
.
Balance
)
require
.
Equal
(
t
,
0.0
,
got
.
LinuxDo
.
Balance
)
require
.
Equal
(
t
,
5
,
got
.
LinuxDo
.
Concurrency
)
require
.
Equal
(
t
,
5
,
got
.
LinuxDo
.
Concurrency
)
require
.
Equal
(
t
,
[]
DefaultSubscriptionSetting
{},
got
.
LinuxDo
.
Subscriptions
)
require
.
Equal
(
t
,
[]
DefaultSubscriptionSetting
{},
got
.
LinuxDo
.
Subscriptions
)
require
.
Tru
e
(
t
,
got
.
LinuxDo
.
GrantOnSignup
)
require
.
Fals
e
(
t
,
got
.
LinuxDo
.
GrantOnSignup
)
require
.
True
(
t
,
got
.
LinuxDo
.
GrantOnFirstBind
)
require
.
True
(
t
,
got
.
LinuxDo
.
GrantOnFirstBind
)
require
.
Equal
(
t
,
5
,
got
.
OIDC
.
Concurrency
)
require
.
Equal
(
t
,
5
,
got
.
OIDC
.
Concurrency
)
require
.
Equal
(
t
,
5
,
got
.
WeChat
.
Concurrency
)
require
.
Equal
(
t
,
5
,
got
.
WeChat
.
Concurrency
)
require
.
False
(
t
,
got
.
OIDC
.
GrantOnSignup
)
require
.
False
(
t
,
got
.
WeChat
.
GrantOnSignup
)
require
.
True
(
t
,
got
.
ForceEmailOnThirdPartySignup
)
require
.
True
(
t
,
got
.
ForceEmailOnThirdPartySignup
)
}
}
...
...
backend/internal/service/setting_service_public_test.go
View file @
2cebb0dc
...
@@ -99,6 +99,8 @@ func TestSettingService_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
...
@@ -99,6 +99,8 @@ func TestSettingService_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
SettingKeyWeChatConnectAppSecret
:
"wx-mp-secret"
,
SettingKeyWeChatConnectAppSecret
:
"wx-mp-secret"
,
SettingKeyWeChatConnectMode
:
"mp"
,
SettingKeyWeChatConnectMode
:
"mp"
,
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
SettingKeyWeChatConnectOpenEnabled
:
"true"
,
SettingKeyWeChatConnectMPEnabled
:
"true"
,
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
},
},
...
@@ -107,6 +109,6 @@ func TestSettingService_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
...
@@ -107,6 +109,6 @@ func TestSettingService_GetPublicSettings_ExposesWeChatOAuthModeCapabilities(t *
settings
,
err
:=
svc
.
GetPublicSettings
(
context
.
Background
())
settings
,
err
:=
svc
.
GetPublicSettings
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
True
(
t
,
settings
.
WeChatOAuthEnabled
)
require
.
True
(
t
,
settings
.
WeChatOAuthEnabled
)
require
.
Fals
e
(
t
,
settings
.
WeChatOAuthOpenEnabled
)
require
.
Tru
e
(
t
,
settings
.
WeChatOAuthOpenEnabled
)
require
.
True
(
t
,
settings
.
WeChatOAuthMPEnabled
)
require
.
True
(
t
,
settings
.
WeChatOAuthMPEnabled
)
}
}
backend/internal/service/setting_service_wechat_config_test.go
View file @
2cebb0dc
...
@@ -59,6 +59,8 @@ func TestSettingService_GetWeChatConnectOAuthConfig_UsesDatabaseOverrides(t *tes
...
@@ -59,6 +59,8 @@ func TestSettingService_GetWeChatConnectOAuthConfig_UsesDatabaseOverrides(t *tes
SettingKeyWeChatConnectAppSecret
:
"wx-db-secret"
,
SettingKeyWeChatConnectAppSecret
:
"wx-db-secret"
,
SettingKeyWeChatConnectMode
:
"mp"
,
SettingKeyWeChatConnectMode
:
"mp"
,
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
SettingKeyWeChatConnectScopes
:
"snsapi_base"
,
SettingKeyWeChatConnectOpenEnabled
:
"true"
,
SettingKeyWeChatConnectMPEnabled
:
"true"
,
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
SettingKeyWeChatConnectRedirectURL
:
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
SettingKeyWeChatConnectFrontendRedirectURL
:
"/auth/wechat/callback"
,
},
},
...
@@ -70,6 +72,8 @@ func TestSettingService_GetWeChatConnectOAuthConfig_UsesDatabaseOverrides(t *tes
...
@@ -70,6 +72,8 @@ func TestSettingService_GetWeChatConnectOAuthConfig_UsesDatabaseOverrides(t *tes
require
.
True
(
t
,
got
.
Enabled
)
require
.
True
(
t
,
got
.
Enabled
)
require
.
Equal
(
t
,
"wx-db-app"
,
got
.
AppID
)
require
.
Equal
(
t
,
"wx-db-app"
,
got
.
AppID
)
require
.
Equal
(
t
,
"wx-db-secret"
,
got
.
AppSecret
)
require
.
Equal
(
t
,
"wx-db-secret"
,
got
.
AppSecret
)
require
.
True
(
t
,
got
.
OpenEnabled
)
require
.
True
(
t
,
got
.
MPEnabled
)
require
.
Equal
(
t
,
"mp"
,
got
.
Mode
)
require
.
Equal
(
t
,
"mp"
,
got
.
Mode
)
require
.
Equal
(
t
,
"snsapi_base"
,
got
.
Scopes
)
require
.
Equal
(
t
,
"snsapi_base"
,
got
.
Scopes
)
require
.
Equal
(
t
,
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
got
.
RedirectURL
)
require
.
Equal
(
t
,
"https://api.example.com/api/v1/auth/oauth/wechat/callback"
,
got
.
RedirectURL
)
...
...
backend/internal/service/settings_view.go
View file @
2cebb0dc
...
@@ -36,6 +36,8 @@ type SystemSettings struct {
...
@@ -36,6 +36,8 @@ type SystemSettings struct {
WeChatConnectAppID
string
WeChatConnectAppID
string
WeChatConnectAppSecret
string
WeChatConnectAppSecret
string
WeChatConnectAppSecretConfigured
bool
WeChatConnectAppSecretConfigured
bool
WeChatConnectOpenEnabled
bool
WeChatConnectMPEnabled
bool
WeChatConnectMode
string
WeChatConnectMode
string
WeChatConnectScopes
string
WeChatConnectScopes
string
WeChatConnectRedirectURL
string
WeChatConnectRedirectURL
string
...
@@ -191,12 +193,30 @@ type WeChatConnectOAuthConfig struct {
...
@@ -191,12 +193,30 @@ type WeChatConnectOAuthConfig struct {
Enabled
bool
Enabled
bool
AppID
string
AppID
string
AppSecret
string
AppSecret
string
OpenEnabled
bool
MPEnabled
bool
Mode
string
Mode
string
Scopes
string
Scopes
string
RedirectURL
string
RedirectURL
string
FrontendRedirectURL
string
FrontendRedirectURL
string
}
}
func
(
cfg
WeChatConnectOAuthConfig
)
SupportsMode
(
mode
string
)
bool
{
switch
normalizeWeChatConnectModeSetting
(
mode
)
{
case
"mp"
:
return
cfg
.
MPEnabled
default
:
return
cfg
.
OpenEnabled
}
}
func
(
cfg
WeChatConnectOAuthConfig
)
ScopeForMode
(
mode
string
)
string
{
if
normalizeWeChatConnectModeSetting
(
mode
)
==
"mp"
{
return
normalizeWeChatConnectScopeSetting
(
cfg
.
Scopes
,
"mp"
)
}
return
defaultWeChatConnectScopeForMode
(
"open"
)
}
// StreamTimeoutSettings 流超时处理配置(仅控制超时后的处理方式,超时判定由网关配置控制)
// StreamTimeoutSettings 流超时处理配置(仅控制超时后的处理方式,超时判定由网关配置控制)
type
StreamTimeoutSettings
struct
{
type
StreamTimeoutSettings
struct
{
// Enabled 是否启用流超时处理
// Enabled 是否启用流超时处理
...
...
backend/migrations/118_wechat_dual_mode_and_auth_source_defaults.sql
0 → 100644
View file @
2cebb0dc
INSERT
INTO
settings
(
key
,
value
)
VALUES
(
'wechat_connect_open_enabled'
,
CASE
WHEN
COALESCE
((
SELECT
value
FROM
settings
WHERE
key
=
'wechat_connect_enabled'
),
'false'
)
<>
'true'
THEN
'false'
WHEN
LOWER
(
TRIM
(
COALESCE
((
SELECT
value
FROM
settings
WHERE
key
=
'wechat_connect_mode'
),
'open'
)))
=
'mp'
THEN
'false'
ELSE
'true'
END
),
(
'wechat_connect_mp_enabled'
,
CASE
WHEN
COALESCE
((
SELECT
value
FROM
settings
WHERE
key
=
'wechat_connect_enabled'
),
'false'
)
<>
'true'
THEN
'false'
WHEN
LOWER
(
TRIM
(
COALESCE
((
SELECT
value
FROM
settings
WHERE
key
=
'wechat_connect_mode'
),
'open'
)))
=
'mp'
THEN
'true'
ELSE
'false'
END
),
(
'auth_source_default_email_grant_on_signup'
,
'false'
),
(
'auth_source_default_linuxdo_grant_on_signup'
,
'false'
),
(
'auth_source_default_oidc_grant_on_signup'
,
'false'
),
(
'auth_source_default_wechat_grant_on_signup'
,
'false'
)
ON
CONFLICT
(
key
)
DO
NOTHING
;
UPDATE
settings
SET
value
=
'false'
WHERE
key
IN
(
'auth_source_default_email_grant_on_signup'
,
'auth_source_default_linuxdo_grant_on_signup'
,
'auth_source_default_oidc_grant_on_signup'
,
'auth_source_default_wechat_grant_on_signup'
);
frontend/src/api/__tests__/settings.authSourceDefaults.spec.ts
View file @
2cebb0dc
import
{
describe
,
expect
,
it
}
from
'
vitest
'
import
{
describe
,
expect
,
it
}
from
"
vitest
"
;
import
{
import
{
appendAuthSourceDefaultsToUpdateRequest
,
appendAuthSourceDefaultsToUpdateRequest
,
buildAuthSourceDefaultsState
,
buildAuthSourceDefaultsState
,
type
UpdateSettingsRequest
,
type
UpdateSettingsRequest
,
}
from
'
@/api/admin/settings
'
}
from
"
@/api/admin/settings
"
;
describe
(
'
admin settings auth source defaults helpers
'
,
()
=>
{
describe
(
"
admin settings auth source defaults helpers
"
,
()
=>
{
it
(
'
builds auth source defaults state from flat settings fields
'
,
()
=>
{
it
(
"
builds auth source defaults state from flat settings fields
"
,
()
=>
{
const
state
=
buildAuthSourceDefaultsState
({
const
state
=
buildAuthSourceDefaultsState
({
auth_source_default_email_balance
:
9.5
,
auth_source_default_email_balance
:
9.5
,
auth_source_default_email_concurrency
:
3
,
auth_source_default_email_concurrency
:
3
,
...
@@ -23,7 +23,7 @@ describe('admin settings auth source defaults helpers', () => {
...
@@ -23,7 +23,7 @@ describe('admin settings auth source defaults helpers', () => {
],
],
auth_source_default_linuxdo_grant_on_signup
:
true
,
auth_source_default_linuxdo_grant_on_signup
:
true
,
auth_source_default_linuxdo_grant_on_first_bind
:
false
,
auth_source_default_linuxdo_grant_on_first_bind
:
false
,
})
})
;
expect
(
state
.
email
).
toEqual
({
expect
(
state
.
email
).
toEqual
({
balance
:
9.5
,
balance
:
9.5
,
...
@@ -31,34 +31,43 @@ describe('admin settings auth source defaults helpers', () => {
...
@@ -31,34 +31,43 @@ describe('admin settings auth source defaults helpers', () => {
subscriptions
:
[{
group_id
:
1
,
validity_days
:
30
}],
subscriptions
:
[{
group_id
:
1
,
validity_days
:
30
}],
grant_on_signup
:
false
,
grant_on_signup
:
false
,
grant_on_first_bind
:
true
,
grant_on_first_bind
:
true
,
})
})
;
expect
(
state
.
linuxdo
).
toEqual
({
expect
(
state
.
linuxdo
).
toEqual
({
balance
:
6
,
balance
:
6
,
concurrency
:
8
,
concurrency
:
8
,
subscriptions
:
[{
group_id
:
2
,
validity_days
:
60
}],
subscriptions
:
[{
group_id
:
2
,
validity_days
:
60
}],
grant_on_signup
:
true
,
grant_on_signup
:
true
,
grant_on_first_bind
:
false
,
grant_on_first_bind
:
false
,
})
})
;
expect
(
state
.
oidc
).
toEqual
({
expect
(
state
.
oidc
).
toEqual
({
balance
:
0
,
balance
:
0
,
concurrency
:
5
,
concurrency
:
5
,
subscriptions
:
[],
subscriptions
:
[],
grant_on_signup
:
tru
e
,
grant_on_signup
:
fals
e
,
grant_on_first_bind
:
false
,
grant_on_first_bind
:
false
,
})
})
;
expect
(
state
.
wechat
).
toEqual
({
expect
(
state
.
wechat
).
toEqual
({
balance
:
0
,
balance
:
0
,
concurrency
:
5
,
concurrency
:
5
,
subscriptions
:
[],
subscriptions
:
[],
grant_on_signup
:
tru
e
,
grant_on_signup
:
fals
e
,
grant_on_first_bind
:
false
,
grant_on_first_bind
:
false
,
})
});
})
});
it
(
"
defaults grant-on-signup to disabled when settings are missing
"
,
()
=>
{
const
state
=
buildAuthSourceDefaultsState
({});
it
(
'
appends auth source defaults back onto update payload
'
,
()
=>
{
expect
(
state
.
email
.
grant_on_signup
).
toBe
(
false
);
expect
(
state
.
linuxdo
.
grant_on_signup
).
toBe
(
false
);
expect
(
state
.
oidc
.
grant_on_signup
).
toBe
(
false
);
expect
(
state
.
wechat
.
grant_on_signup
).
toBe
(
false
);
});
it
(
"
appends auth source defaults back onto update payload
"
,
()
=>
{
const
payload
:
UpdateSettingsRequest
=
{
const
payload
:
UpdateSettingsRequest
=
{
site_name
:
'
Sub2API
'
,
site_name
:
"
Sub2API
"
,
}
}
;
appendAuthSourceDefaultsToUpdateRequest
(
payload
,
{
appendAuthSourceDefaultsToUpdateRequest
(
payload
,
{
email
:
{
email
:
{
...
@@ -89,13 +98,15 @@ describe('admin settings auth source defaults helpers', () => {
...
@@ -89,13 +98,15 @@ describe('admin settings auth source defaults helpers', () => {
grant_on_signup
:
false
,
grant_on_signup
:
false
,
grant_on_first_bind
:
false
,
grant_on_first_bind
:
false
,
},
},
})
})
;
expect
(
payload
).
toMatchObject
({
expect
(
payload
).
toMatchObject
({
site_name
:
'
Sub2API
'
,
site_name
:
"
Sub2API
"
,
auth_source_default_email_balance
:
1.25
,
auth_source_default_email_balance
:
1.25
,
auth_source_default_email_concurrency
:
2
,
auth_source_default_email_concurrency
:
2
,
auth_source_default_email_subscriptions
:
[{
group_id
:
3
,
validity_days
:
7
}],
auth_source_default_email_subscriptions
:
[
{
group_id
:
3
,
validity_days
:
7
},
],
auth_source_default_email_grant_on_signup
:
true
,
auth_source_default_email_grant_on_signup
:
true
,
auth_source_default_email_grant_on_first_bind
:
false
,
auth_source_default_email_grant_on_first_bind
:
false
,
auth_source_default_linuxdo_balance
:
0
,
auth_source_default_linuxdo_balance
:
0
,
...
@@ -105,7 +116,9 @@ describe('admin settings auth source defaults helpers', () => {
...
@@ -105,7 +116,9 @@ describe('admin settings auth source defaults helpers', () => {
auth_source_default_linuxdo_grant_on_first_bind
:
true
,
auth_source_default_linuxdo_grant_on_first_bind
:
true
,
auth_source_default_oidc_balance
:
4
,
auth_source_default_oidc_balance
:
4
,
auth_source_default_oidc_concurrency
:
9
,
auth_source_default_oidc_concurrency
:
9
,
auth_source_default_oidc_subscriptions
:
[{
group_id
:
9
,
validity_days
:
90
}],
auth_source_default_oidc_subscriptions
:
[
{
group_id
:
9
,
validity_days
:
90
},
],
auth_source_default_oidc_grant_on_signup
:
true
,
auth_source_default_oidc_grant_on_signup
:
true
,
auth_source_default_oidc_grant_on_first_bind
:
true
,
auth_source_default_oidc_grant_on_first_bind
:
true
,
auth_source_default_wechat_balance
:
2
,
auth_source_default_wechat_balance
:
2
,
...
@@ -113,6 +126,6 @@ describe('admin settings auth source defaults helpers', () => {
...
@@ -113,6 +126,6 @@ describe('admin settings auth source defaults helpers', () => {
auth_source_default_wechat_subscriptions
:
[],
auth_source_default_wechat_subscriptions
:
[],
auth_source_default_wechat_grant_on_signup
:
false
,
auth_source_default_wechat_grant_on_signup
:
false
,
auth_source_default_wechat_grant_on_first_bind
:
false
,
auth_source_default_wechat_grant_on_first_bind
:
false
,
})
})
;
})
})
;
})
})
;
frontend/src/api/admin/settings.ts
View file @
2cebb0dc
...
@@ -167,7 +167,7 @@ export function buildAuthSourceDefaultsState(
...
@@ -167,7 +167,7 @@ export function buildAuthSourceDefaultsState(
:
[],
:
[],
),
),
grant_on_signup
:
grant_on_signup
:
raw
[
`auth_source_default_
${
source
}
_grant_on_signup`
]
!
==
fals
e
,
raw
[
`auth_source_default_
${
source
}
_grant_on_signup`
]
=
==
tru
e
,
grant_on_first_bind
:
grant_on_first_bind
:
raw
[
`auth_source_default_
${
source
}
_grant_on_first_bind`
]
===
true
,
raw
[
`auth_source_default_
${
source
}
_grant_on_first_bind`
]
===
true
,
};
};
...
@@ -239,6 +239,33 @@ export function defaultWeChatConnectScopesForMode(mode: unknown): string {
...
@@ -239,6 +239,33 @@ export function defaultWeChatConnectScopesForMode(mode: unknown): string {
:
"
snsapi_login
"
;
:
"
snsapi_login
"
;
}
}
export
function
resolveWeChatConnectModeCapabilities
(
openEnabled
:
unknown
,
mpEnabled
:
unknown
,
legacyMode
:
unknown
,
):
{
openEnabled
:
boolean
;
mpEnabled
:
boolean
}
{
if
(
typeof
openEnabled
===
"
boolean
"
||
typeof
mpEnabled
===
"
boolean
"
)
{
return
{
openEnabled
:
openEnabled
===
true
,
mpEnabled
:
mpEnabled
===
true
,
};
}
return
normalizeWeChatConnectMode
(
legacyMode
)
===
"
mp
"
?
{
openEnabled
:
false
,
mpEnabled
:
true
}
:
{
openEnabled
:
true
,
mpEnabled
:
false
};
}
export
function
deriveWeChatConnectStoredMode
(
openEnabled
:
boolean
,
mpEnabled
:
boolean
,
legacyMode
:
unknown
,
):
WeChatConnectMode
{
if
(
mpEnabled
)
return
"
mp
"
;
if
(
openEnabled
)
return
"
open
"
;
return
normalizeWeChatConnectMode
(
legacyMode
);
}
/**
/**
* System settings interface
* System settings interface
*/
*/
...
@@ -315,6 +342,8 @@ export interface SystemSettings {
...
@@ -315,6 +342,8 @@ export interface SystemSettings {
wechat_connect_enabled
:
boolean
;
wechat_connect_enabled
:
boolean
;
wechat_connect_app_id
:
string
;
wechat_connect_app_id
:
string
;
wechat_connect_app_secret_configured
:
boolean
;
wechat_connect_app_secret_configured
:
boolean
;
wechat_connect_open_enabled
?:
boolean
;
wechat_connect_mp_enabled
?:
boolean
;
wechat_connect_mode
:
string
;
wechat_connect_mode
:
string
;
wechat_connect_scopes
:
string
;
wechat_connect_scopes
:
string
;
wechat_connect_redirect_url
:
string
;
wechat_connect_redirect_url
:
string
;
...
@@ -472,6 +501,8 @@ export interface UpdateSettingsRequest {
...
@@ -472,6 +501,8 @@ export interface UpdateSettingsRequest {
wechat_connect_enabled
?:
boolean
;
wechat_connect_enabled
?:
boolean
;
wechat_connect_app_id
?:
string
;
wechat_connect_app_id
?:
string
;
wechat_connect_app_secret
?:
string
;
wechat_connect_app_secret
?:
string
;
wechat_connect_open_enabled
?:
boolean
;
wechat_connect_mp_enabled
?:
boolean
;
wechat_connect_mode
?:
string
;
wechat_connect_mode
?:
string
;
wechat_connect_scopes
?:
string
;
wechat_connect_scopes
?:
string
;
wechat_connect_redirect_url
?:
string
;
wechat_connect_redirect_url
?:
string
;
...
...
frontend/src/views/admin/SettingsView.vue
View file @
2cebb0dc
...
@@ -1408,7 +1408,7 @@
...
@@ -1408,7 +1408,7 @@
v
-
if
=
"
form.wechat_connect_enabled
"
v
-
if
=
"
form.wechat_connect_enabled
"
class
=
"
space-y-6 border-t border-gray-100 pt-4 dark:border-dark-700
"
class
=
"
space-y-6 border-t border-gray-100 pt-4 dark:border-dark-700
"
>
>
<
div
class
=
"
grid grid-cols-1 gap-6 lg:grid-cols-
3
"
>
<
div
class
=
"
grid grid-cols-1 gap-6 lg:grid-cols-
2
"
>
<
div
>
<
div
>
<
label
<
label
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
...
@@ -1463,68 +1463,73 @@
...
@@ -1463,68 +1463,73 @@
}}
}}
<
/p
>
<
/p
>
<
/div
>
<
/div
>
<
/div
>
<
div
>
<
div
class
=
"
grid grid-cols-1 gap-6 lg:grid-cols-2
"
>
<
div
class
=
"
space-y-3
"
>
<
label
<
label
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
>
>
{{
localText
(
"
模式
"
,
"
Mode
"
)
}}
{{
localText
(
"
模式
"
,
"
Mode
"
)
}}
<
/label
>
<
/label
>
<
select
<
div
data
-
testid
=
"
wechat-connect-mode
"
class
=
"
flex items-center justify-between rounded border border-gray-200 px-4 py-3 dark:border-dark-700
"
v
-
model
=
"
form.wechat_connect_mode
"
class
=
"
input font-mono text-sm
"
@
change
=
"
syncWeChatConnectMode
"
>
>
<
option
value
=
"
open
"
>
<
div
>
{{
localText
(
"
开放平台
"
,
"
Open Platform
"
)
}}
<
div
class
=
"
font-medium text-gray-900 dark:text-white
"
>
<
/option
>
{{
<
option
value
=
"
mp
"
>
localText
(
{{
"
非微信环境使用开放平台
"
,
localText
(
"
Use Open outside WeChat
"
,
"
公众号 / 小程序
"
,
)
"
Official Account / Mini Program
"
,
}}
)
<
/div
>
}}
<
p
<
/option
>
class
=
"
mt-0.5 text-xs text-gray-500 dark:text-gray-400
"
<
/select
>
>
<
p
class
=
"
mt-1.5 text-xs text-gray-500 dark:text-gray-400
"
>
{{
{{
localText
(
localText
(
"
浏览器不在微信内时,自动走开放平台扫码授权。
"
,
"
open 对应微信开放平台,mp 对应公众号/小程序授权。
"
,
"
Use Open Platform QR authorization outside the WeChat browser.
"
,
"
open maps to WeChat Open Platform, mp maps to Official Account / Mini Program authorization.
"
,
)
)
}}
}}
<
/p
>
<
/p
>
<
/div
>
<
/div
>
<
Toggle
<
/div
>
v
-
model
=
"
form.wechat_connect_open_enabled
"
data
-
testid
=
"
wechat-connect-open-enabled
"
<
div
class
=
"
grid grid-cols-1 gap-6 lg:grid-cols-2
"
>
@
update
:
model
-
value
=
"
syncWeChatConnectMode
"
<
div
>
/>
<
label
<
/div
>
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
<
div
class
=
"
flex items-center justify-between rounded border border-gray-200 px-4 py-3 dark:border-dark-700
"
>
>
{{
localText
(
"
Scopes
"
,
"
Scopes
"
)
}}
<
div
>
<
/label
>
<
div
class
=
"
font-medium text-gray-900 dark:text-white
"
>
<
input
{{
data
-
testid
=
"
wechat-connect-scopes
"
localText
(
v
-
model
=
"
form.wechat_connect_scopes
"
"
微信环境使用公众号
"
,
type
=
"
text
"
"
Use MP inside WeChat
"
,
class
=
"
input font-mono text-sm
"
)
:
placeholder
=
"
}}
form.wechat_connect_mode === 'mp'
<
/div
>
? 'snsapi_userinfo'
<
p
: 'snsapi_login'
class
=
"
mt-0.5 text-xs text-gray-500 dark:text-gray-400
"
"
>
/>
{{
<
p
class
=
"
mt-1.5 text-xs text-gray-500 dark:text-gray-400
"
>
localText
(
{{
"
浏览器在微信内时,自动走公众号授权。
"
,
localText
(
"
Use Official Account authorization inside the WeChat browser.
"
,
"
留空时会按模式自动回填默认值。
"
,
)
"
Leave empty to use the default scope for the selected mode.
"
,
}}
)
<
/p
>
}}
<
/div
>
<
/p
>
<
Toggle
v
-
model
=
"
form.wechat_connect_mp_enabled
"
data
-
testid
=
"
wechat-connect-mp-enabled
"
@
update
:
model
-
value
=
"
syncWeChatConnectMode
"
/>
<
/div
>
<
/div
>
<
/div
>
<
div
>
<
div
>
...
@@ -2246,83 +2251,77 @@
...
@@ -2246,83 +2251,77 @@
<
Toggle
v
-
model
=
"
form.force_email_on_third_party_signup
"
/>
<
Toggle
v
-
model
=
"
form.force_email_on_third_party_signup
"
/>
<
/div
>
<
/div
>
<
div
class
=
"
grid grid-cols-1 gap-4 xl:grid-cols-2
"
>
<
div
class
=
"
space-y-4
"
>
<
div
<
div
v
-
for
=
"
authSource in authSourceDefaultsMeta
"
v
-
for
=
"
authSource in authSourceDefaultsMeta
"
:
key
=
"
authSource.source
"
:
key
=
"
authSource.source
"
class
=
"
rounded-xl border border-gray-200 p-4 dark:border-dark-700
"
class
=
"
rounded-xl border border-gray-200 p-4 dark:border-dark-700
"
>
>
<
div
class
=
"
mb-4
"
>
<
div
class
=
"
flex items-center justify-between gap-4
"
>
<
div
class
=
"
font-medium text-gray-900 dark:text-white
"
>
{{
authSource
.
title
}}
<
/div
>
<
p
class
=
"
mt-1 text-sm text-gray-500 dark:text-gray-400
"
>
{{
authSource
.
description
}}
<
/p
>
<
/div
>
<
div
class
=
"
grid grid-cols-1 gap-4 md:grid-cols-2
"
>
<
div
>
<
label
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
>
{{
t
(
"
admin.settings.defaults.defaultBalance
"
)
}}
<
/label
>
<
input
v
-
model
.
number
=
"
authSourceDefaults[authSource.source].balance
"
type
=
"
number
"
step
=
"
0.01
"
min
=
"
0
"
class
=
"
input
"
placeholder
=
"
0.00
"
/>
<
/div
>
<
div
>
<
div
>
<
label
<
div
class
=
"
font-medium text-gray-900 dark:text-white
"
>
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
{{
authSource
.
title
}}
>
<
/div
>
{{
t
(
"
admin.settings.defaults.defaultConcurrency
"
)
}}
<
p
class
=
"
mt-1 text-sm text-gray-500 dark:text-gray-400
"
>
<
/label
>
{{
authSource
.
description
}}
<
input
<
/p
>
v
-
model
.
number
=
"
authSourceDefaults[authSource.source].concurrency
"
type
=
"
number
"
min
=
"
1
"
class
=
"
input
"
placeholder
=
"
5
"
/>
<
/div
>
<
/div
>
<
Toggle
v
-
model
=
"
authSourceDefaults[authSource.source].grant_on_signup
"
:
data
-
testid
=
"
`auth-source-${authSource.source
}
-enabled`
"
/>
<
/div
>
<
/div
>
<
div
class
=
"
mt-4 grid grid-cols-1 gap-3 md:grid-cols-2
"
>
<
div
<
div
v
-
if
=
"
authSourceDefaults[authSource.source].grant_on_signup
"
class
=
"
flex items-center justify-between rounded border border-gray-200 px-4 py-3 dark:border-dark-700
"
:
data
-
testid
=
"
`auth-source-${authSource.source
}
-panel`
"
>
class
=
"
mt-4 space-y-4 border-t border-gray-100 pt-4 dark:border-dark-700
"
>
<
p
class
=
"
text-sm text-gray-500 dark:text-gray-400
"
>
{{
localText
(
"
以下默认值会在该来源注册新用户时发放;首次绑定时授权仅作用于已有账号绑定该来源。
"
,
"
These defaults apply when a new user registers through this source. Grant on first bind only applies when an existing user binds this source.
"
,
)
}}
<
/p
>
<
div
class
=
"
grid grid-cols-1 gap-4 md:grid-cols-2
"
>
<
div
>
<
div
>
<
label
<
label
class
=
"
font-medium text-gray-
9
00 dark:text-
white
"
class
=
"
mb-2 block text-sm
font-medium text-gray-
7
00 dark:text-
gray-300
"
>
>
{{
localText
(
"
注册即授权
"
,
"
Grant on signup
"
)
}}
{{
t
(
"
admin.settings.defaults.defaultBalance
"
)
}}
<
/label
>
<
/label
>
<
p
<
input
class
=
"
mt-0.5 text-xs text-gray-500 dark:text-gray-400
"
v
-
model
.
number
=
"
authSourceDefaults[authSource.source].balance
"
type
=
"
number
"
step
=
"
0.01
"
min
=
"
0
"
class
=
"
input
"
placeholder
=
"
0.00
"
/>
<
/div
>
<
div
>
<
label
class
=
"
mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300
"
>
>
{{
{{
t
(
"
admin.settings.defaults.defaultConcurrency
"
)
}}
localText
(
<
/label
>
"
来源首次注册成功后立即发放默认权益。
"
,
<
input
"
Grant default entitlements immediately after signup.
"
,
v
-
model
.
number
=
"
)
authSourceDefaults[authSource.source].concurrency
}}
"
<
/p
>
type
=
"
number
"
min
=
"
1
"
class
=
"
input
"
placeholder
=
"
5
"
/>
<
/div
>
<
/div
>
<
Toggle
v
-
model
=
"
authSourceDefaults[authSource.source].grant_on_signup
"
/>
<
/div
>
<
/div
>
<
div
<
div
...
@@ -2341,8 +2340,8 @@
...
@@ -2341,8 +2340,8 @@
>
>
{{
{{
localText
(
localText
(
"
来源首次绑定到现有账号
时发放默认权益。
"
,
"
已有账号首次绑定该来源
时发放默认权益。
"
,
"
Grant default entitlements when
the source is
first b
ou
nd t
o an existing user
.
"
,
"
Grant default entitlements when
an existing user
first b
i
nd
s
t
his source
.
"
,
)
)
}}
}}
<
/p
>
<
/p
>
...
@@ -2354,11 +2353,7 @@
...
@@ -2354,11 +2353,7 @@
"
"
/>
/>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"
mt-4 border-t border-gray-100 pt-4 dark:border-dark-700
"
>
<
div
class
=
"
mb-3 flex items-center justify-between
"
>
<
div
class
=
"
mb-3 flex items-center justify-between
"
>
<
div
>
<
div
>
<
label
<
label
...
@@ -4710,12 +4705,13 @@ import { useI18n } from "vue-i18n";
...
@@ -4710,12 +4705,13 @@ import { useI18n } from "vue-i18n";
import
{
adminAPI
}
from
"
@/api
"
;
import
{
adminAPI
}
from
"
@/api
"
;
import
{
import
{
appendAuthSourceDefaultsToUpdateRequest
,
appendAuthSourceDefaultsToUpdateRequest
,
defaultWeChatConnectScopesForMode
,
buildAuthSourceDefaultsState
,
buildAuthSourceDefaultsState
,
defaultWeChatConnectScopesForMode
,
deriveWeChatConnectStoredMode
,
getPaymentVisibleMethodSourceOptions
,
getPaymentVisibleMethodSourceOptions
,
normalizePaymentVisibleMethodSource
,
normalizePaymentVisibleMethodSource
,
normalizeDefaultSubscriptionSettings
,
normalizeDefaultSubscriptionSettings
,
normaliz
eWeChatConnectMode
,
resolv
eWeChatConnectMode
Capabilities
,
}
from
"
@/api/admin/settings
"
;
}
from
"
@/api/admin/settings
"
;
import
type
{
import
type
{
AuthSourceDefaultsState
,
AuthSourceDefaultsState
,
...
@@ -4859,11 +4855,16 @@ interface DefaultSubscriptionGroupOption {
...
@@ -4859,11 +4855,16 @@ interface DefaultSubscriptionGroupOption {
[
key
:
string
]:
unknown
;
[
key
:
string
]:
unknown
;
}
}
type
SettingsForm
=
SystemSettings
&
{
type
SettingsForm
=
Omit
<
SystemSettings
,
"
wechat_connect_open_enabled
"
|
"
wechat_connect_mp_enabled
"
>
&
{
smtp_password
:
string
;
smtp_password
:
string
;
turnstile_secret_key
:
string
;
turnstile_secret_key
:
string
;
linuxdo_connect_client_secret
:
string
;
linuxdo_connect_client_secret
:
string
;
wechat_connect_app_secret
:
string
;
wechat_connect_app_secret
:
string
;
wechat_connect_open_enabled
:
boolean
;
wechat_connect_mp_enabled
:
boolean
;
oidc_connect_client_secret
:
string
;
oidc_connect_client_secret
:
string
;
force_email_on_third_party_signup
:
boolean
;
force_email_on_third_party_signup
:
boolean
;
payment_visible_method_alipay_source
:
string
;
payment_visible_method_alipay_source
:
string
;
...
@@ -4958,6 +4959,8 @@ const form = reactive<SettingsForm>({
...
@@ -4958,6 +4959,8 @@ const form = reactive<SettingsForm>({
wechat_connect_app_id
:
""
,
wechat_connect_app_id
:
""
,
wechat_connect_app_secret
:
""
,
wechat_connect_app_secret
:
""
,
wechat_connect_app_secret_configured
:
false
,
wechat_connect_app_secret_configured
:
false
,
wechat_connect_open_enabled
:
false
,
wechat_connect_mp_enabled
:
false
,
wechat_connect_mode
:
"
open
"
,
wechat_connect_mode
:
"
open
"
,
wechat_connect_scopes
:
"
snsapi_login
"
,
wechat_connect_scopes
:
"
snsapi_login
"
,
wechat_connect_redirect_url
:
""
,
wechat_connect_redirect_url
:
""
,
...
@@ -5452,14 +5455,21 @@ const wechatRedirectUrlSuggestion = computed(() => {
...
@@ -5452,14 +5455,21 @@ const wechatRedirectUrlSuggestion = computed(() => {
}
);
}
);
function
syncWeChatConnectMode
()
{
function
syncWeChatConnectMode
()
{
form
.
wechat_connect_mode
=
normalizeWeChatConnectMode
(
const
capabilities
=
resolveWeChatConnectModeCapabilities
(
form
.
wechat_connect_open_enabled
,
form
.
wechat_connect_mp_enabled
,
form
.
wechat_connect_mode
,
);
form
.
wechat_connect_open_enabled
=
capabilities
.
openEnabled
;
form
.
wechat_connect_mp_enabled
=
capabilities
.
mpEnabled
;
form
.
wechat_connect_mode
=
deriveWeChatConnectStoredMode
(
capabilities
.
openEnabled
,
capabilities
.
mpEnabled
,
form
.
wechat_connect_mode
,
);
form
.
wechat_connect_scopes
=
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
,
form
.
wechat_connect_mode
,
);
);
if
(
!
form
.
wechat_connect_scopes
.
trim
())
{
form
.
wechat_connect_scopes
=
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
,
);
}
}
}
async
function
setAndCopyWeChatRedirectUrl
()
{
async
function
setAndCopyWeChatRedirectUrl
()
{
...
@@ -5608,16 +5618,21 @@ async function loadSettings() {
...
@@ -5608,16 +5618,21 @@ async function loadSettings() {
form
.
turnstile_secret_key
=
""
;
form
.
turnstile_secret_key
=
""
;
form
.
linuxdo_connect_client_secret
=
""
;
form
.
linuxdo_connect_client_secret
=
""
;
form
.
wechat_connect_app_secret
=
""
;
form
.
wechat_connect_app_secret
=
""
;
form
.
wechat_connect_mode
=
normalizeWeChatConnectMode
(
const
wechatCapabilities
=
resolveWeChatConnectModeCapabilities
(
settings
.
wechat_connect_open_enabled
,
settings
.
wechat_connect_mp_enabled
,
settings
.
wechat_connect_mode
,
);
form
.
wechat_connect_open_enabled
=
wechatCapabilities
.
openEnabled
;
form
.
wechat_connect_mp_enabled
=
wechatCapabilities
.
mpEnabled
;
form
.
wechat_connect_mode
=
deriveWeChatConnectStoredMode
(
wechatCapabilities
.
openEnabled
,
wechatCapabilities
.
mpEnabled
,
settings
.
wechat_connect_mode
,
settings
.
wechat_connect_mode
,
);
);
const
wechatConnectScopes
=
form
.
wechat_connect_scopes
=
defaultWeChatConnectScopesForMode
(
typeof
settings
.
wechat_connect_scopes
===
"
string
"
form
.
wechat_connect_mode
,
?
settings
.
wechat_connect_scopes
.
trim
()
);
:
""
;
form
.
wechat_connect_scopes
=
wechatConnectScopes
||
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
);
form
.
oidc_connect_client_secret
=
""
;
form
.
oidc_connect_client_secret
=
""
;
// Load web search emulation config separately
// Load web search emulation config separately
...
@@ -5789,6 +5804,12 @@ async function saveSettings() {
...
@@ -5789,6 +5804,12 @@ async function saveSettings() {
// Optional URL fields: auto-clear invalid values so they don't cause backend 400 errors
// Optional URL fields: auto-clear invalid values so they don't cause backend 400 errors
if
(
!
isValidHttpUrl
(
form
.
frontend_url
))
form
.
frontend_url
=
""
;
if
(
!
isValidHttpUrl
(
form
.
frontend_url
))
form
.
frontend_url
=
""
;
if
(
!
isValidHttpUrl
(
form
.
doc_url
))
form
.
doc_url
=
""
;
if
(
!
isValidHttpUrl
(
form
.
doc_url
))
form
.
doc_url
=
""
;
syncWeChatConnectMode
();
const
wechatStoredMode
=
deriveWeChatConnectStoredMode
(
form
.
wechat_connect_open_enabled
,
form
.
wechat_connect_mp_enabled
,
form
.
wechat_connect_mode
,
);
const
payload
:
UpdateSettingsRequest
=
{
const
payload
:
UpdateSettingsRequest
=
{
registration_enabled
:
form
.
registration_enabled
,
registration_enabled
:
form
.
registration_enabled
,
...
@@ -5837,10 +5858,11 @@ async function saveSettings() {
...
@@ -5837,10 +5858,11 @@ async function saveSettings() {
wechat_connect_enabled
:
form
.
wechat_connect_enabled
,
wechat_connect_enabled
:
form
.
wechat_connect_enabled
,
wechat_connect_app_id
:
form
.
wechat_connect_app_id
,
wechat_connect_app_id
:
form
.
wechat_connect_app_id
,
wechat_connect_app_secret
:
form
.
wechat_connect_app_secret
||
undefined
,
wechat_connect_app_secret
:
form
.
wechat_connect_app_secret
||
undefined
,
wechat_connect_mode
:
normalizeWeChatConnectMode
(
form
.
wechat_connect_mode
),
wechat_connect_open_enabled
:
form
.
wechat_connect_open_enabled
,
wechat_connect_mp_enabled
:
form
.
wechat_connect_mp_enabled
,
wechat_connect_mode
:
wechatStoredMode
,
wechat_connect_scopes
:
wechat_connect_scopes
:
form
.
wechat_connect_scopes
.
trim
()
||
defaultWeChatConnectScopesForMode
(
wechatStoredMode
),
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
),
wechat_connect_redirect_url
:
form
.
wechat_connect_redirect_url
,
wechat_connect_redirect_url
:
form
.
wechat_connect_redirect_url
,
wechat_connect_frontend_redirect_url
:
wechat_connect_frontend_redirect_url
:
form
.
wechat_connect_frontend_redirect_url
,
form
.
wechat_connect_frontend_redirect_url
,
...
@@ -5967,16 +5989,21 @@ async function saveSettings() {
...
@@ -5967,16 +5989,21 @@ async function saveSettings() {
form
.
turnstile_secret_key
=
""
;
form
.
turnstile_secret_key
=
""
;
form
.
linuxdo_connect_client_secret
=
""
;
form
.
linuxdo_connect_client_secret
=
""
;
form
.
wechat_connect_app_secret
=
""
;
form
.
wechat_connect_app_secret
=
""
;
form
.
wechat_connect_mode
=
normalizeWeChatConnectMode
(
const
updatedWechatCapabilities
=
resolveWeChatConnectModeCapabilities
(
updated
.
wechat_connect_open_enabled
,
updated
.
wechat_connect_mp_enabled
,
updated
.
wechat_connect_mode
,
updated
.
wechat_connect_mode
,
);
);
const
updatedWechatConnectScopes
=
form
.
wechat_connect_open_enabled
=
updatedWechatCapabilities
.
openEnabled
;
typeof
updated
.
wechat_connect_scopes
===
"
string
"
form
.
wechat_connect_mp_enabled
=
updatedWechatCapabilities
.
mpEnabled
;
?
updated
.
wechat_connect_scopes
.
trim
()
form
.
wechat_connect_mode
=
deriveWeChatConnectStoredMode
(
:
""
;
updatedWechatCapabilities
.
openEnabled
,
form
.
wechat_connect_scopes
=
updatedWechatCapabilities
.
mpEnabled
,
updatedWechatConnectScopes
||
updated
.
wechat_connect_mode
,
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
);
);
form
.
wechat_connect_scopes
=
defaultWeChatConnectScopesForMode
(
form
.
wechat_connect_mode
,
);
form
.
oidc_connect_client_secret
=
""
;
form
.
oidc_connect_client_secret
=
""
;
// Save web search emulation config separately (errors handled internally)
// Save web search emulation config separately (errors handled internally)
const
wsOk
=
await
saveWebSearchConfig
();
const
wsOk
=
await
saveWebSearchConfig
();
...
...
frontend/src/views/admin/__tests__/SettingsView.spec.ts
View file @
2cebb0dc
...
@@ -111,9 +111,11 @@ const ToggleStub = defineComponent({
...
@@ -111,9 +111,11 @@ const ToggleStub = defineComponent({
},
},
},
},
emits
:
[
"
update:modelValue
"
],
emits
:
[
"
update:modelValue
"
],
setup
(
props
,
{
emit
})
{
inheritAttrs
:
false
,
setup
(
props
,
{
attrs
,
emit
})
{
return
()
=>
return
()
=>
h
(
"
input
"
,
{
h
(
"
input
"
,
{
...
attrs
,
class
:
"
toggle-stub
"
,
class
:
"
toggle-stub
"
,
type
:
"
checkbox
"
,
type
:
"
checkbox
"
,
checked
:
props
.
modelValue
,
checked
:
props
.
modelValue
,
...
@@ -217,6 +219,8 @@ const baseSettingsResponse = {
...
@@ -217,6 +219,8 @@ const baseSettingsResponse = {
wechat_connect_enabled
:
true
,
wechat_connect_enabled
:
true
,
wechat_connect_app_id
:
"
wx-app-id-123
"
,
wechat_connect_app_id
:
"
wx-app-id-123
"
,
wechat_connect_app_secret_configured
:
true
,
wechat_connect_app_secret_configured
:
true
,
wechat_connect_open_enabled
:
false
,
wechat_connect_mp_enabled
:
true
,
wechat_connect_mode
:
"
mp
"
,
wechat_connect_mode
:
"
mp
"
,
wechat_connect_scopes
:
""
,
wechat_connect_scopes
:
""
,
wechat_connect_redirect_url
:
wechat_connect_redirect_url
:
...
@@ -334,6 +338,16 @@ async function openSecurityTab(wrapper: ReturnType<typeof mountView>) {
...
@@ -334,6 +338,16 @@ async function openSecurityTab(wrapper: ReturnType<typeof mountView>) {
await
flushPromises
();
await
flushPromises
();
}
}
async
function
openUsersTab
(
wrapper
:
ReturnType
<
typeof
mountView
>
)
{
const
usersTabButton
=
wrapper
.
findAll
(
"
button
"
)
.
find
((
node
)
=>
node
.
text
().
includes
(
"
admin.settings.tabs.users
"
));
expect
(
usersTabButton
).
toBeDefined
();
await
usersTabButton
?.
trigger
(
"
click
"
);
await
flushPromises
();
}
describe
(
"
admin SettingsView payment visible method controls
"
,
()
=>
{
describe
(
"
admin SettingsView payment visible method controls
"
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
getSettings
.
mockReset
();
getSettings
.
mockReset
();
...
@@ -595,16 +609,19 @@ describe("admin SettingsView wechat connect controls", () => {
...
@@ -595,16 +609,19 @@ describe("admin SettingsView wechat connect controls", () => {
).
toBe
(
"
wx-app-id-123
"
);
).
toBe
(
"
wx-app-id-123
"
);
expect
(
expect
(
(
(
wrapper
.
get
(
'
[data-testid="wechat-connect-
mode
"]
'
)
wrapper
.
get
(
'
[data-testid="wechat-connect-
open-enabled
"]
'
)
.
element
as
HTML
Selec
tElement
.
element
as
HTML
Inpu
tElement
).
value
,
).
checked
,
).
toBe
(
"
mp
"
);
).
toBe
(
false
);
expect
(
expect
(
(
(
wrapper
.
get
(
'
[data-testid="wechat-connect-
scopes
"]
'
)
wrapper
.
get
(
'
[data-testid="wechat-connect-
mp-enabled
"]
'
)
.
element
as
HTMLInputElement
.
element
as
HTMLInputElement
).
value
,
).
checked
,
).
toBe
(
"
snsapi_userinfo
"
);
).
toBe
(
true
);
expect
(
wrapper
.
find
(
'
[data-testid="wechat-connect-scopes"]
'
).
exists
()).
toBe
(
false
,
);
expect
(
expect
(
wrapper
wrapper
.
get
(
'
[data-testid="wechat-connect-app-secret"]
'
)
.
get
(
'
[data-testid="wechat-connect-app-secret"]
'
)
...
@@ -630,10 +647,12 @@ describe("admin SettingsView wechat connect controls", () => {
...
@@ -630,10 +647,12 @@ describe("admin SettingsView wechat connect controls", () => {
await
wrapper
await
wrapper
.
get
(
'
[data-testid="wechat-connect-app-secret"]
'
)
.
get
(
'
[data-testid="wechat-connect-app-secret"]
'
)
.
setValue
(
"
new-secret
"
);
.
setValue
(
"
new-secret
"
);
await
wrapper
.
get
(
'
[data-testid="wechat-connect-mode"]
'
).
setValue
(
"
open
"
);
await
wrapper
await
wrapper
.
get
(
'
[data-testid="wechat-connect-scopes"]
'
)
.
get
(
'
[data-testid="wechat-connect-open-enabled"]
'
)
.
setValue
(
"
snsapi_base
"
);
.
setValue
(
true
);
await
wrapper
.
get
(
'
[data-testid="wechat-connect-mp-enabled"]
'
)
.
setValue
(
true
);
await
wrapper
await
wrapper
.
get
(
'
[data-testid="wechat-connect-redirect-url"]
'
)
.
get
(
'
[data-testid="wechat-connect-redirect-url"]
'
)
.
setValue
(
"
https://admin.example.com/api/v1/auth/oauth/wechat/callback
"
);
.
setValue
(
"
https://admin.example.com/api/v1/auth/oauth/wechat/callback
"
);
...
@@ -649,8 +668,8 @@ describe("admin SettingsView wechat connect controls", () => {
...
@@ -649,8 +668,8 @@ describe("admin SettingsView wechat connect controls", () => {
wechat_connect_enabled
:
true
,
wechat_connect_enabled
:
true
,
wechat_connect_app_id
:
"
wx-app-id-updated
"
,
wechat_connect_app_id
:
"
wx-app-id-updated
"
,
wechat_connect_app_secret
:
"
new-secret
"
,
wechat_connect_app_secret
:
"
new-secret
"
,
wechat_connect_
mode
:
"
open
"
,
wechat_connect_
open_enabled
:
true
,
wechat_connect_
scopes
:
"
snsapi_base
"
,
wechat_connect_
mp_enabled
:
true
,
wechat_connect_redirect_url
:
wechat_connect_redirect_url
:
"
https://admin.example.com/api/v1/auth/oauth/wechat/callback
"
,
"
https://admin.example.com/api/v1/auth/oauth/wechat/callback
"
,
wechat_connect_frontend_redirect_url
:
"
/auth/wechat/callback
"
,
wechat_connect_frontend_redirect_url
:
"
/auth/wechat/callback
"
,
...
@@ -668,4 +687,31 @@ describe("admin SettingsView wechat connect controls", () => {
...
@@ -668,4 +687,31 @@ describe("admin SettingsView wechat connect controls", () => {
.
attributes
(
"
placeholder
"
),
.
attributes
(
"
placeholder
"
),
).
toContain
(
"
密钥已配置
"
);
).
toContain
(
"
密钥已配置
"
);
});
});
it
(
"
collapses auth source defaults until the source is enabled
"
,
async
()
=>
{
const
wrapper
=
mountView
();
await
flushPromises
();
await
openUsersTab
(
wrapper
);
expect
(
(
wrapper
.
get
(
'
[data-testid="auth-source-email-enabled"]
'
)
.
element
as
HTMLInputElement
).
checked
,
).
toBe
(
false
);
expect
(
wrapper
.
find
(
'
[data-testid="auth-source-email-panel"]
'
).
exists
(),
).
toBe
(
false
);
expect
(
wrapper
.
text
()).
not
.
toContain
(
"
注册即授权
"
);
await
wrapper
.
get
(
'
[data-testid="auth-source-email-enabled"]
'
)
.
setValue
(
true
);
expect
(
wrapper
.
find
(
'
[data-testid="auth-source-email-panel"]
'
).
exists
(),
).
toBe
(
true
);
expect
(
wrapper
.
text
()).
toContain
(
"
首次绑定时授权
"
);
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment