feat: 后端认证和工具模块更新
- main.go: 添加 Swagger 文档、初始化默认管理员 - 认证模块: 完善用户角色管理 - 新增工具模块: tool_handler, tool_repo, tool_service, tool model - 更新 go.mod 依赖 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
@@ -15,6 +16,8 @@ import (
|
||||
"x-agents/server/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
)
|
||||
|
||||
// Logger 日志记录器
|
||||
@@ -56,6 +59,83 @@ func (l *Logger) LogRequest(method, path, body string, status int, duration time
|
||||
|
||||
var logger *Logger
|
||||
|
||||
// initDefaultAdmin 初始化默认管理员用户
|
||||
func initDefaultAdmin(userRepo *repository.UserRepository) {
|
||||
// 确保 admin 用户的工作空间目录存在
|
||||
ensureAdminWorkspace()
|
||||
|
||||
// 检查 admin 用户是否已存在
|
||||
_, err := userRepo.FindByUsername("admin")
|
||||
if err == nil {
|
||||
log.Println("Admin user already exists")
|
||||
return
|
||||
}
|
||||
|
||||
// 使用 AuthService 创建用户(会自动加密密码)
|
||||
authService := service.NewAuthService("", userRepo)
|
||||
adminUser, err := authService.Register("admin", "admin", "admin@example.com")
|
||||
if err != nil {
|
||||
log.Printf("Failed to create admin user: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 更新角色为管理员
|
||||
adminUser.RoleID = "admin"
|
||||
userRepo.Update(adminUser)
|
||||
|
||||
// 创建管理员角色
|
||||
perms, _ := json.Marshal([]int{int(model.PermissionRead), int(model.PermissionWrite), int(model.PermissionExecute), int(model.PermissionAdmin)})
|
||||
adminRole := &model.Role{
|
||||
ID: "admin",
|
||||
Name: "admin",
|
||||
Permissions: string(perms),
|
||||
}
|
||||
userRepo.CreateRole(adminRole)
|
||||
|
||||
log.Printf("Default admin user created: id=%s, username=admin", adminUser.ID)
|
||||
}
|
||||
|
||||
// ensureAdminWorkspace 确保 admin 用户工作空间目录存在
|
||||
func ensureAdminWorkspace() {
|
||||
execPath, _ := os.Getwd()
|
||||
projectRoot := execPath
|
||||
|
||||
// 如果当前目录名为 server,向上找一级
|
||||
baseName := filepath.Base(execPath)
|
||||
if baseName == "server" {
|
||||
projectRoot = filepath.Dir(execPath)
|
||||
}
|
||||
|
||||
// 尝试向上查找包含 .git 的目录
|
||||
if _, err := os.Stat(filepath.Join(projectRoot, ".git")); os.IsNotExist(err) {
|
||||
for i := 0; i < 3; i++ {
|
||||
parent := filepath.Dir(projectRoot)
|
||||
if parent == projectRoot {
|
||||
break
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(parent, ".git")); err == nil {
|
||||
projectRoot = parent
|
||||
break
|
||||
}
|
||||
projectRoot = parent
|
||||
}
|
||||
}
|
||||
|
||||
// 创建 admin 工作空间
|
||||
workspacePath := filepath.Join(projectRoot, "account", "admin")
|
||||
if err := os.MkdirAll(workspacePath, 0755); err != nil {
|
||||
log.Printf("Warning: failed to create admin workspace: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 创建子目录
|
||||
for _, dir := range []string{"projects", "files", "temp"} {
|
||||
os.MkdirAll(filepath.Join(workspacePath, dir), 0755)
|
||||
}
|
||||
|
||||
log.Printf("Admin workspace created at: %s", workspacePath)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 初始化日志
|
||||
logger = NewLogger()
|
||||
@@ -71,7 +151,66 @@ func main() {
|
||||
}
|
||||
|
||||
// 3. 自动迁移表
|
||||
db.AutoMigrate(&model.DatabaseInfo{}, &model.SubTableInfo{}, &model.ModelInfo{}, &model.KnowledgeBase{}, &model.KnowledgeDocument{}, &model.User{}, &model.Role{})
|
||||
db.AutoMigrate(&model.DatabaseInfo{}, &model.SubTableInfo{}, &model.ModelInfo{}, &model.KnowledgeBase{}, &model.KnowledgeDocument{}, &model.User{}, &model.Role{}, &model.Tool{})
|
||||
|
||||
// 3.1 确保 users 和 roles 表存在(使用 SQL 强制创建)
|
||||
db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
id VARCHAR(191) PRIMARY KEY,
|
||||
name VARCHAR(191) UNIQUE,
|
||||
permissions TEXT,
|
||||
created_at DATETIME(3),
|
||||
updated_at DATETIME(3)
|
||||
)
|
||||
`)
|
||||
db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id VARCHAR(191) PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password VARCHAR(191) NOT NULL,
|
||||
email VARCHAR(191),
|
||||
role_id VARCHAR(50) NOT NULL,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at DATETIME(3),
|
||||
updated_at DATETIME(3),
|
||||
INDEX idx_users_username (username),
|
||||
INDEX idx_users_email (email)
|
||||
)
|
||||
`)
|
||||
|
||||
// 3.2 确保 tools 表存在(使用 SQL 强制创建)
|
||||
db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS tools (
|
||||
id VARCHAR(191) PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
category VARCHAR(50) NOT NULL,
|
||||
provider VARCHAR(100),
|
||||
security_level VARCHAR(20) DEFAULT 'safe',
|
||||
require_approval BOOLEAN DEFAULT FALSE,
|
||||
parameters TEXT,
|
||||
status VARCHAR(20) DEFAULT 'active',
|
||||
created_at DATETIME(3),
|
||||
updated_at DATETIME(3),
|
||||
INDEX idx_tools_name (name),
|
||||
INDEX idx_tools_category (category),
|
||||
INDEX idx_tools_status (status)
|
||||
)
|
||||
`)
|
||||
|
||||
// 使用GORM Migrator添加缺失的列
|
||||
migrator := db.Migrator()
|
||||
if !migrator.HasColumn(&model.Tool{}, "security_level") {
|
||||
migrator.AddColumn(&model.Tool{}, "security_level")
|
||||
}
|
||||
if !migrator.HasColumn(&model.Tool{}, "require_approval") {
|
||||
migrator.AddColumn(&model.Tool{}, "require_approval")
|
||||
}
|
||||
if !migrator.HasColumn(&model.Tool{}, "parameters") {
|
||||
migrator.AddColumn(&model.Tool{}, "parameters")
|
||||
}
|
||||
|
||||
log.Println("Database tables verified/created")
|
||||
|
||||
// 4. 初始化 Repository
|
||||
dbRepo := repository.NewDatabaseRepository(db)
|
||||
@@ -79,6 +218,10 @@ func main() {
|
||||
modelRepo := repository.NewModelRepository(db)
|
||||
knowledgeRepo := repository.NewKnowledgeRepository(db)
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
toolRepo := repository.NewToolRepository(db)
|
||||
|
||||
// 4.1 初始化默认管理员用户
|
||||
initDefaultAdmin(userRepo)
|
||||
|
||||
// 5. 初始化 Service
|
||||
dbService := service.NewDatabaseService(dbRepo, subTableRepo)
|
||||
@@ -91,6 +234,14 @@ func main() {
|
||||
}
|
||||
knowledgeService := service.NewKnowledgeService(knowledgeRepo, modelRepo, uploadService, cfg.PythonServiceURL, cfg.AICoreServiceAddr, cfg.MarkdownLocalPath)
|
||||
authService := service.NewAuthService(cfg.JWTSecret, userRepo)
|
||||
toolService := service.NewToolService(toolRepo)
|
||||
|
||||
// 4.2 初始化默认工具
|
||||
if err := toolService.InitDefaultTools(); err != nil {
|
||||
log.Printf("Warning: Failed to init default tools: %v", err)
|
||||
} else {
|
||||
log.Println("Default tools initialized")
|
||||
}
|
||||
|
||||
// 6. 初始化 Handler
|
||||
dbHandler := handler.NewDatabaseHandler(dbService)
|
||||
@@ -100,6 +251,7 @@ func main() {
|
||||
systemHandler := handler.NewSystemHandler()
|
||||
knowledgeHandler := handler.NewKnowledgeHandler(knowledgeService)
|
||||
authHandler := handler.NewAuthHandler(authService)
|
||||
toolHandler := handler.NewToolHandler(toolService)
|
||||
var uploadHandler *handler.UploadHandler
|
||||
if uploadService != nil {
|
||||
uploadHandler = handler.NewUploadHandler(uploadService, knowledgeRepo)
|
||||
@@ -137,8 +289,8 @@ func main() {
|
||||
// CORS 中间件
|
||||
r.Use(func(c *gin.Context) {
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
|
||||
|
||||
if c.Request.Method == "OPTIONS" {
|
||||
c.AbortWithStatus(204)
|
||||
@@ -162,6 +314,14 @@ func main() {
|
||||
authProtectedGroup.GET("/me", authHandler.GetCurrentUser)
|
||||
}
|
||||
|
||||
// 用户管理模块(需要登录)
|
||||
userGroup := r.Group("/user")
|
||||
userGroup.Use(middleware.Auth(cfg.JWTSecret))
|
||||
{
|
||||
userGroup.GET("/list", authHandler.ListUsers)
|
||||
userGroup.GET("/:id", authHandler.GetUserByID)
|
||||
}
|
||||
|
||||
// 数据库管理模块
|
||||
databaseGroup := r.Group("/database")
|
||||
{
|
||||
@@ -225,6 +385,20 @@ func main() {
|
||||
// 系统信息模块
|
||||
r.GET("/system/info", systemHandler.GetSystemInfo)
|
||||
|
||||
// 工具管理模块
|
||||
toolGroup := r.Group("/tool")
|
||||
{
|
||||
toolGroup.GET("/list", toolHandler.List)
|
||||
toolGroup.GET("/sync", toolHandler.Sync) // 手动同步
|
||||
toolGroup.GET("/:id", toolHandler.GetByID)
|
||||
toolGroup.POST("/add", toolHandler.Create)
|
||||
toolGroup.PUT("/:id", toolHandler.Update)
|
||||
toolGroup.DELETE("/:id", toolHandler.Delete)
|
||||
}
|
||||
|
||||
// Swagger 文档
|
||||
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
||||
// 文件上传模块
|
||||
if uploadHandler != nil {
|
||||
// 本地文件静态服务
|
||||
|
||||
Reference in New Issue
Block a user