96 lines
3.6 KiB
Go
96 lines
3.6 KiB
Go
package auth
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/xerr"
|
||
authdomain "hyapp/services/user-service/internal/domain/auth"
|
||
)
|
||
|
||
const (
|
||
defaultMaxAccountsPerDevice = int32(1)
|
||
registerRiskConfigCacheTTL = 5 * time.Minute
|
||
)
|
||
|
||
// GetRegisterRiskConfig 返回当前 App 的注册风控配置。
|
||
// Redis 只缓存 5 分钟以降低登录注册热路径回源;缓存异常不阻断读取,避免缓存故障改变注册策略。
|
||
func (s *Service) GetRegisterRiskConfig(ctx context.Context) (authdomain.RegisterRiskConfig, error) {
|
||
appCode := appcode.FromContext(ctx)
|
||
if s.registerRiskConfigCache != nil {
|
||
config, ok, err := s.registerRiskConfigCache.GetRegisterRiskConfig(ctx, appCode)
|
||
if err == nil && ok {
|
||
return normalizeRegisterRiskConfig(config), nil
|
||
}
|
||
}
|
||
config, err := s.loadRegisterRiskConfig(ctx, appCode)
|
||
if err != nil {
|
||
return authdomain.RegisterRiskConfig{}, err
|
||
}
|
||
if s.registerRiskConfigCache != nil {
|
||
// 读路径写缓存是加速动作;失败时仍返回 MySQL 事实,后续请求会继续尝试刷新缓存。
|
||
_ = s.registerRiskConfigCache.SetRegisterRiskConfig(ctx, config, registerRiskConfigCacheTTL)
|
||
}
|
||
return config, nil
|
||
}
|
||
|
||
// UpdateRegisterRiskConfig 保存注册风控配置并立即刷新 Redis。
|
||
// MySQL 是持久事实,Redis 是注册热路径缓存;更新后同步刷新同一个 key,避免运营保存后继续命中旧值。
|
||
func (s *Service) UpdateRegisterRiskConfig(ctx context.Context, maxAccountsPerDevice int32, operatorAdminID int64) (authdomain.RegisterRiskConfig, error) {
|
||
if maxAccountsPerDevice < 1 {
|
||
return authdomain.RegisterRiskConfig{}, xerr.New(xerr.InvalidArgument, "max_accounts_per_device must be greater than 0")
|
||
}
|
||
if s.authRepository == nil {
|
||
return authdomain.RegisterRiskConfig{}, xerr.New(xerr.Unavailable, "auth repository is not configured")
|
||
}
|
||
nowMs := s.now().UTC().UnixMilli()
|
||
config, err := s.authRepository.UpsertRegisterRiskConfig(ctx, authdomain.RegisterRiskConfig{
|
||
AppCode: appcode.FromContext(ctx),
|
||
MaxAccountsPerDevice: maxAccountsPerDevice,
|
||
UpdatedByAdminID: operatorAdminID,
|
||
CreatedAtMs: nowMs,
|
||
UpdatedAtMs: nowMs,
|
||
})
|
||
if err != nil {
|
||
return authdomain.RegisterRiskConfig{}, err
|
||
}
|
||
config = normalizeRegisterRiskConfig(config)
|
||
if s.registerRiskConfigCache != nil {
|
||
if err := s.registerRiskConfigCache.SetRegisterRiskConfig(ctx, config, registerRiskConfigCacheTTL); err != nil {
|
||
// 保存成功但缓存未刷新时返回错误,提示后台重试;否则注册链路可能在 5 分钟内继续读取旧配置。
|
||
return authdomain.RegisterRiskConfig{}, err
|
||
}
|
||
}
|
||
return config, nil
|
||
}
|
||
|
||
func (s *Service) loadRegisterRiskConfig(ctx context.Context, appCode string) (authdomain.RegisterRiskConfig, error) {
|
||
if s.authRepository == nil {
|
||
return defaultRegisterRiskConfig(appCode), nil
|
||
}
|
||
config, err := s.authRepository.GetRegisterRiskConfig(ctx, appCode)
|
||
if xerr.IsCode(err, xerr.NotFound) {
|
||
return defaultRegisterRiskConfig(appCode), nil
|
||
}
|
||
if err != nil {
|
||
return authdomain.RegisterRiskConfig{}, err
|
||
}
|
||
return normalizeRegisterRiskConfig(config), nil
|
||
}
|
||
|
||
func defaultRegisterRiskConfig(appCode string) authdomain.RegisterRiskConfig {
|
||
return authdomain.RegisterRiskConfig{
|
||
AppCode: appcode.Normalize(appCode),
|
||
MaxAccountsPerDevice: defaultMaxAccountsPerDevice,
|
||
}
|
||
}
|
||
|
||
func normalizeRegisterRiskConfig(config authdomain.RegisterRiskConfig) authdomain.RegisterRiskConfig {
|
||
config.AppCode = appcode.Normalize(config.AppCode)
|
||
if config.MaxAccountsPerDevice < 1 {
|
||
config.MaxAccountsPerDevice = defaultMaxAccountsPerDevice
|
||
}
|
||
return config
|
||
}
|