package services import ( "NetworkAuth/database" "NetworkAuth/models" "strconv" "sync" "github.com/sirupsen/logrus" ) // ============================================================================ // 结构体定义 // ============================================================================ // SettingsService 设置服务 type SettingsService struct { mu sync.RWMutex cache map[string]string } // ============================================================================ // 全局变量 // ============================================================================ var settingsService *SettingsService var settingsOnce sync.Once // ============================================================================ // 公共函数 // ============================================================================ // GetSettingsService 获取设置服务单例 func GetSettingsService() *SettingsService { settingsOnce.Do(func() { settingsService = &SettingsService{ cache: make(map[string]string), } // 初始化时加载所有设置 settingsService.loadAllSettings() }) return settingsService } // ResetSettingsService 充置设置服务单例,主要用于重新加载设置(比如安装后) func ResetSettingsService() { settingsService = &SettingsService{ cache: make(map[string]string), } settingsService.loadAllSettings() } // ============================================================================ // 私有函数 // ============================================================================ // loadAllSettings 从数据库加载所有设置到缓存 func (s *SettingsService) loadAllSettings() { db, err := database.GetDB() if err != nil { logrus.WithError(err).Error("获取数据库连接失败") return } // 如果数据库未初始化,直接返回,保持缓存为空 if db == nil { return } // 检查 settings 表是否存在,如果不存在则不查询 if !db.Migrator().HasTable(&models.Settings{}) { logrus.Info("settings 表不存在,跳过加载设置") return } var settings []models.Settings if err := db.Find(&settings).Error; err != nil { logrus.WithError(err).Error("加载设置失败") return } s.mu.Lock() defer s.mu.Unlock() for _, setting := range settings { s.cache[setting.Name] = setting.Value } logrus.WithField("count", len(settings)).Debug("设置缓存加载完成") } // Set 设置值(用于测试或运行时更新) func (s *SettingsService) Set(name, value string) { s.mu.Lock() defer s.mu.Unlock() s.cache[name] = value } // GetSettingRealtime 实时获取设置值(优先使用Redis缓存,自动回源数据库) // 相比 GetString 的内存缓存,此方法能感知其他实例或直接数据库的变更(在Redis TTL过期后) func (s *SettingsService) GetSettingRealtime(name string) (*models.Settings, error) { db, err := database.GetDB() if err != nil { return nil, err } return FindSettingByName(name, db) } // GetString 获取字符串类型的设置值 func (s *SettingsService) GetString(name, defaultValue string) string { s.mu.RLock() defer s.mu.RUnlock() if value, exists := s.cache[name]; exists { return value } return defaultValue } // GetInt 获取整数类型的设置值 func (s *SettingsService) GetInt(name string, defaultValue int) int { strValue := s.GetString(name, "") if strValue == "" { return defaultValue } if intValue, err := strconv.Atoi(strValue); err == nil { return intValue } return defaultValue } // GetBool 获取布尔类型的设置值 func (s *SettingsService) GetBool(name string, defaultValue bool) bool { strValue := s.GetString(name, "") if strValue == "" { return defaultValue } return strValue == "1" || strValue == "true" } // RefreshCache 刷新设置缓存 func (s *SettingsService) RefreshCache() { s.loadAllSettings() } // IsMaintenanceMode 检查是否开启维护模式 func (s *SettingsService) IsMaintenanceMode() bool { return s.GetBool("maintenance_mode", false) } // GetJWTSecret 获取JWT密钥 func (s *SettingsService) GetJWTSecret() string { return s.GetString("jwt_secret", "") } // GetEncryptionKey 获取加密密钥 func (s *SettingsService) GetEncryptionKey() string { return s.GetString("encryption_key", "") } // GetJWTRefresh 已废弃,请使用 GetRefreshTokenExpireDays func (s *SettingsService) GetJWTRefresh() int { return 0 } // GetJWTExpire 获取 accessToken 有效期(小时) func (s *SettingsService) GetJWTExpire() int { v := s.GetInt("jwt_expire", 2) if v <= 0 { return 2 } return v } // GetRefreshTokenExpireDays 获取 refreshToken 有效期(天) func (s *SettingsService) GetRefreshTokenExpireDays() int { v := s.GetInt("refresh_token_expire_days", 7) if v <= 0 { return 7 } return v } // GetSessionAbsoluteExpireDays 获取会话绝对过期上限(天) func (s *SettingsService) GetSessionAbsoluteExpireDays() int { v := s.GetInt("session_absolute_expire_days", 30) if v <= 0 { return 30 } return v } // GetCookieConfig 获取Cookie配置 func (s *SettingsService) GetCookieConfig() (secure bool, sameSite string, domain string, maxAge int) { secure = s.GetBool("cookie_secure", true) sameSite = s.GetString("cookie_same_site", "Lax") domain = s.GetString("cookie_domain", "") maxAge = s.GetInt("cookie_max_age", 86400) return }