package db import ( "omega-server/local/model" "omega-server/local/utl/logging" "os" "time" "go.uber.org/dig" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func Start(di *dig.Container) { dbName := os.Getenv("DB_NAME") if dbName == "" { dbName = "app.db" } // Configure GORM logger gormLogger := logger.Default if os.Getenv("LOG_LEVEL") == "DEBUG" { gormLogger = logger.Default.LogMode(logger.Info) } else { gormLogger = logger.Default.LogMode(logger.Silent) } db, err := gorm.Open(sqlite.Open(dbName), &gorm.Config{ Logger: gormLogger, }) if err != nil { logging.Panic("failed to connect database: " + err.Error()) } // Configure connection pool sqlDB, err := db.DB() if err != nil { logging.Panic("failed to get database instance: " + err.Error()) } // Set connection pool settings sqlDB.SetMaxIdleConns(10) sqlDB.SetMaxOpenConns(100) sqlDB.SetConnMaxLifetime(time.Hour) err = di.Provide(func() *gorm.DB { return db }) if err != nil { logging.Panic("failed to bind database: " + err.Error()) } logging.Info("Database connected successfully") Migrate(db) } func Migrate(db *gorm.DB) { logging.Info("Starting database migration...") err := db.AutoMigrate( &model.User{}, &model.Role{}, &model.Permission{}, &model.SystemConfig{}, &model.AuditLog{}, &model.SecurityEvent{}, ) if err != nil { logging.Panic("failed to migrate database models: " + err.Error()) } logging.Info("Database migration completed successfully") Seed(db) } func Seed(db *gorm.DB) error { logging.Info("Starting database seeding...") if err := seedRoles(db); err != nil { return err } if err := seedPermissions(db); err != nil { return err } if err := seedDefaultAdmin(db); err != nil { return err } if err := seedSystemConfigs(db); err != nil { return err } logging.Info("Database seeding completed successfully") return nil } func seedRoles(db *gorm.DB) error { roles := []model.Role{ {Name: "admin", Description: "Administrator with full access"}, {Name: "user", Description: "Regular user with limited access"}, {Name: "viewer", Description: "Read-only access"}, } for _, role := range roles { var existingRole model.Role err := db.Where("name = ?", role.Name).First(&existingRole).Error if err == gorm.ErrRecordNotFound { role.Init() if err := db.Create(&role).Error; err != nil { return err } logging.Info("Created role: %s", role.Name) } } return nil } func seedPermissions(db *gorm.DB) error { permissions := []model.Permission{ {Name: "user:create", Description: "Create new users"}, {Name: "user:read", Description: "Read user information"}, {Name: "user:update", Description: "Update user information"}, {Name: "user:delete", Description: "Delete users"}, {Name: "role:create", Description: "Create new roles"}, {Name: "role:read", Description: "Read role information"}, {Name: "role:update", Description: "Update role information"}, {Name: "role:delete", Description: "Delete roles"}, {Name: "system:config", Description: "Access system configuration"}, {Name: "system:logs", Description: "Access system logs"}, {Name: "system:admin", Description: "Full system administration"}, } for _, permission := range permissions { var existingPermission model.Permission err := db.Where("name = ?", permission.Name).First(&existingPermission).Error if err == gorm.ErrRecordNotFound { permission.Init() if err := db.Create(&permission).Error; err != nil { return err } logging.Info("Created permission: %s", permission.Name) } } // Assign all permissions to admin role var adminRole model.Role if err := db.Where("name = ?", "admin").First(&adminRole).Error; err != nil { return err } var allPermissions []model.Permission if err := db.Find(&allPermissions).Error; err != nil { return err } if err := db.Model(&adminRole).Association("Permissions").Replace(allPermissions); err != nil { return err } // Assign basic permissions to user role var userRole model.Role if err := db.Where("name = ?", "user").First(&userRole).Error; err != nil { return err } var userPermissions []model.Permission userPermissionNames := []string{"user:read", "role:read"} if err := db.Where("name IN ?", userPermissionNames).Find(&userPermissions).Error; err != nil { return err } if err := db.Model(&userRole).Association("Permissions").Replace(userPermissions); err != nil { return err } // Assign read permissions to viewer role var viewerRole model.Role if err := db.Where("name = ?", "viewer").First(&viewerRole).Error; err != nil { return err } var viewerPermissions []model.Permission viewerPermissionNames := []string{"user:read", "role:read"} if err := db.Where("name IN ?", viewerPermissionNames).Find(&viewerPermissions).Error; err != nil { return err } if err := db.Model(&viewerRole).Association("Permissions").Replace(viewerPermissions); err != nil { return err } return nil } func seedDefaultAdmin(db *gorm.DB) error { // Check if admin user already exists var existingAdmin model.User err := db.Where("email = ?", "admin@example.com").First(&existingAdmin).Error if err != gorm.ErrRecordNotFound { return nil // Admin already exists or other error } // Get admin role var adminRole model.Role if err := db.Where("name = ?", "admin").First(&adminRole).Error; err != nil { return err } // Create default admin user defaultPassword := os.Getenv("DEFAULT_ADMIN_PASSWORD") if defaultPassword == "" { defaultPassword = "admin123" } admin := model.User{ Email: "admin@example.com", Username: "admin", Name: "System Administrator", Active: true, } admin.Init() if err := admin.SetPassword(defaultPassword); err != nil { return err } if err := db.Create(&admin).Error; err != nil { return err } // Assign admin role if err := db.Model(&admin).Association("Roles").Append(&adminRole); err != nil { return err } logging.Info("Created default admin user with email: %s", admin.Email) logging.Warn("Default admin password is: %s - PLEASE CHANGE THIS IMMEDIATELY!", defaultPassword) return nil } func seedSystemConfigs(db *gorm.DB) error { configs := []model.SystemConfig{ { Key: "app.name", Value: "Bootstrap App", DefaultValue: "Bootstrap App", Description: "Application name", Category: "general", DataType: "string", IsEditable: true, DateModified: time.Now().UTC().Format(time.RFC3339), }, { Key: "app.version", Value: "1.0.0", DefaultValue: "1.0.0", Description: "Application version", Category: "general", DataType: "string", IsEditable: false, DateModified: time.Now().UTC().Format(time.RFC3339), }, { Key: "security.jwt_expiry_hours", Value: "24", DefaultValue: "24", Description: "JWT token expiry time in hours", Category: "security", DataType: "integer", IsEditable: true, DateModified: time.Now().UTC().Format(time.RFC3339), }, { Key: "security.password_min_length", Value: "8", DefaultValue: "8", Description: "Minimum password length", Category: "security", DataType: "integer", IsEditable: true, DateModified: time.Now().UTC().Format(time.RFC3339), }, { Key: "security.max_login_attempts", Value: "5", DefaultValue: "5", Description: "Maximum login attempts before lockout", Category: "security", DataType: "integer", IsEditable: true, DateModified: time.Now().UTC().Format(time.RFC3339), }, { Key: "security.lockout_duration_minutes", Value: "30", DefaultValue: "30", Description: "Account lockout duration in minutes", Category: "security", DataType: "integer", IsEditable: true, DateModified: time.Now().UTC().Format(time.RFC3339), }, } for _, config := range configs { var existingConfig model.SystemConfig err := db.Where("key = ?", config.Key).First(&existingConfig).Error if err == gorm.ErrRecordNotFound { config.Init() if err := db.Create(&config).Error; err != nil { return err } logging.Info("Created system config: %s", config.Key) } } return nil }