package service import ( "context" "errors" "kra/internal/biz" "kra/internal/service/dto" ) func securityDTO(v *biz.SecurityConfig) map[string]any { return map[string]any{"ID": v.ID, "captchaOpen": v.CaptchaOpen, "captchaTimeout": v.CaptchaTimeout, "keyLong": v.KeyLong, "imgWidth": v.ImgWidth, "imgHeight": v.ImgHeight, "pwdMinLength": v.PwdMinLength, "pwdRequireUpper": v.PwdRequireUpper, "pwdRequireLower": v.PwdRequireLower, "pwdRequireDigit": v.PwdRequireDigit, "pwdRequireSpecial": v.PwdRequireSpecial, "limitEnable": v.LimitEnable, "limitWindow": v.LimitWindow, "limitCount": v.LimitCount, "lockEnable": v.LockEnable, "lockThreshold": v.LockThreshold, "lockDuration": v.LockDuration, "pwdExpireEnable": v.PwdExpireEnable, "pwdExpireDays": v.PwdExpireDays, "forceNewUserChangePassword": v.ForceNewUserChangePassword} } func (s *SettingsService) CurrentSecurity(ctx context.Context) (*biz.SecurityConfig, error) { s.securityMu.RLock() if s.securityCache != nil { copy := *s.securityCache s.securityMu.RUnlock() return ©, nil } s.securityMu.RUnlock() value, err := s.Repo().SecurityConfig(ctx) if err != nil { return nil, err } s.securityMu.Lock() s.securityCache = value copy := *value s.securityMu.Unlock() return ©, nil } func (s *SettingsService) Security(ctx context.Context) (map[string]any, error) { value, err := s.CurrentSecurity(ctx) if err != nil { return nil, err } return securityDTO(value), nil } func (s *SettingsService) SaveSecurity(ctx context.Context, value *biz.SecurityConfig) (map[string]any, error) { if value.KeyLong < 1 || value.ImgWidth < 1 || value.ImgHeight < 1 || value.PwdMinLength < 1 || value.LimitWindow < 1 || value.LimitCount < 1 || value.LockThreshold < 1 || value.LockDuration < 1 || value.PwdExpireDays < 1 { return nil, errors.New("安全配置数值必须大于0") } if err := s.Repo().SaveSecurityConfig(ctx, value); err != nil { return nil, err } s.securityMu.Lock() s.securityCache = value s.securityMu.Unlock() return securityDTO(value), nil } func (s *SettingsService) SaveSecurityRequest(ctx context.Context, value *dto.SecurityConfigRequest) (map[string]any, error) { return s.SaveSecurity(ctx, &biz.SecurityConfig{ ID: value.ID, CaptchaOpen: value.CaptchaOpen, CaptchaTimeout: value.CaptchaTimeout, KeyLong: value.KeyLong, ImgWidth: value.ImgWidth, ImgHeight: value.ImgHeight, PwdMinLength: value.PwdMinLength, PwdRequireUpper: value.PwdRequireUpper, PwdRequireLower: value.PwdRequireLower, PwdRequireDigit: value.PwdRequireDigit, PwdRequireSpecial: value.PwdRequireSpecial, LimitEnable: value.LimitEnable, LimitWindow: value.LimitWindow, LimitCount: value.LimitCount, LockEnable: value.LockEnable, LockThreshold: value.LockThreshold, LockDuration: value.LockDuration, PwdExpireEnable: value.PwdExpireEnable, PwdExpireDays: value.PwdExpireDays, ForceNewUserChangePassword: value.ForceNewUserChangePassword, }) } func (s *SettingsService) ValidatePassword(ctx context.Context, password string) error { cfg, err := s.CurrentSecurity(ctx) if err != nil { return err } if len([]rune(password)) < cfg.PwdMinLength { return errors.New("密码长度不足") } hasUpper, hasLower, hasDigit, hasSpecial := false, false, false, false for _, ch := range password { switch { case ch >= 'A' && ch <= 'Z': hasUpper = true case ch >= 'a' && ch <= 'z': hasLower = true case ch >= '0' && ch <= '9': hasDigit = true default: hasSpecial = true } } if cfg.PwdRequireUpper && !hasUpper { return errors.New("密码必须包含大写字母") } if cfg.PwdRequireLower && !hasLower { return errors.New("密码必须包含小写字母") } if cfg.PwdRequireDigit && !hasDigit { return errors.New("密码必须包含数字") } if cfg.PwdRequireSpecial && !hasSpecial { return errors.New("密码必须包含特殊字符") } return nil }