ldap-1-backend/main.go

158 lines
5.0 KiB
Go
Raw Permalink Normal View History

2025-08-26 00:43:50 +08:00
/*
Package main Go LDAP Admin 项目的主入口文件
Go LDAP Admin 是一个基于 Go + Vue 实现的 OpenLDAP 后台管理系统
旨在为 OpenLDAP 服务端提供一个简单易用清晰美观的现代化管理后台
主要功能
- 用户管理支持用户的增删改查密码管理等
- 组织架构管理支持部门/组的层级管理
- 权限控制基于 RBAC 的角色权限管理
- LDAP 集成 OpenLDAP 服务器双向同步
- 企业 IM 集成支持钉钉企业微信飞书等平台同步
- 操作审计完整的操作日志记录
技术栈
- Web 框架Gin
- ORMGORM
- 数据库MySQL/SQLite
- 权限控制Casbin
- LDAP 客户端go-ldap
- 认证JWT
*/
2022-05-18 17:57:03 +08:00
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"time"
"github.com/eryajf/go-ldap-admin/logic"
2022-05-29 10:06:21 +08:00
"github.com/eryajf/go-ldap-admin/config"
"github.com/eryajf/go-ldap-admin/middleware"
"github.com/eryajf/go-ldap-admin/public/common"
"github.com/eryajf/go-ldap-admin/routes"
"github.com/eryajf/go-ldap-admin/service/isql"
2022-05-18 17:57:03 +08:00
)
2025-08-26 00:43:50 +08:00
// Swagger API 文档配置
// @title Go Ldap Admin
// @version 1.0
// @description 基于Go+Vue实现的openLDAP后台管理项目
// @termsOfService https://github.com/eryajf/go-ldap-admin
// @contact.name 项目作者:二丫讲梵 、 swagger作者南宫乘风
// @contact.url https://github.com/eryajf/go-ldap-admin
// @contact.email https://github.com/eryajf/go-ldap-admin
// @host 127.0.0.1:8888
// @BasePath /api
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
2025-08-26 00:43:50 +08:00
// main 函数是程序的入口点,负责初始化各个组件并启动 HTTP 服务器
2022-05-18 17:57:03 +08:00
func main() {
2025-08-26 00:43:50 +08:00
// ==================== 系统初始化阶段 ====================
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 1. 加载配置文件到全局配置结构体
// 从 config.yml 文件中读取系统配置包括数据库、LDAP、JWT 等配置信息
2022-05-18 17:57:03 +08:00
config.InitConfig()
2025-08-26 00:43:50 +08:00
// 2. 初始化日志系统
// 配置 zap 日志库,设置日志级别、输出格式、文件轮转等
2022-05-18 17:57:03 +08:00
common.InitLogger()
2025-08-26 00:43:50 +08:00
// 3. 初始化数据库连接
// 根据配置连接 MySQL 或 SQLite 数据库,建立连接池
common.InitDB()
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 4. 初始化 LDAP 连接
// 建立与 OpenLDAP 服务器的连接池,用于用户认证和数据同步
2022-05-18 17:57:03 +08:00
common.InitLDAP()
2025-08-26 00:43:50 +08:00
// 5. 初始化 Casbin 策略管理器
// 加载 RBAC 权限模型,用于接口级别的权限控制
2022-05-18 17:57:03 +08:00
common.InitCasbinEnforcer()
2025-08-26 00:43:50 +08:00
// 6. 初始化数据校验器
// 配置 gin 的数据校验器,用于请求参数验证
2022-05-18 17:57:03 +08:00
common.InitValidate()
2025-08-26 00:43:50 +08:00
// 7. 初始化基础数据
// 如果是首次启动,会创建默认的管理员账户、角色、菜单等基础数据
2022-05-18 17:57:03 +08:00
common.InitData()
2025-08-26 00:43:50 +08:00
// ==================== 后台服务启动 ====================
// 启动操作日志处理协程
// 操作日志中间件将日志发送到 channel 中,这里启动 3 个 goroutine
// 异步处理 channel 中的日志并写入数据库,提高系统性能
2022-05-18 17:57:03 +08:00
for i := 0; i < 3; i++ {
go isql.OperationLog.SaveOperationLogChannel(middleware.OperationLogChan)
}
2025-08-26 00:43:50 +08:00
// ==================== HTTP 服务器配置 ====================
2022-05-18 17:57:03 +08:00
// 注册所有路由
2025-08-26 00:43:50 +08:00
// 包括用户管理、组织架构、权限管理、系统管理等所有 API 路由
2022-05-18 17:57:03 +08:00
r := routes.InitRoutes()
2025-08-26 00:43:50 +08:00
// 配置服务器监听地址和端口
host := "0.0.0.0" // 监听所有网络接口
port := config.Conf.System.Port // 从配置文件读取端口号
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 创建 HTTP 服务器实例
2022-05-18 17:57:03 +08:00
srv := &http.Server{
Addr: fmt.Sprintf("%s:%d", host, port),
Handler: r,
}
2025-08-26 00:43:50 +08:00
// ==================== 服务器启动 ====================
// 在单独的 goroutine 中启动 HTTP 服务器
// 这样不会阻塞后续的优雅关闭处理逻辑
2022-05-18 17:57:03 +08:00
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
2025-08-26 00:43:50 +08:00
common.Log.Fatalf("HTTP 服务器启动失败: %s\n", err)
2022-05-18 17:57:03 +08:00
}
}()
2025-08-26 00:43:50 +08:00
// 启动定时任务调度器
// 用于执行企业 IM 同步、数据清理等定时任务
logic.InitCron()
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 输出服务器启动成功信息
common.Log.Info(fmt.Sprintf("🚀 Go LDAP Admin 服务器启动成功! 访问地址: http://%s:%d", host, port))
// ==================== 优雅关闭处理 ====================
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 创建信号接收通道,用于接收系统关闭信号
quit := make(chan os.Signal, 1)
2025-08-26 00:43:50 +08:00
// 注册信号处理
// kill (无参数) 默认发送 syscall.SIGTERM 信号
// kill -2 发送 syscall.SIGINT 信号 (Ctrl+C)
// kill -9 发送 syscall.SIGKILL 信号,但无法被捕获,所以不需要处理
signal.Notify(quit, os.Interrupt)
2025-08-26 00:43:50 +08:00
// 阻塞等待关闭信号
2022-05-18 17:57:03 +08:00
<-quit
2025-08-26 00:43:50 +08:00
common.Log.Info("🛑 接收到关闭信号,开始优雅关闭服务器...")
2022-05-18 17:57:03 +08:00
2025-08-26 00:43:50 +08:00
// 创建带超时的上下文,给服务器 5 秒时间完成当前正在处理的请求
2022-05-18 17:57:03 +08:00
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
2025-08-26 00:43:50 +08:00
// 优雅关闭服务器
2022-05-18 17:57:03 +08:00
if err := srv.Shutdown(ctx); err != nil {
2025-08-26 00:43:50 +08:00
common.Log.Fatal("❌ 服务器强制关闭:", err)
2022-05-18 17:57:03 +08:00
}
2025-08-26 00:43:50 +08:00
common.Log.Info("✅ 服务器已安全退出!")
2022-05-18 17:57:03 +08:00
}