fix: Support encrypted backup of databases (#10963)

This commit is contained in:
ssongliu 2025-11-14 22:12:55 +08:00 committed by GitHub
parent 1afe84ed02
commit a6062897d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 105 additions and 86 deletions

View file

@ -102,7 +102,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
} }
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase)) parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.MysqlName, DBType: resourceKey, Name: db.Name} databaseHelper := DatabaseHelper{Database: db.MysqlName, DBType: resourceKey, Name: db.Name}
if err := handleMysqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil { if err := handleMysqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), "", ""); err != nil {
return err return err
} }
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase)) parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
@ -113,7 +113,7 @@ func backupDatabaseWithTask(parentTask *task.Task, resourceKey, tmpDir, name str
} }
parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase)) parentTask.LogStart(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
databaseHelper := DatabaseHelper{Database: db.PostgresqlName, DBType: resourceKey, Name: db.Name} databaseHelper := DatabaseHelper{Database: db.PostgresqlName, DBType: resourceKey, Name: db.Name}
if err := handlePostgresqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), ""); err != nil { if err := handlePostgresqlBackup(databaseHelper, parentTask, 0, tmpDir, fmt.Sprintf("%s.sql.gz", name), "", ""); err != nil {
return err return err
} }
parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase)) parentTask.LogSuccess(task.GetTaskName(db.Name, task.TaskBackup, task.TaskScopeDatabase))
@ -260,7 +260,7 @@ func handleAppRecover(install *model.AppInstall, parentTask *task.Task, recoverF
Name: newDB.MysqlName, Name: newDB.MysqlName,
DetailName: newDB.Name, DetailName: newDB.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name), File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, install.Name),
}, parentTask, true, ""); err != nil { }, parentTask, true); err != nil {
t.LogFailedWithErr(taskName, err) t.LogFailedWithErr(taskName, err)
return err return err
} }

View file

@ -48,7 +48,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
} }
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName} databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil { if err := handleMysqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID, req.Secret); err != nil {
backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()}) backupRepo.UpdateRecordByMap(record.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
return err return err
} }
@ -56,7 +56,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error {
} }
func (u *BackupService) MysqlRecover(req dto.CommonRecover) error { func (u *BackupService) MysqlRecover(req dto.CommonRecover) error {
return handleMysqlRecover(req, nil, false, req.TaskID) return handleMysqlRecover(req, nil, false)
} }
func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error { func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
@ -66,13 +66,13 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
} }
req.File = recoveFile req.File = recoveFile
if err := handleMysqlRecover(req, nil, false, req.TaskID); err != nil { if err := handleMysqlRecover(req, nil, false); err != nil {
return err return err
} }
return nil return nil
} }
func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error { func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID, secret string) error {
var ( var (
err error err error
backupTask *task.Task backupTask *task.Task
@ -90,7 +90,7 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
} }
} }
itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName) } itemHandler := func() error { return doMysqlBackup(db, targetDir, fileName, secret) }
if parentTask != nil { if parentTask != nil {
return itemHandler() return itemHandler()
} }
@ -105,7 +105,7 @@ func handleMysqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint,
return nil return nil
} }
func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool, taskID string) error { func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback bool) error {
var ( var (
err error err error
itemTask *task.Task itemTask *task.Task
@ -117,7 +117,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
} }
itemName := fmt.Sprintf("%s[%s] - %s", req.Name, req.Type, req.DetailName) itemName := fmt.Sprintf("%s[%s] - %s", req.Name, req.Type, req.DetailName)
if parentTask == nil { if parentTask == nil {
itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeBackup, taskID, dbInfo.ID) itemTask, err = task.NewTaskWithOps(itemName, task.TaskRecover, task.TaskScopeBackup, req.TaskID, dbInfo.ID)
if err != nil { if err != nil {
return err return err
} }
@ -170,6 +170,15 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
} }
}() }()
} }
if len(req.Secret) != 0 {
err = files.OpensslDecrypt(req.File, req.Secret)
if err != nil {
return err
}
req.File = path.Join(path.Dir(req.File), "tmp_"+path.Base(req.File))
defer os.Remove(req.File)
t.LogWithStatus(i18n.GetMsgByKey("Decrypt"), err)
}
if err := cli.Recover(client.RecoverInfo{ if err := cli.Recover(client.RecoverInfo{
Name: req.DetailName, Name: req.DetailName,
Type: req.Type, Type: req.Type,
@ -194,7 +203,7 @@ func handleMysqlRecover(req dto.CommonRecover, parentTask *task.Task, isRollback
return nil return nil
} }
func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error { func doMysqlBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
dbInfo, err := mysqlRepo.Get(repo.WithByName(db.Name), mysqlRepo.WithByMysqlName(db.Database)) dbInfo, err := mysqlRepo.Get(repo.WithByName(db.Name), mysqlRepo.WithByMysqlName(db.Database))
if err != nil { if err != nil {
return err return err
@ -211,7 +220,13 @@ func doMysqlBackup(db DatabaseHelper, targetDir, fileName string) error {
TargetDir: targetDir, TargetDir: targetDir,
FileName: fileName, FileName: fileName,
} }
return cli.Backup(backupInfo) if err := cli.Backup(backupInfo); err != nil {
return err
}
if len(secret) != 0 {
return files.OpensslEncrypt(path.Join(targetDir, fileName), secret)
}
return nil
} }
func loadSqlFile(file string) (string, error) { func loadSqlFile(file string) (string, error) {

View file

@ -6,21 +6,18 @@ import (
"path" "path"
"time" "time"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/utils/common"
pgclient "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
"github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task" "github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global" "github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/files" "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/1Panel-dev/1Panel/agent/utils/postgresql/client" "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
pgclient "github.com/1Panel-dev/1Panel/agent/utils/postgresql/client"
) )
func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error { func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
@ -46,7 +43,7 @@ func (u *BackupService) PostgresqlBackup(req dto.CommonBackup) error {
} }
databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName} databaseHelper := DatabaseHelper{Database: req.Name, DBType: req.Type, Name: req.DetailName}
if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID); err != nil { if err := handlePostgresqlBackup(databaseHelper, nil, record.ID, targetDir, fileName, req.TaskID, req.Secret); err != nil {
return err return err
} }
return nil return nil
@ -71,7 +68,7 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
return nil return nil
} }
func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID string) error { func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID uint, targetDir, fileName, taskID, secret string) error {
var ( var (
err error err error
backupTask *task.Task backupTask *task.Task
@ -85,7 +82,7 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
} }
} }
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName) } itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret) }
if parentTask != nil { if parentTask != nil {
return itemHandler() return itemHandler()
} }
@ -160,6 +157,15 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
} }
}() }()
} }
if len(req.Secret) != 0 {
err = files.OpensslDecrypt(req.File, req.Secret)
if err != nil {
return err
}
req.File = path.Join(path.Dir(req.File), "tmp_"+path.Base(req.File))
defer os.Remove(req.File)
t.LogWithStatus(i18n.GetMsgByKey("Decrypt"), err)
}
if err := cli.Recover(client.RecoverInfo{ if err := cli.Recover(client.RecoverInfo{
Name: req.DetailName, Name: req.DetailName,
SourceFile: req.File, SourceFile: req.File,
@ -183,7 +189,7 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
return nil return nil
} }
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error { func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
cli, err := LoadPostgresqlClientByFrom(db.Database) cli, err := LoadPostgresqlClientByFrom(db.Database)
if err != nil { if err != nil {
return err return err
@ -196,5 +202,11 @@ func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName string) error {
Timeout: 300, Timeout: 300,
} }
return cli.Backup(backupInfo) if err := cli.Backup(backupInfo); err != nil {
return err
}
if len(secret) != 0 {
return files.OpensslEncrypt(path.Join(targetDir, fileName), secret)
}
return nil
} }

View file

@ -363,7 +363,7 @@ func recoverWebsiteDatabase(t *task.Task, dbID uint, dbType, tmpPath, websiteKey
Name: db.MysqlName, Name: db.MysqlName,
DetailName: db.Name, DetailName: db.Name,
File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, websiteKey), File: fmt.Sprintf("%s/%s.sql.gz", tmpPath, websiteKey),
}, t, true, ""); err != nil { }, t, true); err != nil {
t.LogFailedWithErr(taskName, err) t.LogFailedWithErr(taskName, err)
return err return err
} }

View file

@ -167,7 +167,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
backupDir := path.Join(global.Dir.LocalBackupDir, fmt.Sprintf("tmp/database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name)) backupDir := path.Join(global.Dir.LocalBackupDir, fmt.Sprintf("tmp/database/%s/%s/%s", dbInfo.DBType, record.Name, dbInfo.Name))
record.FileName = simplifiedFileName(fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5))) record.FileName = simplifiedFileName(fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)))
if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" { if cronjob.DBType == "mysql" || cronjob.DBType == "mariadb" || cronjob.DBType == "mysql-cluster" {
if err := doMysqlBackup(dbInfo, backupDir, record.FileName); err != nil { if err := doMysqlBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr { if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++ retry++
return err return err
@ -178,7 +178,7 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Ti
} }
} }
} else { } else {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName); err != nil { if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr { if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++ retry++
return err return err

View file

@ -36,6 +36,7 @@ Failed: 'Failed'
SystemRestart: 'Task interrupted due to system restart' SystemRestart: 'Task interrupted due to system restart'
ErrGroupIsDefault: 'Default group, cannot be deleted' ErrGroupIsDefault: 'Default group, cannot be deleted'
ErrGroupIsInWebsiteUse: 'The group is being used by another website and cannot be deleted.' ErrGroupIsInWebsiteUse: 'The group is being used by another website and cannot be deleted.'
Decrypt: "Decrypt"
#backup #backup
Localhost: 'Local Machine' Localhost: 'Local Machine'

View file

@ -36,6 +36,7 @@ Failed: 'Error'
SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema' SystemRestart: 'La tarea fue interrumpida debido a un reinicio del sistema'
ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar' ErrGroupIsDefault: 'Grupo predeterminado, no se puede eliminar'
ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.' ErrGroupIsInWebsiteUse: 'El grupo está siendo usado por otro sitio web y no se puede eliminar.'
Decrypt: "Descifrar"
#backup #backup
ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.' ErrBackupInUsed: 'La cuenta de respaldo está siendo utilizada en una tarea programada y no se puede eliminar.'

View file

@ -35,6 +35,7 @@ Failed: '失敗'
SystemRestart: 'システムの再起動によりタスクが中断されました' SystemRestart: 'システムの再起動によりタスクが中断されました'
ErrGroupIsDefault: 'デフォルト グループ、削除できません' ErrGroupIsDefault: 'デフォルト グループ、削除できません'
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。' ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
Decrypt: "復号化"
#backup #backup
Localhost: 'ローカルマシン' Localhost: 'ローカルマシン'

View file

@ -36,6 +36,7 @@ Failed: '실패했습니다'
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다' SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다' ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.' ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
Decrypt: "복호화"
#지원 #지원
Localhost: '로컬 머신' Localhost: '로컬 머신'

View file

@ -39,6 +39,7 @@ Failed: 'Gagal'
SystemRestart: 'Tugas terganggu kerana sistem mula semula' SystemRestart: 'Tugas terganggu kerana sistem mula semula'
ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan' ErrGroupIsDefault: 'Kumpulan lalai, tidak boleh dipadamkan'
ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.' ErrGroupIsInWebsiteUse: 'Kumpulan sedang digunakan oleh tapak web lain dan tidak boleh dipadamkan.'
Decrypt: "Dekripsi"
#sandaran #sandaran
Localhost: 'Mesin Tempatan' Localhost: 'Mesin Tempatan'

View file

@ -39,6 +39,7 @@ Failed: 'Falhou'
SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema' SystemRestart: 'Tarefa interrompida devido à reinicialização do sistema'
ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído' ErrGroupIsDefault: 'Grupo padrão, não pode ser excluído'
ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.' ErrGroupIsInWebsiteUse: 'O grupo está sendo usado por outro site e não pode ser excluído.'
Decrypt: "Descriptografar"
#backup #backup
Localhost: 'Máquina Local' Localhost: 'Máquina Local'

View file

@ -39,6 +39,7 @@ Failed: 'Не удалось'
SystemRestart: 'Задача прервана из-за перезапуска системы' SystemRestart: 'Задача прервана из-за перезапуска системы'
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена' ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.' ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
Decrypt: "Расшифровать"
#резервное копирование #резервное копирование
Localhost: 'Локальная машина' Localhost: 'Локальная машина'

View file

@ -39,6 +39,7 @@ Failed: 'Başarısız'
SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi' SystemRestart: 'Sistem yeniden başlatması nedeniyle görev kesildi'
ErrGroupIsDefault: 'Varsayılan grup, silinemez' ErrGroupIsDefault: 'Varsayılan grup, silinemez'
ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.' ErrGroupIsInWebsiteUse: 'Grup başka bir web sitesi tarafından kullanılıyor ve silinemez.'
Decrypt: "Şifre Çöz"
#backup #backup
Localhost: 'Yerel Makine' Localhost: 'Yerel Makine'

View file

@ -36,6 +36,7 @@ Failed: '失敗'
SystemRestart: '系統重新啟動導致任務中斷' SystemRestart: '系統重新啟動導致任務中斷'
ErrGroupIsDefault: '預設分組,無法刪除' ErrGroupIsDefault: '預設分組,無法刪除'
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除' ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
Decrypt: "解密"
#backup #backup
Localhost: '本機' Localhost: '本機'

View file

@ -36,6 +36,7 @@ Failed: "失败"
SystemRestart: "系统重启导致任务中断" SystemRestart: "系统重启导致任务中断"
ErrGroupIsDefault: "默认分组,无法删除" ErrGroupIsDefault: "默认分组,无法删除"
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除" ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
Decrypt: "解密"
#backup #backup
Localhost: '本机' Localhost: '本机'

View file

@ -957,3 +957,23 @@ func CopyCustomAppFile(srcPath, dstPath string) error {
} }
return nil return nil
} }
func OpensslEncrypt(filePath, secret string) error {
tmpName := path.Join(path.Dir(filePath), "tmp_"+path.Base(filePath))
if err := cmd.RunDefaultBashCf("MY_PASS='%s' openssl enc -aes-256-cbc -salt -pass env:MY_PASS -in %s -out %s", secret, filePath, tmpName); err != nil {
_ = os.Remove(tmpName)
return err
}
return os.Rename(tmpName, filePath)
}
func OpensslDecrypt(filePath, secret string) error {
tmpName := path.Join(path.Dir(filePath), "tmp_"+path.Base(filePath))
if err := cmd.RunDefaultBashCf("MY_PASS='%s' openssl enc -aes-256-cbc -d -salt -pass env:MY_PASS -in %s -out %s", secret, filePath, tmpName); err != nil {
if strings.Contains(err.Error(), "bad decrypt") || strings.Contains(err.Error(), "bad magic number") {
return buserr.New("ErrBadDecrypt")
}
return err
}
return nil
}

View file

@ -107,7 +107,7 @@
{{ $t('commons.msg.' + (isBackup ? 'backupHelper' : 'recoverHelper'), [name + '( ' + detailName + ' )']) }} {{ $t('commons.msg.' + (isBackup ? 'backupHelper' : 'recoverHelper'), [name + '( ' + detailName + ' )']) }}
</el-alert> </el-alert>
<el-form class="mt-5" ref="backupForm" @submit.prevent label-position="top" v-loading="loading"> <el-form class="mt-5" ref="backupForm" @submit.prevent label-position="top" v-loading="loading">
<el-form-item :label="$t('setting.compressPassword')" v-if="type === 'app' || type === 'website'"> <el-form-item :label="$t('setting.compressPassword')">
<el-input v-model="secret" :placeholder="$t('setting.backupRecoverMessage')" /> <el-input v-model="secret" :placeholder="$t('setting.backupRecoverMessage')" />
</el-form-item> </el-form-item>
<el-form-item v-if="isBackup" :label="$t('commons.table.description')"> <el-form-item v-if="isBackup" :label="$t('commons.table.description')">
@ -281,7 +281,7 @@ function selectable(row) {
return row.status !== 'Waiting'; return row.status !== 'Waiting';
} }
const backup = async (close: boolean) => { const backup = async () => {
const taskID = newUUID(); const taskID = newUUID();
let params = { let params = {
type: type.value, type: type.value,
@ -292,23 +292,18 @@ const backup = async (close: boolean) => {
description: description.value, description: description.value,
}; };
loading.value = true; loading.value = true;
try { await handleBackup(params)
await handleBackup(params); .then(() => {
loading.value = false; loading.value = false;
if (close) {
handleClose();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search();
} else {
openTaskLog(taskID); openTaskLog(taskID);
} handleBackupClose();
handleBackupClose(); })
} catch (error) { .catch(() => {
loading.value = false; loading.value = false;
} });
}; };
const recover = async (close: boolean, row?: any) => { const recover = async (row?: any) => {
const taskID = newUUID(); const taskID = newUUID();
let params = { let params = {
downloadAccountID: row.downloadAccountID, downloadAccountID: row.downloadAccountID,
@ -324,14 +319,8 @@ const recover = async (close: boolean, row?: any) => {
await handleRecover(params) await handleRecover(params)
.then(() => { .then(() => {
loading.value = false; loading.value = false;
openTaskLog(taskID);
handleBackupClose(); handleBackupClose();
if (close) {
handleClose();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
search();
} else {
openTaskLog(taskID);
}
}) })
.catch(() => { .catch(() => {
loading.value = false; loading.value = false;
@ -340,6 +329,7 @@ const recover = async (close: boolean, row?: any) => {
const onBackup = async () => { const onBackup = async () => {
description.value = ''; description.value = '';
secret.value = '';
isBackup.value = true; isBackup.value = true;
open.value = true; open.value = true;
}; };
@ -347,28 +337,15 @@ const onBackup = async () => {
const onRecover = async (row: Backup.RecordInfo) => { const onRecover = async (row: Backup.RecordInfo) => {
secret.value = ''; secret.value = '';
isBackup.value = false; isBackup.value = false;
if (type.value !== 'app' && type.value !== 'website') {
ElMessageBox.confirm(
i18n.global.t('commons.msg.recoverHelper', [name.value + '( ' + detailName.value + ' )']),
i18n.global.t('commons.button.recover'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
},
).then(async () => {
recover(true, row);
});
return;
}
recordInfo.value = row; recordInfo.value = row;
open.value = true; open.value = true;
}; };
const onSubmit = () => { const onSubmit = () => {
if (isBackup.value) { if (isBackup.value) {
backup(false); backup();
} else { } else {
recover(false, recordInfo.value); recover(recordInfo.value);
} }
}; };

View file

@ -88,13 +88,10 @@
v-model="recoverDialog" v-model="recoverDialog"
:title="$t('commons.button.recover') + ' - ' + name" :title="$t('commons.button.recover') + ' - ' + name"
@close="handleRecoverClose" @close="handleRecoverClose"
size="small"
> >
<el-form ref="backupForm" label-position="left" v-loading="loading"> <el-form ref="backupForm" @submit.prevent label-position="top" v-loading="loading">
<el-form-item <el-form-item :label="$t('setting.compressPassword')">
:label="$t('setting.compressPassword')"
class="mt-5"
v-if="type === 'app' || type === 'website'"
>
<el-input v-model="secret" :placeholder="$t('setting.backupRecoverMessage')" /> <el-input v-model="secret" :placeholder="$t('setting.backupRecoverMessage')" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -282,19 +279,7 @@ const onHandleRecover = async () => {
const onRecover = async (row: File.File) => { const onRecover = async (row: File.File) => {
currentRow.value = row; currentRow.value = row;
if (type.value !== 'app' && type.value !== 'website') { secret.value = '';
ElMessageBox.confirm(
i18n.global.t('commons.msg.recoverHelper', [row.name]),
i18n.global.t('commons.button.recover'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
},
).then(async () => {
onHandleRecover();
});
return;
}
recoverDialog.value = true; recoverDialog.value = true;
}; };