99 lines
3.8 KiB
Go
99 lines
3.8 KiB
Go
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
|
|
}
|