mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-18 21:38:57 +08:00
fix: Support encrypted backup of databases (#10963)
This commit is contained in:
parent
1afe84ed02
commit
a6062897d5
18 changed files with 105 additions and 86 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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.'
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ Failed: '失敗'
|
||||||
SystemRestart: 'システムの再起動によりタスクが中断されました'
|
SystemRestart: 'システムの再起動によりタスクが中断されました'
|
||||||
ErrGroupIsDefault: 'デフォルト グループ、削除できません'
|
ErrGroupIsDefault: 'デフォルト グループ、削除できません'
|
||||||
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
|
ErrGroupIsInWebsiteUse: 'グループは別の Web サイトで使用されているため、削除できません。'
|
||||||
|
Decrypt: "復号化"
|
||||||
|
|
||||||
#backup
|
#backup
|
||||||
Localhost: 'ローカルマシン'
|
Localhost: 'ローカルマシン'
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Failed: '실패했습니다'
|
||||||
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
|
SystemRestart: '시스템 재시작으로 인해 작업이 중단되었습니다'
|
||||||
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
|
ErrGroupIsDefault: '기본 그룹, 삭제할 수 없습니다'
|
||||||
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
|
ErrGroupIsInWebsiteUse: '그룹이 다른 웹사이트에서 사용 중이므로 삭제할 수 없습니다.'
|
||||||
|
Decrypt: "복호화"
|
||||||
|
|
||||||
#지원
|
#지원
|
||||||
Localhost: '로컬 머신'
|
Localhost: '로컬 머신'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ Failed: 'Не удалось'
|
||||||
SystemRestart: 'Задача прервана из-за перезапуска системы'
|
SystemRestart: 'Задача прервана из-за перезапуска системы'
|
||||||
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
|
ErrGroupIsDefault: 'Группа по умолчанию, не может быть удалена'
|
||||||
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
|
ErrGroupIsInWebsiteUse: 'Группа используется другим веб-сайтом и не может быть удалена.'
|
||||||
|
Decrypt: "Расшифровать"
|
||||||
|
|
||||||
#резервное копирование
|
#резервное копирование
|
||||||
Localhost: 'Локальная машина'
|
Localhost: 'Локальная машина'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Failed: '失敗'
|
||||||
SystemRestart: '系統重新啟動導致任務中斷'
|
SystemRestart: '系統重新啟動導致任務中斷'
|
||||||
ErrGroupIsDefault: '預設分組,無法刪除'
|
ErrGroupIsDefault: '預設分組,無法刪除'
|
||||||
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
|
ErrGroupIsInWebsiteUse: '分組正在被其他網站使用,無法刪除'
|
||||||
|
Decrypt: "解密"
|
||||||
|
|
||||||
#backup
|
#backup
|
||||||
Localhost: '本機'
|
Localhost: '本機'
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Failed: "失败"
|
||||||
SystemRestart: "系统重启导致任务中断"
|
SystemRestart: "系统重启导致任务中断"
|
||||||
ErrGroupIsDefault: "默认分组,无法删除"
|
ErrGroupIsDefault: "默认分组,无法删除"
|
||||||
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
|
ErrGroupIsInWebsiteUse: "分组正在被其他网站使用,无法删除"
|
||||||
|
Decrypt: "解密"
|
||||||
|
|
||||||
#backup
|
#backup
|
||||||
Localhost: '本机'
|
Localhost: '本机'
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue