ldap-1-backend/config/config.go

283 lines
15 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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 基础 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
}
// 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"` // 是否同步更新已同步的用户信息
}