2026-06-25 11:21:16 +08:00

96 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}