/* Package config 负责管理 Go LDAP Admin 系统的所有配置信息 该包使用 Viper 库来读取和管理配置文件,支持: - YAML 格式的配置文件 - 环境变量覆盖配置 - 配置文件热更新 - RSA 密钥嵌入 配置文件结构包括: - 系统配置:运行模式、端口、URL前缀等 - 日志配置:日志级别、路径、轮转策略等 - 数据库配置:MySQL/SQLite 连接信息 - LDAP 配置:OpenLDAP 服务器连接信息 - JWT 配置:Token 生成和验证配置 - 企业 IM 配置:钉钉、企业微信、飞书集成配置 */ package config import ( _ "embed" "fmt" "os" "strconv" "github.com/fsnotify/fsnotify" "github.com/spf13/viper" "go.uber.org/zap/zapcore" ) // Conf 全局配置变量,存储从配置文件和环境变量中读取的所有配置信息 // 系统启动时通过 InitConfig() 函数初始化,之后可在全局范围内访问 var Conf = new(config) // RSA 密钥文件嵌入 // 使用 go:embed 指令将 RSA 私钥和公钥文件嵌入到二进制文件中 // 用于 JWT Token 的签名和验证 //go:embed go-ldap-admin-priv.pem var priv []byte // RSA 私钥,用于 JWT Token 签名 //go:embed go-ldap-admin-pub.pem var pub []byte // RSA 公钥,用于 JWT Token 验证 // config 主配置结构体,包含系统所有模块的配置信息 // 使用 mapstructure 标签将 YAML 配置映射到结构体字段 // YAML 文件中使用 "-" 分隔单词,映射到 Go 的驼峰命名 type config struct { System *SystemConfig `mapstructure:"system" json:"system"` // 系统基础配置 Logs *LogsConfig `mapstructure:"logs" json:"logs"` // 日志配置 Database *Database `mapstructure:"database" json:"database"` // 数据库类型配置 Mysql *MysqlConfig `mapstructure:"mysql" json:"mysql"` // MySQL 数据库配置 Jwt *JwtConfig `mapstructure:"jwt" json:"jwt"` // JWT 认证配置 RateLimit *RateLimitConfig `mapstructure:"rate-limit" json:"rateLimit"` // 限流配置 Ldap *LdapConfig `mapstructure:"ldap" json:"ldap"` // LDAP 服务器配置 Email *EmailConfig `mapstructure:"email" json:"email"` // 邮件服务配置 DingTalk *DingTalkConfig `mapstructure:"dingtalk" json:"dingTalk"` // 钉钉集成配置 WeCom *WeComConfig `mapstructure:"wecom" json:"weCom"` // 企业微信集成配置 FeiShu *FeiShuConfig `mapstructure:"feishu" json:"feiShu"` // 飞书集成配置 } // InitConfig 初始化系统配置 // 该函数负责: // 1. 读取 config.yml 配置文件 // 2. 设置配置文件热更新监听 // 3. 加载嵌入的 RSA 密钥 // 4. 支持环境变量覆盖配置 func InitConfig() { // ==================== 配置文件读取 ==================== // 获取当前工作目录 workDir, err := os.Getwd() if err != nil { panic(fmt.Errorf("读取应用目录失败:%s", err)) } // 配置 Viper 读取配置文件 viper.SetConfigName("config") // 配置文件名(不包含扩展名) viper.SetConfigType("yml") // 配置文件类型 viper.AddConfigPath(workDir + "/") // 配置文件搜索路径 // 读取配置文件内容 err = viper.ReadInConfig() if err != nil { panic(fmt.Errorf("读取配置文件失败:%s", err)) } // ==================== 配置热更新 ==================== // 启用配置文件监听,支持热更新 viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { // 配置文件发生变化时,重新解析配置到全局变量 if err := viper.Unmarshal(Conf); err != nil { panic(fmt.Errorf("热更新配置文件失败:%s", err)) } // 重新加载 RSA 密钥 Conf.System.RSAPublicBytes = pub Conf.System.RSAPrivateBytes = priv }) // ==================== 初始配置解析 ==================== // 将配置文件内容解析到全局配置结构体 if err := viper.Unmarshal(Conf); err != nil { panic(fmt.Errorf("初始化配置文件失败:%s", err)) } // 加载嵌入的 RSA 密钥到配置中 Conf.System.RSAPublicBytes = pub Conf.System.RSAPrivateBytes = priv // ==================== 环境变量覆盖配置 ==================== // 支持通过环境变量覆盖配置文件中的设置,便于容器化部署 // 数据库配置环境变量覆盖 if dbDriver := os.Getenv("DB_DRIVER"); dbDriver != "" { Conf.Database.Driver = dbDriver } if mysqlHost := os.Getenv("MYSQL_HOST"); mysqlHost != "" { Conf.Mysql.Host = mysqlHost } if mysqlUsername := os.Getenv("MYSQL_USERNAME"); mysqlUsername != "" { Conf.Mysql.Username = mysqlUsername } if mysqlPassword := os.Getenv("MYSQL_PASSWORD"); mysqlPassword != "" { Conf.Mysql.Password = mysqlPassword } if mysqlDatabase := os.Getenv("MYSQL_DATABASE"); mysqlDatabase != "" { Conf.Mysql.Database = mysqlDatabase } if mysqlPort := os.Getenv("MYSQL_PORT"); mysqlPort != "" { if port, err := strconv.Atoi(mysqlPort); err == nil { Conf.Mysql.Port = port } } // LDAP 配置环境变量覆盖 if ldapUrl := os.Getenv("LDAP_URL"); ldapUrl != "" { Conf.Ldap.Url = ldapUrl } if ldapBaseDN := os.Getenv("LDAP_BASE_DN"); ldapBaseDN != "" { Conf.Ldap.BaseDN = ldapBaseDN } if ldapAdminDN := os.Getenv("LDAP_ADMIN_DN"); ldapAdminDN != "" { Conf.Ldap.AdminDN = ldapAdminDN } if ldapAdminPass := os.Getenv("LDAP_ADMIN_PASS"); ldapAdminPass != "" { Conf.Ldap.AdminPass = ldapAdminPass } if ldapUserDN := os.Getenv("LDAP_USER_DN"); ldapUserDN != "" { Conf.Ldap.UserDN = ldapUserDN } if ldapUserInitPassword := os.Getenv("LDAP_USER_INIT_PASSWORD"); ldapUserInitPassword != "" { Conf.Ldap.UserInitPassword = ldapUserInitPassword } if ldapDefaultEmailSuffix := os.Getenv("LDAP_DEFAULT_EMAIL_SUFFIX"); ldapDefaultEmailSuffix != "" { Conf.Ldap.DefaultEmailSuffix = ldapDefaultEmailSuffix } if ldapUserPasswordEncryptionType := os.Getenv("LDAP_USER_PASSWORD_ENCRYPTION_TYPE"); ldapUserPasswordEncryptionType != "" { Conf.Ldap.UserPasswordEncryptionType = ldapUserPasswordEncryptionType } } // ==================== 配置结构体定义 ==================== // SystemConfig 系统基础配置 type SystemConfig struct { Mode string `mapstructure:"mode" json:"mode"` // 运行模式:debug/release/test UrlPathPrefix string `mapstructure:"url-path-prefix" json:"urlPathPrefix"` // API URL 前缀 Port int `mapstructure:"port" json:"port"` // HTTP 服务监听端口 InitData bool `mapstructure:"init-data" json:"initData"` // 是否初始化基础数据 RSAPublicBytes []byte `mapstructure:"-" json:"-"` // RSA 公钥字节数组(不序列化) RSAPrivateBytes []byte `mapstructure:"-" json:"-"` // RSA 私钥字节数组(不序列化) } // LogsConfig 日志系统配置 type LogsConfig struct { Level zapcore.Level `mapstructure:"level" json:"level"` // 日志级别(-1:Debug, 0:Info, 1:Warn, 2:Error, 3:DPanic, 4:Panic, 5:Fatal) Path string `mapstructure:"path" json:"path"` // 日志文件存储路径 MaxSize int `mapstructure:"max-size" json:"maxSize"` // 单个日志文件最大大小(MB) MaxBackups int `mapstructure:"max-backups" json:"maxBackups"` // 保留的日志文件备份数量 MaxAge int `mapstructure:"max-age" json:"maxAge"` // 日志文件保留天数 Compress bool `mapstructure:"compress" json:"compress"` // 是否压缩旧日志文件 } // Database 数据库类型配置 type Database struct { Driver string `mapstructure:"driver" json:"driver"` // 数据库驱动类型:mysql/sqlite3 Source string `mapstructure:"source" json:"source"` // SQLite 数据库文件路径 } // MysqlConfig MySQL 数据库连接配置 type MysqlConfig struct { Username string `mapstructure:"username" json:"username"` // 数据库用户名 Password string `mapstructure:"password" json:"password"` // 数据库密码 Database string `mapstructure:"database" json:"database"` // 数据库名称 Host string `mapstructure:"host" json:"host"` // 数据库主机地址 Port int `mapstructure:"port" json:"port"` // 数据库端口 Query string `mapstructure:"query" json:"query"` // 连接字符串参数 LogMode bool `mapstructure:"log-mode" json:"logMode"` // 是否开启 SQL 日志 TablePrefix string `mapstructure:"table-prefix" json:"tablePrefix"` // 数据表前缀 Charset string `mapstructure:"charset" json:"charset"` // 字符编码 Collation string `mapstructure:"collation" json:"collation"` // 字符集排序规则 } // JwtConfig JWT 认证配置 type JwtConfig struct { Realm string `mapstructure:"realm" json:"realm"` // JWT 标识符 Key string `mapstructure:"key" json:"key"` // JWT 签名密钥 Timeout int `mapstructure:"timeout" json:"timeout"` // Token 过期时间(小时) MaxRefresh int `mapstructure:"max-refresh" json:"maxRefresh"` // 刷新 Token 最大过期时间(小时) } // RateLimitConfig 限流配置(令牌桶算法) type RateLimitConfig struct { FillInterval int64 `mapstructure:"fill-interval" json:"fillInterval"` // 填充一个令牌的时间间隔(毫秒) Capacity int64 `mapstructure:"capacity" json:"capacity"` // 令牌桶容量 } // LdapConfig LDAP 服务器连接配置 type LdapConfig struct { Url string `mapstructure:"url" json:"url"` // LDAP 服务器地址(如:ldap://localhost:389) MaxConn int `mapstructure:"max-conn" json:"maxConn"` // LDAP 连接池最大连接数 BaseDN string `mapstructure:"base-dn" json:"baseDN"` // LDAP 基础 DN(如:dc=example,dc=com) AdminDN string `mapstructure:"admin-dn" json:"adminDN"` // LDAP 管理员 DN AdminPass string `mapstructure:"admin-pass" json:"adminPass"` // LDAP 管理员密码 UserDN string `mapstructure:"user-dn" json:"userDN"` // 用户 OU DN(如:ou=people,dc=example,dc=com) UserInitPassword string `mapstructure:"user-init-password" json:"userInitPassword"` // 新用户默认密码 GroupNameModify bool `mapstructure:"group-name-modify" json:"groupNameModify"` // 是否允许修改组 DN UserNameModify bool `mapstructure:"user-name-modify" json:"userNameModify"` // 是否允许修改用户 DN DefaultEmailSuffix string `mapstructure:"default-email-suffix" json:"defaultEmailSuffix"` // 默认邮箱后缀 UserPasswordEncryptionType string `mapstructure:"user-password-encryption-type" json:"userPasswordEncryptionType"` // 用户密码加密方式(ssha/clear) } // EmailConfig 邮件服务配置 type EmailConfig struct { Host string `mapstructure:"host" json:"host"` // SMTP 服务器地址 Port string `mapstructure:"port" json:"port"` // SMTP 服务器端口 User string `mapstructure:"user" json:"user"` // 邮箱用户名 Pass string `mapstructure:"pass" json:"pass"` // 邮箱密码或授权码 From string `mapstructure:"from" json:"from"` // 发件人显示名称 } // DingTalkConfig 钉钉集成配置 type DingTalkConfig struct { AppKey string `mapstructure:"app-key" json:"appKey"` // 钉钉应用 Key AppSecret string `mapstructure:"app-secret" json:"appSecret"` // 钉钉应用 Secret AgentId string `mapstructure:"agent-id" json:"agentId"` // 钉钉应用 Agent ID RootOuName string `mapstructure:"root-ou-name" json:"rootOuName"` // 根部门名称 Flag string `mapstructure:"flag" json:"flag"` // 钉钉在平台的标识 EnableSync bool `mapstructure:"enable-sync" json:"enableSync"` // 是否开启定时同步 DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"` // 部门同步时间(Cron 表达式) UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"` // 用户同步时间(Cron 表达式) DeptList []string `mapstructure:"dept-list" json:"deptList"` // 要同步的部门列表(空则同步所有) IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` // 是否同步更新已同步的用户信息 ULeaveRange uint `mapstructure:"user-leave-range" json:"userLevelRange"` // 离职用户查询天数范围 } // WeComConfig 企业微信集成配置 type WeComConfig struct { Flag string `mapstructure:"flag" json:"flag"` // 企业微信在平台的标识 CorpID string `mapstructure:"corp-id" json:"corpId"` // 企业微信企业 ID AgentID int `mapstructure:"agent-id" json:"agentId"` // 企业微信应用 ID CorpSecret string `mapstructure:"corp-secret" json:"corpSecret"` // 企业微信应用 Secret EnableSync bool `mapstructure:"enable-sync" json:"enableSync"` // 是否开启定时同步 DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"` // 部门同步时间(Cron 表达式) UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"` // 用户同步时间(Cron 表达式) IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` // 是否同步更新已同步的用户信息 } // FeiShuConfig 飞书集成配置 type FeiShuConfig struct { Flag string `mapstructure:"flag" json:"flag"` // 飞书在平台的标识 AppID string `mapstructure:"app-id" json:"appId"` // 飞书应用 ID AppSecret string `mapstructure:"app-secret" json:"appSecret"` // 飞书应用 Secret EnableSync bool `mapstructure:"enable-sync" json:"enableSync"` // 是否开启定时同步 DeptSyncTime string `mapstructure:"dept-sync-time" json:"deptSyncTime"` // 部门同步时间(Cron 表达式) UserSyncTime string `mapstructure:"user-sync-time" json:"userSyncTime"` // 用户同步时间(Cron 表达式) DeptList []string `mapstructure:"dept-list" json:"deptList"` // 要同步的部门列表(空则同步所有) IsUpdateSyncd bool `mapstructure:"is-update-syncd" json:"isUpdateSyncd"` // 是否同步更新已同步的用户信息 }