This commit is contained in:
Yvan
2026-09-04 16:51:03 +08:00
parent dce95412dd
commit d83720c8fd
3 changed files with 83 additions and 2 deletions
+32
View File
@@ -37,6 +37,29 @@ type SecurityConfig struct {
ForceNewUserChangePassword bool
}
// ErrDatabaseNotInitialized is returned by storage-backed settings that are
// intentionally unavailable during the first-install bootstrap phase.
var ErrDatabaseNotInitialized = errors.New("database not initialized")
// DefaultSecurityConfig matches the seed values used for a fresh installation.
// It is owned by biz so bootstrap callers do not need to depend on data.
func DefaultSecurityConfig() *SecurityConfig {
return &SecurityConfig{
ID: 1,
CaptchaTimeout: 3600,
KeyLong: 6,
ImgWidth: 240,
ImgHeight: 80,
PwdMinLength: 8,
LimitWindow: 60,
LimitCount: 30,
LockThreshold: 5,
LockDuration: 30,
PwdExpireDays: 90,
ForceNewUserChangePassword: false,
}
}
type SecurityRepo interface {
SecurityConfig(context.Context) (*SecurityConfig, error)
SaveSecurityConfig(context.Context, *SecurityConfig) error
@@ -99,8 +122,17 @@ func (uc *SecurityUsecase) Current(ctx context.Context) (*SecurityConfig, error)
uc.mu.RUnlock()
value, err := uc.repo.SecurityConfig(ctx)
if err != nil {
// The login page and captcha are also the entry point for first install.
// Do not cache this fallback: after initdb succeeds the next request must
// load the persisted row instead of serving bootstrap defaults forever.
if errors.Is(err, ErrDatabaseNotInitialized) {
return DefaultSecurityConfig(), nil
}
return nil, err
}
if value == nil {
return nil, errors.New("security config is nil")
}
uc.mu.Lock()
copy := *value
uc.cachedConfig = &copy