提交
This commit is contained in:
176
server/main.go
176
server/main.go
@@ -22,6 +22,11 @@ func main() {
|
||||
log.Fatalf("加载配置失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证授权(启动时必须通过, 否则拒绝启动)
|
||||
if err := checkLicense(cfg.License); err != nil {
|
||||
log.Fatalf("授权验证失败: %v", err)
|
||||
}
|
||||
|
||||
if err := config.InitDB(&cfg.Database); err != nil {
|
||||
log.Fatalf("初始化数据库失败: %v", err)
|
||||
}
|
||||
@@ -67,6 +72,7 @@ func autoMigrate() error {
|
||||
&model.OperationLog{},
|
||||
&model.BackupPolicy{},
|
||||
&model.BackupLog{},
|
||||
&model.UserSession{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -83,6 +89,19 @@ func autoMigrate() error {
|
||||
|
||||
// createIndexIfNotExists 安全创建索引(忽略已存在错误)
|
||||
func createIndexIfNotExists(table, indexName, columns string) {
|
||||
// 先检查索引是否已存在(兼容MySQL/PostgreSQL/SQL Server)
|
||||
var count int64
|
||||
switch config.AppConfig.Database.Type {
|
||||
case "postgres":
|
||||
config.DB.Raw("SELECT COUNT(*) FROM pg_indexes WHERE indexname = ?", indexName).Scan(&count)
|
||||
case "sqlserver":
|
||||
config.DB.Raw("SELECT COUNT(*) FROM sys.indexes WHERE name = ?", indexName).Scan(&count)
|
||||
default:
|
||||
config.DB.Raw("SELECT COUNT(*) FROM information_schema.statistics WHERE table_name = ? AND index_name = ?", table, indexName).Scan(&count)
|
||||
}
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
sql := fmt.Sprintf("CREATE INDEX %s ON %s(%s)", indexName, table, columns)
|
||||
config.DB.Exec(sql)
|
||||
}
|
||||
@@ -107,7 +126,11 @@ func initDefaultData() {
|
||||
{Code: "system:manage", Name: "系统管理", Resource: "system", Action: "manage"},
|
||||
}
|
||||
for _, p := range permissions {
|
||||
config.DB.Where("code = ?", p.Code).FirstOrCreate(&p)
|
||||
var existing model.Permission
|
||||
if config.DB.Where("code = ?", p.Code).First(&existing).Error != nil {
|
||||
p.ID = utils.GenID()
|
||||
config.DB.Create(&p)
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 2. 四级角色 ==========
|
||||
@@ -118,7 +141,13 @@ func initDefaultData() {
|
||||
{Name: "guest", DisplayName: "访客", Description: "仅可查看公开分享资源", IsSystem: 1},
|
||||
}
|
||||
for _, r := range roles {
|
||||
config.DB.Where("name = ?", r.Name).FirstOrCreate(&r)
|
||||
var existing model.Role
|
||||
if config.DB.Where("name = ?", r.Name).First(&existing).Error != nil {
|
||||
r.ID = utils.GenID()
|
||||
config.DB.Create(&r)
|
||||
} else {
|
||||
r = existing
|
||||
}
|
||||
}
|
||||
|
||||
// 角色-权限分配
|
||||
@@ -179,6 +208,7 @@ func initDefaultData() {
|
||||
var existing model.StoragePolicy
|
||||
if config.DB.Where("policy_type = ?", pd.PolicyType).First(&existing).Error != nil {
|
||||
config.DB.Create(&model.StoragePolicy{
|
||||
ID: utils.GenID(),
|
||||
Name: pd.Name,
|
||||
Type: pd.Type,
|
||||
PolicyType: pd.PolicyType,
|
||||
@@ -213,6 +243,7 @@ func initDefaultData() {
|
||||
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{
|
||||
ID: utils.GenID(),
|
||||
PolicyID: policy.ID,
|
||||
GroupID: role.ID,
|
||||
StorageQuota: ad.Quota,
|
||||
@@ -228,6 +259,7 @@ func initDefaultData() {
|
||||
var defaultAssign model.StorageAssignment
|
||||
if config.DB.Where("is_default = 1").First(&defaultAssign).Error != nil {
|
||||
config.DB.Create(&model.StorageAssignment{
|
||||
ID: utils.GenID(),
|
||||
PolicyID: hotPolicy.ID,
|
||||
IsDefault: 1,
|
||||
Status: 1,
|
||||
@@ -239,62 +271,102 @@ func initDefaultData() {
|
||||
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)
|
||||
}
|
||||
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,
|
||||
}
|
||||
admin := &model.User{
|
||||
ID: utils.GenID(),
|
||||
Username: "admin",
|
||||
Password: string(hashedPassword),
|
||||
Nickname: "管理员",
|
||||
Role: "admin",
|
||||
Status: 1,
|
||||
StorageQuota: 107374182400, // 100GB
|
||||
MustChangePwd: 1,
|
||||
}
|
||||
|
||||
if err := config.DB.Create(admin).Error; err != nil {
|
||||
log.Fatalf("创建 admin 失败: %v", err)
|
||||
}
|
||||
log.Println("✅ 默认管理员已创建: admin / admin123")
|
||||
} else {
|
||||
log.Println("⚠️ admin 用户已存在,跳过")
|
||||
}
|
||||
if err := config.DB.Create(admin).Error; err != nil {
|
||||
log.Fatalf("创建 admin 失败: %v", err)
|
||||
}
|
||||
log.Println("默认管理员已创建: admin / admin123")
|
||||
} else {
|
||||
// 确保已有admin用户的Role字段为admin
|
||||
config.DB.Model(&model.User{}).Where("username = ? AND (role IS NULL OR role = '')", "admin").Update("role", "admin")
|
||||
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 角色")
|
||||
}
|
||||
}
|
||||
// ========== 6. 确保admin用户有admin角色 ==========
|
||||
var adminUser model.User
|
||||
if config.DB.Where("username = ?", "admin").First(&adminUser).Error == nil {
|
||||
var adminRole model.Role
|
||||
if config.DB.Where("name = ?", "admin").First(&adminRole).Error == nil {
|
||||
var ur model.UserRole
|
||||
if config.DB.Where("user_id = ? AND role_id = ?", adminUser.ID, adminRole.ID).First(&ur).Error != nil {
|
||||
config.DB.Create(&model.UserRole{UserID: adminUser.ID, RoleID: adminRole.ID})
|
||||
log.Println("admin 已分配 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))
|
||||
}
|
||||
}
|
||||
// ========== 7. 给没有角色的用户补上默认角色(user) ==========
|
||||
var userRole model.Role
|
||||
if config.DB.Where("name = ?", "user").First(&userRole).Error == nil {
|
||||
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("默认数据初始化完成")
|
||||
}
|
||||
|
||||
// checkLicense 验证产品授权
|
||||
func checkLicense(cfg config.LicenseConfig) error {
|
||||
machineID := utils.GetMachineID()
|
||||
log.Printf("机器标识: %s", machineID)
|
||||
|
||||
licensePath := cfg.FilePath
|
||||
if licensePath == "" {
|
||||
licensePath = "license.json"
|
||||
}
|
||||
|
||||
resp, err := utils.ReadAndVerifyLicense(licensePath, cfg.VerifyURL, "seeyon-filesystem", "1.0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !resp.Valid {
|
||||
return fmt.Errorf("%s", resp.Message)
|
||||
}
|
||||
|
||||
// 设置当前授权信息
|
||||
licPath := cfg.FilePath
|
||||
if licPath == "" {
|
||||
licPath = "license.json"
|
||||
}
|
||||
if licData, licErr := utils.ReadLicenseFile(licPath); licErr == nil {
|
||||
utils.SetCurrentLicense(licData)
|
||||
}
|
||||
|
||||
lic := utils.GetCurrentLicense()
|
||||
features := ""
|
||||
if lic != nil {
|
||||
features = lic.Features
|
||||
}
|
||||
|
||||
if resp.ExpireDays == -1 {
|
||||
log.Printf("[授权] 企业版 - 永久授权, 用户上限: %d, 功能: %s", resp.MaxUsers, features)
|
||||
} else {
|
||||
log.Printf("[授权] 企业版 - 有效期剩余 %d 天, 用户上限: %d, 功能: %s", resp.ExpireDays, resp.MaxUsers, features)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user