diff --git a/backend/app/repo/app_install_resource.go b/backend/app/repo/app_install_resource.go index f0718aba4..e57bbf87d 100644 --- a/backend/app/repo/app_install_resource.go +++ b/backend/app/repo/app_install_resource.go @@ -19,6 +19,7 @@ type IAppInstallResourceRpo interface { GetFirst(opts ...DBOption) (model.AppInstallResource, error) Create(ctx context.Context, resource *model.AppInstallResource) error DeleteBy(ctx context.Context, opts ...DBOption) error + BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error } func NewIAppInstallResourceRpo() IAppInstallResourceRpo { @@ -71,3 +72,11 @@ func (a AppInstallResourceRpo) Create(ctx context.Context, resource *model.AppIn func (a AppInstallResourceRpo) DeleteBy(ctx context.Context, opts ...DBOption) error { return getTx(ctx, opts...).Delete(&model.AppInstallResource{}).Error } + +func (a *AppInstallResourceRpo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error { + db := getDb(opts...).Model(&model.AppInstallResource{}) + if len(opts) == 0 { + db = db.Where("1=1") + } + return db.Updates(&maps).Error +} diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go index f6cf42c06..7b675c43d 100644 --- a/backend/app/service/backup_app.go +++ b/backend/app/service/backup_app.go @@ -148,7 +148,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback if err := json.Unmarshal(appjson, &oldInstall); err != nil { return fmt.Errorf("unmarshal app.json failed, err: %v", err) } - if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name || oldInstall.Version != install.Version || oldInstall.ID != install.ID { + if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name || oldInstall.Version != install.Version { return errors.New("the current backup file does not match the application") } @@ -182,7 +182,14 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback if err != nil { return err } - if err := handleMysqlRecover(mysqlInfo, tmpPath, db.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil { + + newDB, err := reCreateDB(db.ID, oldInstall.Env) + if err != nil { + return err + } + _ = appInstallResourceRepo.BatchUpdateBy(map[string]interface{}{"resource_id": newDB.ID}, commonRepo.WithByID(resource.ID)) + + if err := handleMysqlRecover(mysqlInfo, tmpPath, newDB.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil { global.LOG.Errorf("handle recover from sql.gz failed, err: %v", err) return err } @@ -193,11 +200,39 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback return err } - oldInstall.Status = constant.Running - if err := appInstallRepo.Save(context.Background(), install); err != nil { + oldInstall.ID = install.ID + oldInstall.Status = constant.StatusRunning + oldInstall.AppId = install.AppId + oldInstall.AppDetailId = install.AppDetailId + if err := appInstallRepo.Save(context.Background(), &oldInstall); err != nil { global.LOG.Errorf("save db app install failed, err: %v", err) return err } isOk = true return nil } + +func reCreateDB(dbID uint, oldEnv string) (*model.DatabaseMysql, error) { + mysqlService := NewIMysqlService() + ctx := context.Background() + _ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, DeleteBackup: true, ForceDelete: true}) + + envMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil { + return nil, err + } + oldName, _ := envMap["PANEL_DB_NAME"].(string) + oldUser, _ := envMap["PANEL_DB_USER"].(string) + oldPassword, _ := envMap["PANEL_DB_USER_PASSWORD"].(string) + createDB, err := mysqlService.Create(context.Background(), dto.MysqlDBCreate{ + Name: oldName, + Format: "utf8mb4", + Username: oldUser, + Password: oldPassword, + Permission: "%", + }) + if err != nil { + return nil, err + } + return createDB, nil +} diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index 914598158..8ae11a7bd 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -14,7 +14,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/app/repo" "github.com/1Panel-dev/1Panel/backend/buserr" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" @@ -100,7 +99,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode } return nil, err } - if err := u.createUser(app, req); err != nil { + if err := u.createUser(app.ContainerName, app.Password, app.Version, req); err != nil { return nil, err } @@ -291,7 +290,7 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { } } - if err := u.createUser(app, dto.MysqlDBCreate{ + if err := u.createUser(app.ContainerName, app.Password, app.Version, dto.MysqlDBCreate{ Username: mysql.Username, Name: mysql.Name, Permission: info.Value, @@ -470,7 +469,7 @@ func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) { return &info, nil } -func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) error { +func (u *MysqlService) createUser(container, password, version string, req dto.MysqlDBCreate) error { var userlist []string if strings.Contains(req.Permission, ",") { ips := strings.Split(req.Permission, ",") @@ -484,8 +483,8 @@ func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) err } for _, user := range userlist { - if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("create user %s identified by '%s';", user, req.Password)); err != nil { - handleCreateError(req.Name, userlist, app) + if err := excSQL(container, password, fmt.Sprintf("create user %s identified by '%s';", user, req.Password)); err != nil { + handleCreateError(container, password, req.Name, userlist) if strings.Contains(err.Error(), "ERROR 1396") { return buserr.New(constant.ErrUserIsExist) } @@ -495,20 +494,20 @@ func (u *MysqlService) createUser(app *repo.RootInfo, req dto.MysqlDBCreate) err if req.Name == "*" { grantStr = fmt.Sprintf("grant all privileges on *.* to %s", user) } - if strings.HasPrefix(app.Version, "5.7") { + if strings.HasPrefix(version, "5.7") { grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password) } - if err := excSQL(app.ContainerName, app.Password, grantStr); err != nil { - handleCreateError(req.Name, userlist, app) + if err := excSQL(container, password, grantStr); err != nil { + handleCreateError(container, password, req.Name, userlist) return err } } return nil } -func handleCreateError(dbName string, userlist []string, app *repo.RootInfo) { - _ = excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop database `%s`", dbName)) +func handleCreateError(contaienr, password, dbName string, userlist []string) { + _ = excSQL(contaienr, password, fmt.Sprintf("drop database `%s`", dbName)) for _, user := range userlist { - if err := excSQL(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists %s", user)); err != nil { + if err := excSQL(contaienr, password, fmt.Sprintf("drop user if exists %s", user)); err != nil { global.LOG.Errorf("drop user failed, err: %v", err) } }