173 lines
5.0 KiB
Go
173 lines
5.0 KiB
Go
package config
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Config 全局配置结构
|
|
type Config struct {
|
|
App AppConfig `mapstructure:"app"`
|
|
Server ServerConfig `mapstructure:"server"`
|
|
Database DatabaseConfig `mapstructure:"database"`
|
|
JWT JWTConfig `mapstructure:"jwt"`
|
|
Log LogConfig `mapstructure:"log"`
|
|
Encryption EncryptionConfig `mapstructure:"encryption"`
|
|
WireGuard WireGuardConfig `mapstructure:"wireguard"`
|
|
STUN STUNConfig `mapstructure:"stun"`
|
|
TURN TURNConfig `mapstructure:"turn"`
|
|
}
|
|
|
|
// AppConfig 应用配置
|
|
type AppConfig struct {
|
|
Version string `mapstructure:"version"` // 版本号
|
|
BuildDate string `mapstructure:"build_date"` // 构建日期
|
|
}
|
|
|
|
// ServerConfig 服务器配置
|
|
type ServerConfig struct {
|
|
Port int `mapstructure:"port"`
|
|
Mode string `mapstructure:"mode"` // debug, release, test
|
|
StaticPath string `mapstructure:"static_path"` // 前端静态文件目录
|
|
}
|
|
|
|
// DatabaseConfig 数据库配置
|
|
type DatabaseConfig struct {
|
|
Type string `mapstructure:"type"`
|
|
Path string `mapstructure:"path"`
|
|
}
|
|
|
|
// JWTConfig JWT 配置
|
|
type JWTConfig struct {
|
|
Secret string `mapstructure:"secret"`
|
|
AccessTokenDur string `mapstructure:"access_token_duration"`
|
|
RefreshTokenDur string `mapstructure:"refresh_token_duration"`
|
|
}
|
|
|
|
// LogConfig 日志配置
|
|
type LogConfig struct {
|
|
Level string `mapstructure:"level"`
|
|
Format string `mapstructure:"format"`
|
|
Output string `mapstructure:"output"`
|
|
MaxSize int `mapstructure:"max_size"`
|
|
MaxBackups int `mapstructure:"max_backups"`
|
|
MaxAge int `mapstructure:"max_age"`
|
|
}
|
|
|
|
// EncryptionConfig 加密配置
|
|
type EncryptionConfig struct {
|
|
NetworkSecretKey string `mapstructure:"network_secret_key"`
|
|
}
|
|
|
|
// WireGuardConfig WireGuard 配置(固定使用用户态)
|
|
type WireGuardConfig struct {
|
|
// 已删除 PreferredMode 字段 - 统一使用 wireguard-go 用户态
|
|
}
|
|
|
|
// STUNConfig STUN 配置
|
|
type STUNConfig struct {
|
|
DefaultServers []string `mapstructure:"default_servers"` // 默认 STUN 服务器列表
|
|
SelectionStrategy string `mapstructure:"selection_strategy"` // 选择策略:auto, domestic, international, custom
|
|
AutoTest bool `mapstructure:"auto_test"` // 是否启用自动测试
|
|
TestInterval int `mapstructure:"test_interval"` // 测试间隔(秒)
|
|
Timeout int `mapstructure:"timeout"` // 超时时间(秒)
|
|
}
|
|
|
|
// TURNConfig TURN 配置
|
|
type TURNConfig struct {
|
|
DefaultServers []TURNServerConfig `mapstructure:"default_servers"` // 默认 TURN 服务器列表
|
|
}
|
|
|
|
// TURNServerConfig TURN 服务器配置
|
|
type TURNServerConfig struct {
|
|
URL string `mapstructure:"url"` // TURN 服务器 URL
|
|
Username string `mapstructure:"username"` // 用户名
|
|
Credential string `mapstructure:"credential"` // 凭证
|
|
AuthType string `mapstructure:"auth_type"` // 鉴权方式:credential, token, secret
|
|
}
|
|
|
|
// Load 加载配置文件
|
|
func Load(configPath string) (*Config, error) {
|
|
// 如果未指定配置文件路径,使用默认路径
|
|
if configPath == "" {
|
|
configPath = "config.yaml"
|
|
}
|
|
|
|
// 检查配置文件是否存在
|
|
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
|
// 尝试从示例文件复制
|
|
examplePath := "configs/config.example.yaml"
|
|
if _, err := os.Stat(examplePath); err == nil {
|
|
// 创建目录
|
|
dir := filepath.Dir(configPath)
|
|
if dir != "." {
|
|
os.MkdirAll(dir, 0755)
|
|
}
|
|
// 复制示例配置
|
|
data, _ := os.ReadFile(examplePath)
|
|
os.WriteFile(configPath, data, 0644)
|
|
}
|
|
}
|
|
|
|
// 读取配置文件
|
|
viper.SetConfigFile(configPath)
|
|
viper.AutomaticEnv()
|
|
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
return nil, fmt.Errorf("读取配置文件失败:%w", err)
|
|
}
|
|
|
|
var config Config
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf("解析配置文件失败:%w", err)
|
|
}
|
|
|
|
// 自动填充默认值
|
|
if config.Server.Port == 0 {
|
|
config.Server.Port = 9531
|
|
}
|
|
if config.Server.Mode == "" {
|
|
config.Server.Mode = "release"
|
|
}
|
|
|
|
// 自动生成 JWT Secret
|
|
if config.JWT.Secret == "" {
|
|
config.JWT.Secret = generateJWTSecret()
|
|
}
|
|
|
|
// 自动生成加密密钥
|
|
if config.Encryption.NetworkSecretKey == "" {
|
|
config.Encryption.NetworkSecretKey = generateEncryptionKey()
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// generateJWTSecret 使用 crypto/rand 生成随机 JWT Secret
|
|
func generateJWTSecret() string {
|
|
b := make([]byte, 32)
|
|
_, err := rand.Read(b)
|
|
if err != nil {
|
|
// 极端情况回退(几乎不会发生)
|
|
return uuid.New().String()
|
|
}
|
|
return hex.EncodeToString(b)
|
|
}
|
|
|
|
// generateEncryptionKey 使用 crypto/rand 生成加密密钥
|
|
func generateEncryptionKey() string {
|
|
key := make([]byte, 32)
|
|
_, err := rand.Read(key)
|
|
if err != nil {
|
|
// 极端情况回退(几乎不会发生)
|
|
return uuid.New().String() + uuid.New().String()
|
|
}
|
|
return hex.EncodeToString(key)
|
|
}
|