// Package main 程序入口 package main import ( "fmt" "log" "seeyon-filesystem/api" "seeyon-filesystem/config" "seeyon-filesystem/model" "seeyon-filesystem/storage" "seeyon-filesystem/utils" "golang.org/x/crypto/bcrypt" ) func main() { // 将日志输出接入环形缓冲区(同时保留控制台输出) log.SetOutput(utils.LogBuf) cfg, err := config.Load() if err != nil { log.Fatalf("加载配置失败: %v", err) } if err := config.InitDB(&cfg.Database); err != nil { log.Fatalf("初始化数据库失败: %v", err) } // if err := autoMigrate(); err != nil { // log.Fatalf("数据库迁移失败: %v", err) // } initDefaultData() storage.InitEngines(cfg.Storage.LocalBasePath) r := api.SetupRouter() addr := fmt.Sprintf(":%d", cfg.Server.Port) log.Printf("服务启动: http://localhost%s", addr) if err := r.Run(addr); err != nil { log.Fatalf("服务启动失败: %v", err) } } func autoMigrate() error { err := config.DB.AutoMigrate( &model.User{}, &model.Folder{}, &model.File{}, &model.Share{}, &model.StoragePolicy{}, &model.FileAssociation{}, &model.Role{}, &model.Permission{}, &model.RolePermission{}, &model.UserRole{}, &model.SSOProvider{}, &model.SSOSession{}, &model.Department{}, &model.UploadSession{}, &model.StorageAssignment{}, &model.App{}, &model.AppUser{}, &model.FilePermission{}, &model.OperationLog{}, &model.BackupPolicy{}, &model.BackupLog{}, ) if err != nil { return err } // 添加复合索引优化查询性能 createIndexIfNotExists("fs_file_permission", "idx_fp_user_file", "user_id, file_id") createIndexIfNotExists("fs_file_permission", "idx_fp_role_file", "role_id, file_id") createIndexIfNotExists("fs_file", "idx_file_folder_owner", "folder_id, owner_id, status") createIndexIfNotExists("fs_file", "idx_file_status", "status") return nil } // createIndexIfNotExists 安全创建索引(忽略已存在错误) func createIndexIfNotExists(table, indexName, columns string) { sql := fmt.Sprintf("CREATE INDEX %s ON %s(%s)", indexName, table, columns) config.DB.Exec(sql) } // initDefaultData 初始化默认数据: 权限、角色、存储策略、分配规则 func initDefaultData() { // ========== 1. 权限 ========== permissions := []model.Permission{ {Code: "file:create", Name: "创建文件/文件夹", Resource: "file", Action: "create"}, {Code: "file:read", Name: "查看文件", Resource: "file", Action: "read"}, {Code: "file:update", Name: "修改文件", Resource: "file", Action: "update"}, {Code: "file:delete", Name: "删除文件", Resource: "file", Action: "delete"}, {Code: "file:upload", Name: "上传文件", Resource: "file", Action: "upload"}, {Code: "file:download", Name: "下载文件", Resource: "file", Action: "download"}, {Code: "file:grant", Name: "授权文件权限", Resource: "file", Action: "grant"}, {Code: "share:create", Name: "创建分享", Resource: "share", Action: "create"}, {Code: "share:manage", Name: "管理分享", Resource: "share", Action: "manage"}, {Code: "webdav:access", Name: "WebDAV访问", Resource: "webdav", Action: "access"}, {Code: "user:manage", Name: "用户管理", Resource: "user", Action: "manage"}, {Code: "role:manage", Name: "角色管理", Resource: "role", Action: "manage"}, {Code: "sso:manage", Name: "SSO管理", Resource: "sso", Action: "manage"}, {Code: "system:manage", Name: "系统管理", Resource: "system", Action: "manage"}, } for _, p := range permissions { config.DB.Where("code = ?", p.Code).FirstOrCreate(&p) } // ========== 2. 四级角色 ========== roles := []model.Role{ {Name: "admin", DisplayName: "超级管理员", Description: "全平台最高权限, 仅用于后台运维", IsSystem: 1}, {Name: "staff", DisplayName: "内部员工", Description: "团队内部成员, 可上传下载分享文件", IsSystem: 1}, {Name: "user", DisplayName: "普通用户", Description: "注册用户, 基础存储功能", IsSystem: 1}, {Name: "guest", DisplayName: "访客", Description: "仅可查看公开分享资源", IsSystem: 1}, } for _, r := range roles { config.DB.Where("name = ?", r.Name).FirstOrCreate(&r) } // 角色-权限分配 rolePermMap := map[string][]string{ "admin": {"*"}, // 全部权限 "staff": {"file:create", "file:read", "file:update", "file:delete", "file:upload", "file:download", "file:grant", "share:create", "webdav:access"}, "user": {"file:create", "file:read", "file:update", "file:upload", "file:download", "share:create"}, "guest": {"file:read"}, } var allPerms []model.Permission config.DB.Find(&allPerms) permMap := make(map[string]uint64) for _, p := range allPerms { permMap[p.Code] = p.ID } for roleName, permCodes := range rolePermMap { var role model.Role config.DB.Where("name = ?", roleName).First(&role) if role.ID == 0 { continue } // 清除旧权限 config.DB.Where("role_id = ?", role.ID).Delete(&model.RolePermission{}) if len(permCodes) == 1 && permCodes[0] == "*" { // 全部权限 for _, p := range allPerms { config.DB.Create(&model.RolePermission{RoleID: role.ID, PermissionID: p.ID}) } } else { for _, code := range permCodes { if pid, ok := permMap[code]; ok { config.DB.Create(&model.RolePermission{RoleID: role.ID, PermissionID: pid}) } } } } // ========== 3. 四类存储策略 ========== type policyDef struct { Name string PolicyType string Type string BasePath string Quota int64 } policyDefs := []policyDef{ {Name: "高性能热存储", PolicyType: "hot", Type: "local", BasePath: "./data/storage/hot", Quota: 53687091200}, // 50GB {Name: "低成本冷存储", PolicyType: "cold", Type: "local", BasePath: "./data/storage/cold", Quota: 107374182400}, // 100GB {Name: "公开资源存储", PolicyType: "public", Type: "local", BasePath: "./data/storage/public", Quota: 0}, // 不限 {Name: "扩展存储", PolicyType: "slave", Type: "local", BasePath: "./data/storage/slave", Quota: 214748364800}, // 200GB } for _, pd := range policyDefs { var existing model.StoragePolicy if config.DB.Where("policy_type = ?", pd.PolicyType).First(&existing).Error != nil { config.DB.Create(&model.StoragePolicy{ Name: pd.Name, Type: pd.Type, PolicyType: pd.PolicyType, Config: model.PolicyConfig{BasePath: pd.BasePath}, Status: 1, }) } } // ========== 4. 角色-存储策略分配(支持多策略+优先级) ========== type assignDef struct { RoleName string PolicyType string Quota int64 Priority int } assignDefs := []assignDef{ {RoleName: "admin", PolicyType: "hot", Quota: 0, Priority: 10}, {RoleName: "staff", PolicyType: "hot", Quota: 53687091200, Priority: 10}, {RoleName: "user", PolicyType: "cold", Quota: 10737418240, Priority: 10}, } for _, ad := range assignDefs { var role model.Role var policy model.StoragePolicy config.DB.Where("name = ?", ad.RoleName).First(&role) config.DB.Where("policy_type = ?", ad.PolicyType).First(&policy) if role.ID == 0 || policy.ID == 0 { continue } var existing model.StorageAssignment if config.DB.Where("group_id = ? AND policy_id = ?", role.ID, policy.ID).First(&existing).Error != nil { config.DB.Create(&model.StorageAssignment{ PolicyID: policy.ID, GroupID: role.ID, StorageQuota: ad.Quota, Priority: ad.Priority, Status: 1, }) } } // 设置默认存储策略(热存储) var hotPolicy model.StoragePolicy if config.DB.Where("policy_type = ?", "hot").First(&hotPolicy).Error == nil { var defaultAssign model.StorageAssignment if config.DB.Where("is_default = 1").First(&defaultAssign).Error != nil { config.DB.Create(&model.StorageAssignment{ PolicyID: hotPolicy.ID, IsDefault: 1, Status: 1, }) } } // ========== 5. 创建默认管理员 ========== var count int64 config.DB.Model(&model.User{}).Where("username = ?", "admin").Count(&count) if count == 0 { hashedPassword, err := bcrypt.GenerateFromPassword([]byte("admin123"), 10) if err != nil { log.Fatalf("密码加密失败: %v", err) } admin := &model.User{ Username: "admin", Password: string(hashedPassword), Status: 1, } if err := config.DB.Create(admin).Error; err != nil { log.Fatalf("创建 admin 失败: %v", err) } log.Println("✅ 默认管理员已创建: admin / admin123") } else { log.Println("⚠️ admin 用户已存在,跳过") } // ========== 6. 确保admin用户有admin角色 ========== var adminUser model.User if config.DB.Where("username = ?", "admin").First(&adminUser).Error == nil { var superAdminRole model.Role err := config.DB.Where("name = ?", "admin").First(&superAdminRole).Error if err == nil { // ✅ 用 Error 判断,找到了才继续 var ur model.UserRole if err := config.DB.Where("user_id = ? AND role_id = ?", adminUser.ID, superAdminRole.ID).First(&ur).Error; err != nil { // 没找到这条关联记录,才创建 config.DB.Create(&model.UserRole{UserID: adminUser.ID, RoleID: superAdminRole.ID}) log.Println("✅ admin 已分配 admin 角色") } else { log.Println("⚠️ admin 已有 admin 角色,跳过") } } else { log.Println("❌ 找不到 admin 角色") } } // ========== 7. 给没有角色的用户补上默认角色(user) ========== var userRole model.Role if config.DB.Where("name = ?", "user").First(&userRole).Error == nil { // ✅ 排除 admin var usersWithoutRole []model.User config.DB.Where("id NOT IN (SELECT user_id FROM fs_user_role) AND username != ?", "admin").Find(&usersWithoutRole) for _, u := range usersWithoutRole { config.DB.Create(&model.UserRole{UserID: u.ID, RoleID: userRole.ID}) } if len(usersWithoutRole) > 0 { log.Printf("已为 %d 个无角色用户分配默认角色", len(usersWithoutRole)) } } log.Println("默认数据初始化完成") }