Files
MeBox/internal/config/normalize.go
T
2026-09-05 12:34:17 +08:00

83 lines
2.5 KiB
Go

package config
import (
"crypto/rand"
"encoding/hex"
"fmt"
"os"
"path/filepath"
"strings"
)
// normalize 填充派生默认值并自愈空的关键字段。
func (c *Config) normalize() error {
if c.App.DataDir == "" {
c.App.DataDir = "./data"
}
if c.Database.DBPath == "" {
c.Database.DBPath = filepath.Join(c.App.DataDir, "mebox.db")
}
if c.Database.Type == "" {
c.Database.Type = "auto"
}
if c.App.MaxCPUThreads < 1 {
c.App.MaxCPUThreads = 1
}
if c.App.MaxCPUThreads > 8 {
c.App.MaxCPUThreads = 8
}
if c.App.CloudScanMaxConcurrent < 1 {
c.App.CloudScanMaxConcurrent = 1
}
if c.App.CloudScanMaxConcurrent > 16 {
c.App.CloudScanMaxConcurrent = 16
}
if c.Database.MaxOpenConns <= 0 {
c.Database.MaxOpenConns = defaultDatabaseMaxOpenConns
}
if c.Database.MaxIdleConns <= 0 || c.Database.MaxIdleConns > c.Database.MaxOpenConns {
c.Database.MaxIdleConns = defaultDatabaseMaxIdleConns
if c.Database.MaxIdleConns > c.Database.MaxOpenConns {
c.Database.MaxIdleConns = c.Database.MaxOpenConns
}
}
if c.Cache.CacheDir == "" {
c.Cache.CacheDir = filepath.Join(c.App.DataDir, "cache")
}
if c.Cache.ImagesMaxSizeMB < 0 {
c.Cache.ImagesMaxSizeMB = 0
}
if c.Cache.RedisPrefix == "" {
c.Cache.RedisPrefix = "mebox"
}
if c.Cache.MediaTTLSeconds < 1 {
c.Cache.MediaTTLSeconds = 90
}
c.Search.Backend = strings.ToLower(strings.TrimSpace(c.Search.Backend))
if c.Search.Index == "" {
c.Search.Index = "mebox_media"
}
if c.Secrets.JWTSecret == "" {
// 持久化自动生成的密钥以在操作员忘记配置时保持会话稳定。
path := filepath.Join(c.App.DataDir, ".jwt_secret")
if data, err := os.ReadFile(path); err == nil && len(data) > 0 { // #nosec G304 -- path is fixed to .jwt_secret under configured DataDir.
c.Secrets.JWTSecret = strings.TrimSpace(string(data))
} else {
buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
return fmt.Errorf("generate jwt secret: %w", err)
}
c.Secrets.JWTSecret = hex.EncodeToString(buf)
// 持久化失败(DataDir 只读/权限异常)会导致每次重启重新生成
// 密钥、全部会话静默失效、多实例各持不同 secret——必须让
// 操作员感知。
if mkErr := os.MkdirAll(c.App.DataDir, 0o750); mkErr != nil {
fmt.Fprintf(os.Stderr, "warning: persist jwt secret failed (mkdir): %v\n", mkErr)
} else if wErr := os.WriteFile(path, []byte(c.Secrets.JWTSecret), 0o600); wErr != nil {
fmt.Fprintf(os.Stderr, "warning: persist jwt secret failed (write): %v\n", wErr)
}
}
}
return nil
}