package patch import ( "github.com/perfect-panel/ppanel-server/initialize/migrate" "github.com/perfect-panel/ppanel-server/internal/model/application" "github.com/perfect-panel/ppanel-server/internal/model/auth" "github.com/perfect-panel/ppanel-server/internal/model/log" "github.com/perfect-panel/ppanel-server/internal/model/server" "github.com/perfect-panel/ppanel-server/internal/model/system" "github.com/perfect-panel/ppanel-server/internal/model/user" "github.com/perfect-panel/ppanel-server/pkg/email" "github.com/perfect-panel/ppanel-server/pkg/logger" "github.com/perfect-panel/ppanel-server/pkg/sms" "gorm.io/gorm" ) func Migrate01200(db *gorm.DB) error { var version = "0.1.2(01200)" return db.Transaction(func(tx *gorm.DB) error { if exists := db.Migrator().HasColumn(&user.OldUser{}, "email"); !exists { logger.Debug("Migrate 01200 skipped", logger.Field("reason", "old user table not exists")) return nil } logger.Debug("Migrate 01200 started", logger.Field("step", "1"), logger.Field("action", "migrate old user to user auth methods")) var users []*user.OldUser if err := tx.Model(&user.OldUser{}).Find(&users).Error; err != nil { return err } if err := tx.Migrator().AutoMigrate(&user.AuthMethods{}); err != nil { logger.Errorw("Migrate 01200 failed", logger.Field("step", "1"), logger.Field("action", "create user auth methods table"), logger.Field("error", err.Error())) return err } err := tx.Transaction(func(tx *gorm.DB) error { for _, oldUser := range users { if oldUser.Email == "" { continue } // create user auth method authMethod := &user.AuthMethods{ UserId: oldUser.Id, AuthType: "email", AuthIdentifier: oldUser.Email, Verified: false, } if err := tx.Create(authMethod).Error; err != nil { return err } } return nil }) if err != nil { logger.Errorw("Migrate 01200 failed", logger.Field("step", "1"), logger.Field("action", "migrate old user to user auth methods"), logger.Field("error", err.Error())) return err } logger.Debug("Migrate 01200 completed", logger.Field("step", "1"), logger.Field("action", "migrate old user to user auth methods")) logger.Debug("Migrate 01200 started", logger.Field("step", "2"), logger.Field("action", "exclude sql files")) // exclude sql files if err := migrate.ExecuteSQLFile(tx, "database/01200-patch.sql"); err != nil { logger.Errorw("Migrate 01200 failed", logger.Field("step", "2"), logger.Field("action", "exclude sql files"), logger.Field("file", "database/01200-patch.sql"), logger.Field("error", err.Error())) return err } logger.Debug("Migrate 01200 completed", logger.Field("step", "2"), logger.Field("action", "exclude sql files")) logger.Debug("Migrate 01200 started", logger.Field("step", "3"), logger.Field("action", "update system config")) versionConfig := &system.System{ Category: "system", Key: "Version", Value: version, Type: "string", Desc: "Version of the system, eg: 1.0.0(10000)", } // update system config if err := tx.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Save(&versionConfig).Error; err != nil { logger.Errorw("Migrate 01200 failed", logger.Field("step", "3"), logger.Field("action", "update system config"), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01201(db *gorm.DB) error { version := "0.1.2(01201)" // exclude sql files if err := migrate.ExecuteSQLFile(db, "database/01201-patch.sql"); err != nil { logger.Errorw("Migrate 01201 failed", logger.Field("step", "1"), logger.Field("action", "exclude sql files"), logger.Field("file", "database/01200-patch.sql"), logger.Field("error", err.Error())) return err } // update system config if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate 01201 failed", logger.Field("step", "2"), logger.Field("action", "update system config"), logger.Field("error", err.Error())) return err } return nil } func Migrate01202(db *gorm.DB) error { version := "0.1.2(01202)" return db.Transaction(func(tx *gorm.DB) error { // migrate email config to system config if err := db.Migrator().AutoMigrate(&auth.Auth{}); err != nil { logger.Errorw("Migrate01202: AutoMigrate Auth failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } if db.Migrator().HasColumn("oauth_config", "platform") { if err := db.Migrator().RenameColumn("oauth_config", "platform", "method"); err != nil { logger.Errorw("Migrate01202: RenameColumn platform to method failed", logger.Field("version", version), logger.Field("error", err.Error())) } } // init email config if err := initEmailConfig(db); err != nil { logger.Errorw("Migrate01202: initEmailConfig failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // init mobile config if err := initMobileConfig(db); err != nil { logger.Errorw("Migrate01202: initMobileConfig failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // drop oauth_config table err := db.Migrator().DropTable("oauth_config") if err != nil { logger.Debug("Migrate01202: DropTable oauth_config failed", logger.Field("version", version), logger.Field("error", err.Error())) } // exclude sql files if err := migrate.ExecuteSQLFile(db, "database/01202-patch.sql"); err != nil { logger.Errorw("Migrate 01202 failed", logger.Field("action", "exclude sql files"), logger.Field("file", "database/012002-patch.sql"), logger.Field("error", err.Error())) return err } // update system config if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate 01202 failed", logger.Field("step", "2"), logger.Field("action", "update system config"), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01203(db *gorm.DB) error { version := "0.1.2(01203)" return db.Transaction(func(tx *gorm.DB) error { if err := db.AutoMigrate(&user.LoginLog{}, &user.SubscribeLog{}); err != nil { logger.Errorw("Migrate01203: AutoMigrate LoginLog/SubscribeLog failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // update version if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate01203: Update Version failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01204(db *gorm.DB) error { version := "0.1.2(01204)" return db.Transaction(func(tx *gorm.DB) error { if err := db.AutoMigrate(&log.MessageLog{}); err != nil { logger.Errorw("Migrate01204: AutoMigrate MessageLog failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // Trial configuration if err := initTrialConfig(tx); err != nil { logger.Errorw("Migrate01204: initTrialConfig failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // Add auth method with device if err := addAuthMethodWithDevice(tx); err != nil { logger.Errorw("Migrate01204: Add auth method with device failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } // update version if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate01204: Update Version failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01205(db *gorm.DB) error { version := "0.1.2(01205)" return db.Transaction(func(tx *gorm.DB) error { // Add VerifyCode public configuration configs := []system.System{ { Category: "verify_code", Key: "VerifyCodeExpireTime", Value: "5", Type: "int", Desc: "Verify code expire time", }, { Category: "verify_code", Key: "VerifyCodeLimit", Value: "15", Type: "int", Desc: "limits of verify code", }, { Category: "verify_code", Key: "VerifyCodeInterval", Value: "60", Type: "int", Desc: "Interval of verify code", }, } if err := tx.Model(&system.System{}).Save(&configs).Error; err != nil { logger.Errorw("Migrate01205: Save VerifyCode public configuration failed", logger.Field("error", err.Error())) return err } // update version if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate01205: Update Version failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01301(db *gorm.DB) error { version := "0.1.3(01301)" return db.Transaction(func(tx *gorm.DB) error { err := tx.Migrator().AlterColumn(&application.Application{}, "icon") if err != nil { logger.Errorw("Migrate01301: AlterColumn failed", logger.Field("error", err.Error())) return err } // update version if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate01205: Update Version failed", logger.Field("version", version), logger.Field("error", err.Error())) return err } return nil }) } func Migrate01602(db *gorm.DB) error { version := "0.1.6(01602)" return db.Transaction(func(tx *gorm.DB) error { if tx.Model(&system.System{}).Where("`category` = 'tos' AND `key` = 'TosContent'").Find(&system.System{}).RowsAffected == 0 { if err := tx.Save(&system.System{ Category: "tos", Key: "TosContent", Value: "Welcome to use Perfect Panel", Type: "string", Desc: "Terms of Service", }).Error; err != nil { return err } } // update version if err := tx.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { return err } return nil }) } func Migrate01701(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { version := "0.1.7(01701)" if err := db.Migrator().AlterColumn(&user.User{}, "Avatar"); err != nil { return err } // update version if err := tx.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { return err } return nil }) } func Migrate01702(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { version := "0.1.7(01702)" if tx.Model(&system.System{}).Where("`category` = 'site' AND `key` = 'Keywords'").Find(&system.System{}).RowsAffected == 0 { if err := tx.Save(&system.System{ Category: "site", Key: "Keywords", Value: "Perfect Panel,PPanel", Type: "string", Desc: "Keywords", }).Error; err != nil { return err } } if tx.Model(&system.System{}).Where("`category` = 'site' AND `key` = 'CustomHTML'").Find(&system.System{}).RowsAffected == 0 { if err := tx.Save(&system.System{ Category: "site", Key: "CustomHTML", Value: "", Type: "string", Desc: "Custom HTML", }).Error; err != nil { return err } } // update version if err := tx.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { return err } return nil }) } func Migrate01703(db *gorm.DB) error { version := "0.1.7(01703)" return db.Transaction(func(tx *gorm.DB) error { if tx.Model(&system.System{}).Where("`category` = 'tos' AND `key` = 'PrivacyPolicy'").Find(&system.System{}).RowsAffected == 0 { if err := tx.Save(&system.System{ Category: "tos", Key: "PrivacyPolicy", Value: "", Type: "string", Desc: "Privacy Policy", }).Error; err != nil { return err } } return tx.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error }) } func Migrate01704(db *gorm.DB) error { version := "0.1.7(01704)" // check server table latitude column exists, if not exists, create it if exists := db.Migrator().HasColumn(&server.Server{}, "latitude"); !exists { if err := db.Migrator().AddColumn(&server.Server{}, "latitude"); err != nil { logger.Errorw("Migrate 01704 failed", logger.Field("action", "add latitude column"), logger.Field("error", err.Error())) return err } logger.Infow("Migrate 01704 success", logger.Field("action", "add latitude column")) } // check server table longitude column exists, if not exists, create it if exists := db.Migrator().HasColumn(&server.Server{}, "longitude"); !exists { if err := db.Migrator().AddColumn(&server.Server{}, "longitude"); err != nil { logger.Errorw("Migrate 01704 failed", logger.Field("action", "add longitude column"), logger.Field("error", err.Error())) return err } logger.Infow("Migrate 01704 success", logger.Field("action", "add longitude column")) } // update system config if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate 01704 failed", logger.Field("step", "2"), logger.Field("action", "update system config"), logger.Field("error", err.Error())) return err } logger.Infow("Migrate 01704 success", logger.Field("action", "update system config")) return nil } func Migrate01705(db *gorm.DB) error { version := "0.1.7(01705)" // check user_device table exists, if not exists, create it if exists := db.Migrator().HasTable(&user.Device{}); !exists { if err := db.Migrator().CreateTable(&user.Device{}); err != nil { logger.Errorw("Migrate 01705 failed", logger.Field("action", "create user_device table"), logger.Field("error", err.Error())) return err } logger.Infow("Migrate 01705 success", logger.Field("action", "create user_device table")) } // check user_table exists and imei column exists, if exists, update imei column name to identifier if exists := db.Migrator().HasColumn(&user.Device{}, "imei"); exists { if err := db.Migrator().RenameColumn(&user.Device{}, "imei", "identifier"); err != nil { logger.Errorw("Migrate 01705 failed", logger.Field("action", "rename imei column to identifier"), logger.Field("error", err.Error())) return err } logger.Infow("Migrate 01705 success", logger.Field("action", "rename imei column to identifier")) } // update system config if err := db.Model(&system.System{}).Where("`category` = 'system' AND `key` = 'Version'").Update("value", version).Error; err != nil { logger.Errorw("Migrate 01705 failed", logger.Field("step", "2"), logger.Field("action", "update system config"), logger.Field("error", err.Error())) return err } return nil } func initMobileConfig(db *gorm.DB) error { cfg := new(auth.AlibabaCloudConfig) mobileConfig := auth.MobileAuthConfig{ Platform: sms.AlibabaCloud.String(), PlatformConfig: cfg.Marshal(), EnableWhitelist: false, Whitelist: make([]string, 0), } authMethod := auth.Auth{ Method: "mobile", Config: mobileConfig.Marshal(), } if err := db.Save(&authMethod).Error; err != nil { return err } return nil } func initEmailConfig(db *gorm.DB) error { enable := true smtpConfig := new(auth.SMTPConfig) emailConfig := auth.EmailAuthConfig{ Platform: "smtp", PlatformConfig: smtpConfig.Marshal(), EnableVerify: false, EnableDomainSuffix: false, DomainSuffixList: "", VerifyEmailTemplate: email.DefaultEmailVerifyTemplate, ExpirationEmailTemplate: email.DefaultExpirationEmailTemplate, MaintenanceEmailTemplate: email.DefaultMaintenanceEmailTemplate, } authMethod := auth.Auth{ Method: "email", Config: emailConfig.Marshal(), Enabled: &enable, } return db.Save(&authMethod).Error } func initTrialConfig(tx *gorm.DB) error { configs := []system.System{ { Category: "register", Key: "TrialSubscribe", Value: "", Type: "int", Desc: "Trial subscription", }, { Category: "register", Key: "TrialTime", Value: "24", Type: "int", Desc: "Trial time", }, { Category: "register", Key: "TrialTimeUnit", Value: "Hour", Type: "string", Desc: "Trial time unit", }, } return tx.Model(&system.System{}).Save(&configs).Error } func addAuthMethodWithDevice(tx *gorm.DB) error { return tx.Model(&auth.Auth{}).Save(&auth.Auth{ Method: "device", }).Error }