package models import ( "sync" "gorm.io/gorm" ) // configCache holds process-level caches of platform configuration so that // per-request rendering and upload validation do not hit the database. The // cache is populated once at startup and refreshed whenever an admin saves a // settings page (see RefreshConfigCache / the admin handlers). var configCache = struct { mu sync.RWMutex site *SiteSetting upload *UploadConfig types []UploadFileType baseURLs []DownloadBaseURL }{ site: &SiteSetting{}, upload: &UploadConfig{Enabled: true, DefaultMaxSize: DefaultUploadMaxSize, StorageDir: "attachments"}, } // LoadConfigCache reads all platform configuration from the database into the // process cache. Called once at startup after InitDB. func LoadConfigCache(db *gorm.DB) { configCache.mu.Lock() defer configCache.mu.Unlock() var s SiteSetting if err := db.First(&s, 1).Error; err == nil { configCache.site = &s } else { configCache.site = &SiteSetting{ID: 1} } var u UploadConfig if err := db.First(&u, 1).Error; err == nil { configCache.upload = &u } else { configCache.upload = &UploadConfig{ID: 1, Enabled: true, DefaultMaxSize: DefaultUploadMaxSize, StorageDir: "attachments"} } var t []UploadFileType if err := db.Order("sort asc, id asc").Find(&t).Error; err == nil { configCache.types = t } var b []DownloadBaseURL if err := db.Order("is_default desc, priority asc, id asc").Find(&b).Error; err == nil { configCache.baseURLs = b } } // RefreshConfigCache reloads all cached platform configuration. Admin handlers // call this after writing changes so the next request sees them. func RefreshConfigCache(db *gorm.DB) { LoadConfigCache(db) } // GetSiteSetting returns a pointer to the cached site settings (read-only copy // semantics: callers must not mutate). func GetSiteSetting() *SiteSetting { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.site } // GetUploadConfig returns the cached upload policy. func GetUploadConfig() *UploadConfig { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.upload } // GetUploadFileTypes returns the cached list of permitted file types. func GetUploadFileTypes() []UploadFileType { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.types } // GetDownloadBaseURLs returns the cached list of download base URLs. func GetDownloadBaseURLs() []DownloadBaseURL { configCache.mu.RLock() defer configCache.mu.RUnlock() return configCache.baseURLs } // DefaultDownloadBaseURL returns the base URL used to build attachment download // links: the enabled row marked IsDefault, else the highest-priority enabled // row. Returns an empty string if none is configured. func DefaultDownloadBaseURL() string { configCache.mu.RLock() defer configCache.mu.RUnlock() // Rows are ordered is_default desc, priority asc, so the first enabled row // is the right pick. for _, b := range configCache.baseURLs { if b.Enabled { return b.BaseURL } } return "" }