ldap-1-backend/config/config.go

283 lines
15 KiB
Go
Raw Permalink Normal View History

2025-08-26 00:43:50 +08:00
/*
Package config 负责管理 Go LDAP Admin 系统的所有配置信息
该包使用 Viper 库来读取和管理配置文件支持
- YAML 格式的配置文件
- 环境变量覆盖配置
- 配置文件热更新
- RSA 密钥嵌入
配置文件结构包括
- 系统配置运行模式端口URL前缀等
- 日志配置日志级别路径轮转策略等
- 数据库配置MySQL/SQLite 连接信息
- LDAP 配置OpenLDAP 服务器连接信息
- JWT 配置Token 生成和验证配置
- 企业 IM 配置钉钉企业微信飞书集成配置
*/
2022-05-18 17:57:03 +08:00
package config
import (
_ "embed"
2022-05-18 17:57:03 +08:00
"fmt"
"os"
"strconv"
2022-05-18 17:57:03 +08:00
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"go.uber.org/zap/zapcore"
)
2025-08-26 00:43:50 +08:00
// Conf 全局配置变量,存储从配置文件和环境变量中读取的所有配置信息
// 系统启动时通过 InitConfig() 函数初始化,之后可在全局范围内访问
2022-05-18 17:57:03 +08:00
var Conf = new(config)
2025-08-26 00:43:50 +08:00
// RSA 密钥文件嵌入
// 使用 go:embed 指令将 RSA 私钥和公钥文件嵌入到二进制文件中
// 用于 JWT Token 的签名和验证
//go:embed go-ldap-admin-priv.pem
2025-08-26 00:43:50 +08:00
var priv []byte // RSA 私钥,用于 JWT Token 签名
//go:embed go-ldap-admin-pub.pem
2025-08-26 00:43:50 +08:00
var pub []byte // RSA 公钥,用于 JWT Token 验证
2025-08-26 00:43:50 +08:00
// config 主配置结构体,包含系统所有模块的配置信息
// 使用 mapstructure 标签将 YAML 配置映射到结构体字段
// YAML 文件中使用 "-" 分隔单词,映射到 Go 的驼峰命名
2022-05-18 17:57:03 +08:00
type config struct {
2025-08-26 00:43:50 +08:00
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"` // 飞书集成配置
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// InitConfig 初始化系统配置
// 该函数负责:
// 1. 读取 config.yml 配置文件
// 2. 设置配置文件热更新监听
// 3. 加载嵌入的 RSA 密钥
// 4. 支持环境变量覆盖配置
2022-05-18 17:57:03 +08:00
func InitConfig() {
2025-08-26 00:43:50 +08:00
// ==================== 配置文件读取 ====================
// 获取当前工作目录
2022-05-18 17:57:03 +08:00
workDir, err := os.Getwd()
if err != nil {
panic(fmt.Errorf("读取应用目录失败:%s", err))
}
2025-08-26 00:43:50 +08:00
// 配置 Viper 读取配置文件
viper.SetConfigName("config") // 配置文件名(不包含扩展名)
viper.SetConfigType("yml") // 配置文件类型
viper.AddConfigPath(workDir + "/") // 配置文件搜索路径
// 读取配置文件内容
2022-05-18 17:57:03 +08:00
err = viper.ReadInConfig()
2025-08-26 00:43:50 +08:00
if err != nil {
panic(fmt.Errorf("读取配置文件失败:%s", err))
}
// ==================== 配置热更新 ====================
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 启用配置文件监听,支持热更新
2022-05-18 17:57:03 +08:00
viper.WatchConfig()
viper.OnConfigChange(func(e fsnotify.Event) {
2025-08-26 00:43:50 +08:00
// 配置文件发生变化时,重新解析配置到全局变量
2022-05-18 17:57:03 +08:00
if err := viper.Unmarshal(Conf); err != nil {
2025-08-26 00:43:50 +08:00
panic(fmt.Errorf("热更新配置文件失败:%s", err))
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// 重新加载 RSA 密钥
Conf.System.RSAPublicBytes = pub
Conf.System.RSAPrivateBytes = priv
2022-05-18 17:57:03 +08:00
})
2025-08-26 00:43:50 +08:00
// ==================== 初始配置解析 ====================
// 将配置文件内容解析到全局配置结构体
2022-05-18 17:57:03 +08:00
if err := viper.Unmarshal(Conf); err != nil {
panic(fmt.Errorf("初始化配置文件失败:%s", err))
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// 加载嵌入的 RSA 密钥到配置中
Conf.System.RSAPublicBytes = pub
Conf.System.RSAPrivateBytes = priv
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// ==================== 环境变量覆盖配置 ====================
// 支持通过环境变量覆盖配置文件中的设置,便于容器化部署
// 数据库配置环境变量覆盖
if dbDriver := os.Getenv("DB_DRIVER"); dbDriver != "" {
Conf.Database.Driver = dbDriver
}
2025-08-26 00:43:50 +08:00
if mysqlHost := os.Getenv("MYSQL_HOST"); mysqlHost != "" {
Conf.Mysql.Host = mysqlHost
}
2025-08-26 00:43:50 +08:00
if mysqlUsername := os.Getenv("MYSQL_USERNAME"); mysqlUsername != "" {
Conf.Mysql.Username = mysqlUsername
}
2025-08-26 00:43:50 +08:00
if mysqlPassword := os.Getenv("MYSQL_PASSWORD"); mysqlPassword != "" {
Conf.Mysql.Password = mysqlPassword
}
2025-08-26 00:43:50 +08:00
if mysqlDatabase := os.Getenv("MYSQL_DATABASE"); mysqlDatabase != "" {
Conf.Mysql.Database = mysqlDatabase
}
2025-08-26 00:43:50 +08:00
if mysqlPort := os.Getenv("MYSQL_PORT"); mysqlPort != "" {
if port, err := strconv.Atoi(mysqlPort); err == nil {
Conf.Mysql.Port = port
}
}
2025-08-26 00:43:50 +08:00
// LDAP 配置环境变量覆盖
if ldapUrl := os.Getenv("LDAP_URL"); ldapUrl != "" {
Conf.Ldap.Url = ldapUrl
}
2025-08-26 00:43:50 +08:00
if ldapBaseDN := os.Getenv("LDAP_BASE_DN"); ldapBaseDN != "" {
Conf.Ldap.BaseDN = ldapBaseDN
}
2025-08-26 00:43:50 +08:00
if ldapAdminDN := os.Getenv("LDAP_ADMIN_DN"); ldapAdminDN != "" {
Conf.Ldap.AdminDN = ldapAdminDN
}
2025-08-26 00:43:50 +08:00
if ldapAdminPass := os.Getenv("LDAP_ADMIN_PASS"); ldapAdminPass != "" {
Conf.Ldap.AdminPass = ldapAdminPass
}
2025-08-26 00:43:50 +08:00
if ldapUserDN := os.Getenv("LDAP_USER_DN"); ldapUserDN != "" {
Conf.Ldap.UserDN = ldapUserDN
}
2025-08-26 00:43:50 +08:00
if ldapUserInitPassword := os.Getenv("LDAP_USER_INIT_PASSWORD"); ldapUserInitPassword != "" {
Conf.Ldap.UserInitPassword = ldapUserInitPassword
}
2025-08-26 00:43:50 +08:00
if ldapDefaultEmailSuffix := os.Getenv("LDAP_DEFAULT_EMAIL_SUFFIX"); ldapDefaultEmailSuffix != "" {
Conf.Ldap.DefaultEmailSuffix = ldapDefaultEmailSuffix
}
2025-08-26 00:43:50 +08:00
if ldapUserPasswordEncryptionType := os.Getenv("LDAP_USER_PASSWORD_ENCRYPTION_TYPE"); ldapUserPasswordEncryptionType != "" {
Conf.Ldap.UserPasswordEncryptionType = ldapUserPasswordEncryptionType
}
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// ==================== 配置结构体定义 ====================
// SystemConfig 系统基础配置
2022-05-18 17:57:03 +08:00
type SystemConfig struct {
2025-08-26 00:43:50 +08:00
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 私钥字节数组(不序列化)
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// LogsConfig 日志系统配置
2022-05-18 17:57:03 +08:00
type LogsConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 是否压缩旧日志文件
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// Database 数据库类型配置
type Database struct {
2025-08-26 00:43:50 +08:00
Driver string `mapstructure:"driver" json:"driver"` // 数据库驱动类型mysql/sqlite3
Source string `mapstructure:"source" json:"source"` // SQLite 数据库文件路径
}
2025-08-26 00:43:50 +08:00
// MysqlConfig MySQL 数据库连接配置
2022-05-18 17:57:03 +08:00
type MysqlConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 字符集排序规则
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// JwtConfig JWT 认证配置
2022-05-18 17:57:03 +08:00
type JwtConfig struct {
2025-08-26 00:43:50 +08:00
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 最大过期时间(小时)
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// RateLimitConfig 限流配置(令牌桶算法)
2022-05-18 17:57:03 +08:00
type RateLimitConfig struct {
2025-08-26 00:43:50 +08:00
FillInterval int64 `mapstructure:"fill-interval" json:"fillInterval"` // 填充一个令牌的时间间隔(毫秒)
Capacity int64 `mapstructure:"capacity" json:"capacity"` // 令牌桶容量
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// LdapConfig LDAP 服务器连接配置
2022-05-18 17:57:03 +08:00
type LdapConfig struct {
2025-08-26 00:43:50 +08:00
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 基础 DNdc=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 DNou=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
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// EmailConfig 邮件服务配置
2022-05-18 17:57:03 +08:00
type EmailConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 发件人显示名称
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
// DingTalkConfig 钉钉集成配置
type DingTalkConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 离职用户查询天数范围
}
2025-08-26 00:43:50 +08:00
// WeComConfig 企业微信集成配置
type WeComConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 是否同步更新已同步的用户信息
}
2025-08-26 00:43:50 +08:00
// FeiShuConfig 飞书集成配置
type FeiShuConfig struct {
2025-08-26 00:43:50 +08:00
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"` // 是否同步更新已同步的用户信息
}