package service import ( "context" "sync" "time" "kra/internal/biz" "kra/internal/conf" ) type SettingsService struct { uc *biz.SettingsUsecase runtime *conf.Runtime securityMu sync.RWMutex securityCache *biz.SecurityConfig cache biz.Cache } func NewSettingsService(uc *biz.SettingsUsecase, runtime *conf.Runtime, cache biz.Cache) *SettingsService { return &SettingsService{uc: uc, runtime: runtime, cache: cache} } func (s *SettingsService) CacheGet(ctx context.Context, key string) (string, bool, error) { return s.cache.Get(ctx, key) } func (s *SettingsService) CacheSet(ctx context.Context, key, value string, expiration time.Duration) error { return s.cache.Set(ctx, key, value, expiration) } func (s *SettingsService) CacheDelete(ctx context.Context, key string) error { return s.cache.Delete(ctx, key) } func (s *SettingsService) CacheIncrement(ctx context.Context, key string, expiration time.Duration) (int64, error) { return s.cache.Increment(ctx, key, expiration) } func (s *SettingsService) UseMultipoint() bool { config := s.runtime.Admin() return config != nil && config.System != nil && config.System.UseMultipoint } func activeTokenKey(username string) string { return "jwt:active:" + username } func (s *SettingsService) ActiveTokenMatches(ctx context.Context, username, token string) (bool, error) { if !s.UseMultipoint() { return true, nil } active, ok, err := s.CacheGet(ctx, activeTokenKey(username)) return ok && active == token, err } func (s *SettingsService) RotateActiveToken(ctx context.Context, username, oldToken, newToken string, expiration time.Duration) error { if !s.UseMultipoint() { return nil } if oldToken != "" && oldToken != newToken { if err := s.BlacklistToken(ctx, oldToken); err != nil { return err } } return s.CacheSet(ctx, activeTokenKey(username), newToken, expiration) }