package model import ( "fmt" "github.com/veypi/vbase/internal/config" "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) var DB *gorm.DB // InitDB 初始化数据库 func InitDB() error { cfg := config.C.Database var dialector gorm.Dialector switch cfg.Type { case "mysql": dialector = mysql.Open(cfg.DSN) case "postgres": dialector = postgres.Open(cfg.DSN) case "sqlite": dialector = sqlite.Open(cfg.DSN) default: return fmt.Errorf("unsupported database type: %s", cfg.Type) } var err error DB, err = gorm.Open(dialector, &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) if err != nil { return fmt.Errorf("failed to connect database: %w", err) } sqlDB, err := DB.DB() if err != nil { return err } sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime) return nil } // AutoMigrate 自动迁移表结构 func AutoMigrate() error { return DB.AutoMigrate( &User{}, &Identity{}, &Session{}, &Org{}, &OrgMember{}, &Policy{}, &Role{}, &OAuthClient{}, &OAuthAuthorization{}, &OAuthToken{}, ) } // InitSystemData 初始化系统数据 func InitSystemData() error { return DB.Transaction(func(tx *gorm.DB) error { // 1. 创建系统策略 if err := initSystemPolicies(tx); err != nil { return err } // 2. 检查是否需要创建初始管理员 var count int64 if err := tx.Model(&User{}).Count(&count).Error; err != nil { return err } if count == 0 { if err := initAdminUser(tx); err != nil { return err } } return nil }) } // initSystemPolicies 创建系统内置策略 func initSystemPolicies(tx *gorm.DB) error { policies := []Policy{ { Code: SysPolicyUserReadOwn, Name: "读取自己", Description: "用户读取自己的信息", Resource: "user", Action: "read", Condition: "resource.id == user.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyUserUpdateOwn, Name: "更新自己", Description: "用户更新自己的信息", Resource: "user", Action: "update", Condition: "resource.id == user.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyUserDeleteOwn, Name: "删除自己", Description: "用户删除自己的账号", Resource: "user", Action: "delete", Condition: "resource.id == user.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyOrgAdmin, Name: "组织管理员", Description: "组织所有者拥有所有权限", Resource: "*", Action: "*", Condition: "org.owner_id == user.id", Effect: EffectAllow, Priority: 100, IsSystem: true, }, { Code: SysPolicyOrgRead, Name: "读取组织", Description: "组织成员可读组织信息", Resource: "org", Action: "read", Condition: "member.org_id == org.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyMemberRead, Name: "读取成员", Description: "读取组织成员列表", Resource: "member", Action: "read", Condition: "member.org_id == org.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyMemberManage, Name: "管理成员", Description: "管理组织成员", Resource: "member", Action: "*", Condition: "", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyRoleRead, Name: "读取角色", Description: "读取组织角色", Resource: "role", Action: "read", Condition: "resource.org_id == org.id", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyRoleManage, Name: "管理角色", Description: "管理组织角色", Resource: "role", Action: "*", Condition: "", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyPolicyRead, Name: "读取策略", Description: "读取策略", Resource: "policy", Action: "read", Condition: "", Effect: EffectAllow, IsSystem: true, }, { Code: SysPolicyPolicyManage, Name: "管理策略", Description: "管理策略", Resource: "policy", Action: "*", Condition: "", Effect: EffectAllow, IsSystem: true, }, } for _, p := range policies { var existing Policy if err := tx.Where("code = ?", p.Code).First(&existing).Error; err != nil { if err == gorm.ErrRecordNotFound { if err := tx.Create(&p).Error; err != nil { return err } } else { return err } } } return nil } // initAdminUser 创建初始管理员 func initAdminUser(tx *gorm.DB) error { adminCfg := config.C.App.InitAdmin // 生成随机密码(如果未配置) password := adminCfg.Password if password == "" { password = generateRandomPassword(16) fmt.Printf("\n========================================\n") fmt.Printf("Initial admin user created!\n") fmt.Printf("Username: %s\n", adminCfg.Username) fmt.Printf("Password: %s\n", password) fmt.Printf("Email: %s\n", adminCfg.Email) fmt.Printf("========================================\n\n") } // 密码哈希(这里需要crypto包,后续实现) // hashedPassword, _ := crypto.HashPassword(password) admin := &User{ Username: adminCfg.Username, Password: password, // TODO: hash password Email: adminCfg.Email, Nickname: "Administrator", Status: UserStatusActive, EmailVerified: true, PhoneVerified: false, } if err := tx.Create(admin).Error; err != nil { return err } return nil } // generateRandomPassword 生成随机密码 func generateRandomPassword(length int) string { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*" result := make([]byte, length) for i := range result { result[i] = charset[i%len(charset)] } return string(result) }