mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 压缩和解压缩 tar.gz 文件时支持设置压缩密码 (#5258)
This commit is contained in:
parent
dab5434125
commit
0182586869
@ -35,6 +35,7 @@ type CommonBackup struct {
|
||||
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website postgresql"`
|
||||
Name string `json:"name"`
|
||||
DetailName string `json:"detailName"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
type CommonRecover struct {
|
||||
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"`
|
||||
@ -42,6 +43,7 @@ type CommonRecover struct {
|
||||
Name string `json:"name"`
|
||||
DetailName string `json:"detailName"`
|
||||
File string `json:"file"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type RecordSearch struct {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package dto
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type CronjobCreate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
@ -21,6 +23,7 @@ type CronjobCreate struct {
|
||||
BackupAccounts string `json:"backupAccounts"`
|
||||
DefaultDownload string `json:"defaultDownload"`
|
||||
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type CronjobUpdate struct {
|
||||
@ -42,6 +45,7 @@ type CronjobUpdate struct {
|
||||
BackupAccounts string `json:"backupAccounts"`
|
||||
DefaultDownload string `json:"defaultDownload"`
|
||||
RetainCopies int `json:"retainCopies" validate:"number,min=1"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type CronjobUpdateStatus struct {
|
||||
@ -87,6 +91,7 @@ type CronjobInfo struct {
|
||||
|
||||
LastRecordTime string `json:"lastRecordTime"`
|
||||
Status string `json:"status"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type SearchRecord struct {
|
||||
|
@ -54,12 +54,14 @@ type FileCompress struct {
|
||||
Type string `json:"type" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Replace bool `json:"replace"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type FileDeCompress struct {
|
||||
Dst string `json:"dst" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
Dst string `json:"dst" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
type FileEdit struct {
|
||||
|
@ -116,11 +116,13 @@ type SnapshotCreate struct {
|
||||
From string `json:"from" validate:"required"`
|
||||
DefaultDownload string `json:"defaultDownload" validate:"required"`
|
||||
Description string `json:"description" validate:"max=256"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
type SnapshotRecover struct {
|
||||
IsNew bool `json:"isNew"`
|
||||
ReDownload bool `json:"reDownload"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
IsNew bool `json:"isNew"`
|
||||
ReDownload bool `json:"reDownload"`
|
||||
ID uint `json:"id" validate:"required"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
type SnapshotBatchDelete struct {
|
||||
DeleteWithFile bool `json:"deleteWithFile"`
|
||||
|
@ -1,6 +1,8 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Cronjob struct {
|
||||
BaseModel
|
||||
@ -31,6 +33,7 @@ type Cronjob struct {
|
||||
Status string `gorm:"type:varchar(64)" json:"status"`
|
||||
EntryIDs string `gorm:"type:varchar(64)" json:"entryIDs"`
|
||||
Records []JobRecords `json:"records"`
|
||||
Secret string `gorm:"type:varchar(64)" json:"secret"`
|
||||
}
|
||||
|
||||
type JobRecords struct {
|
||||
|
@ -767,7 +767,7 @@ func getAppFromRepo(downloadPath string) error {
|
||||
if err := fileOp.DownloadFile(downloadUrl, packagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.SdkZip); err != nil {
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.SdkZip, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
|
@ -765,7 +765,7 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
|
||||
global.LOG.Errorf("download app[%s] error %v", app.Name, err)
|
||||
return
|
||||
}
|
||||
if err = fileOp.Decompress(filePath, appResourceDir, files.SdkTarGz); err != nil {
|
||||
if err = fileOp.Decompress(filePath, appResourceDir, files.SdkTarGz, ""); err != nil {
|
||||
global.LOG.Errorf("decompress app[%s] error %v", app.Name, err)
|
||||
return
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er
|
||||
backupDir := path.Join(localDir, itemDir)
|
||||
|
||||
fileName := fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
|
||||
if err := handleAppBackup(&install, backupDir, fileName, ""); err != nil {
|
||||
if err := handleAppBackup(&install, backupDir, fileName, "", req.Secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -78,13 +78,13 @@ func (u *BackupService) AppRecover(req dto.CommonRecover) error {
|
||||
if _, err := compose.Down(install.GetComposePath()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleAppRecover(&install, req.File, false); err != nil {
|
||||
if err := handleAppRecover(&install, req.File, false, req.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAppBackup(install *model.AppInstall, backupDir, fileName string, excludes string) error {
|
||||
func handleAppBackup(install *model.AppInstall, backupDir, fileName string, excludes string, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", ""))
|
||||
if !fileOp.Stat(tmpDir) {
|
||||
@ -103,7 +103,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string, excl
|
||||
}
|
||||
|
||||
appPath := install.GetPath()
|
||||
if err := handleTar(appPath, tmpDir, "app.tar.gz", excludes); err != nil {
|
||||
if err := handleTar(appPath, tmpDir, "app.tar.gz", excludes, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -129,16 +129,16 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string, excl
|
||||
}
|
||||
}
|
||||
|
||||
if err := handleTar(tmpDir, backupDir, fileName, ""); err != nil {
|
||||
if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback bool) error {
|
||||
func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback bool, secret string) error {
|
||||
isOk := false
|
||||
fileOp := files.NewFileOp()
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil {
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil {
|
||||
return err
|
||||
}
|
||||
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
|
||||
@ -164,13 +164,13 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
|
||||
if !isRollback {
|
||||
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("app/%s_%s.tar.gz", install.Name, time.Now().Format("20060102150405")))
|
||||
if err := handleAppBackup(install, path.Dir(rollbackFile), path.Base(rollbackFile), ""); err != nil {
|
||||
if err := handleAppBackup(install, path.Dir(rollbackFile), path.Base(rollbackFile), "", ""); err != nil {
|
||||
return fmt.Errorf("backup app %s for rollback before recover failed, err: %v", install.Name, err)
|
||||
}
|
||||
defer func() {
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleAppRecover(install, rollbackFile, true); err != nil {
|
||||
if err := handleAppRecover(install, rollbackFile, true, secret); err != nil {
|
||||
global.LOG.Errorf("rollback app %s from %s failed, err: %v", install.Name, rollbackFile, err)
|
||||
return
|
||||
}
|
||||
@ -251,7 +251,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
_ = fileOp.Rename(appDir, backPath)
|
||||
_ = fileOp.CreateDir(appDir, 0755)
|
||||
|
||||
if err := handleUnTar(tmpPath+"/app.tar.gz", install.GetAppPath()); err != nil {
|
||||
if err := handleUnTar(tmpPath+"/app.tar.gz", install.GetAppPath(), ""); err != nil {
|
||||
global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err)
|
||||
_ = fileOp.DeleteDir(appDir)
|
||||
_ = fileOp.Rename(backPath, appDir)
|
||||
|
@ -66,7 +66,7 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err)
|
||||
}
|
||||
}
|
||||
if err := handleUnTar(req.File, dstDir); err != nil {
|
||||
if err := handleUnTar(req.File, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return err
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func (u *BackupService) PostgresqlRecoverByUpload(req dto.CommonRecover) error {
|
||||
return fmt.Errorf("mkdir %s failed, err: %v", dstDir, err)
|
||||
}
|
||||
}
|
||||
if err := handleUnTar(req.File, dstDir); err != nil {
|
||||
if err := handleUnTar(req.File, dstDir, ""); err != nil {
|
||||
_ = os.RemoveAll(dstDir)
|
||||
return err
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func (u *BackupService) RedisBackup(db dto.CommonBackup) error {
|
||||
}
|
||||
itemDir := fmt.Sprintf("database/redis/%s", redisInfo.Name)
|
||||
backupDir := path.Join(localDir, itemDir)
|
||||
if err := handleRedisBackup(redisInfo, backupDir, fileName); err != nil {
|
||||
if err := handleRedisBackup(redisInfo, backupDir, fileName, db.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
record := &model.BackupRecord{
|
||||
@ -70,13 +70,13 @@ func (u *BackupService) RedisRecover(req dto.CommonRecover) error {
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("recover redis from backup file %s", req.File)
|
||||
if err := handleRedisRecover(redisInfo, req.File, false); err != nil {
|
||||
if err := handleRedisRecover(redisInfo, req.File, false, req.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRedisBackup(redisInfo *repo.RootInfo, backupDir, fileName string) error {
|
||||
func handleRedisBackup(redisInfo *repo.RootInfo, backupDir, fileName string, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(backupDir) {
|
||||
if err := os.MkdirAll(backupDir, os.ModePerm); err != nil {
|
||||
@ -91,7 +91,7 @@ func handleRedisBackup(redisInfo *repo.RootInfo, backupDir, fileName string) err
|
||||
|
||||
if strings.HasSuffix(fileName, ".tar.gz") {
|
||||
redisDataDir := fmt.Sprintf("%s/%s/%s/data/appendonlydir", constant.AppInstallDir, "redis", redisInfo.Name)
|
||||
if err := handleTar(redisDataDir, backupDir, fileName, ""); err != nil {
|
||||
if err := handleTar(redisDataDir, backupDir, fileName, "", secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -111,7 +111,7 @@ func handleRedisBackup(redisInfo *repo.RootInfo, backupDir, fileName string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback bool) error {
|
||||
func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback bool, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
if !fileOp.Stat(recoverFile) {
|
||||
return buserr.WithName("ErrFileNotFound", recoverFile)
|
||||
@ -147,13 +147,13 @@ func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback
|
||||
}
|
||||
}
|
||||
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/redis/%s_%s.%s", redisInfo.Name, time.Now().Format("20060102150405"), suffix))
|
||||
if err := handleRedisBackup(redisInfo, path.Dir(rollbackFile), path.Base(rollbackFile)); err != nil {
|
||||
if err := handleRedisBackup(redisInfo, path.Dir(rollbackFile), path.Base(rollbackFile), secret); err != nil {
|
||||
return fmt.Errorf("backup database %s for rollback before recover failed, err: %v", redisInfo.Name, err)
|
||||
}
|
||||
defer func() {
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleRedisRecover(redisInfo, rollbackFile, true); err != nil {
|
||||
if err := handleRedisRecover(redisInfo, rollbackFile, true, secret); err != nil {
|
||||
global.LOG.Errorf("rollback redis from %s failed, err: %v", rollbackFile, err)
|
||||
return
|
||||
}
|
||||
@ -170,7 +170,7 @@ func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback
|
||||
}
|
||||
if appendonly == "yes" && strings.HasPrefix(redisInfo.Version, "7.") {
|
||||
redisDataDir := fmt.Sprintf("%s/%s/%s/data", constant.AppInstallDir, "redis", redisInfo.Name)
|
||||
if err := handleUnTar(recoverFile, redisDataDir); err != nil {
|
||||
if err := handleUnTar(recoverFile, redisDataDir, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
)
|
||||
|
||||
func handleRuntimeBackup(runtime *model.Runtime, backupDir, fileName string, excludes string) error {
|
||||
func handleRuntimeBackup(runtime *model.Runtime, backupDir, fileName string, excludes string, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", ""))
|
||||
if !fileOp.Stat(tmpDir) {
|
||||
@ -35,19 +35,19 @@ func handleRuntimeBackup(runtime *model.Runtime, backupDir, fileName string, exc
|
||||
}
|
||||
|
||||
appPath := runtime.GetPath()
|
||||
if err := handleTar(appPath, tmpDir, "runtime.tar.gz", excludes); err != nil {
|
||||
if err := handleTar(appPath, tmpDir, "runtime.tar.gz", excludes, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleTar(tmpDir, backupDir, fileName, ""); err != nil {
|
||||
if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback bool) error {
|
||||
func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback bool, secret string) error {
|
||||
isOk := false
|
||||
fileOp := files.NewFileOp()
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil {
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil {
|
||||
return err
|
||||
}
|
||||
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
|
||||
@ -73,13 +73,13 @@ func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback
|
||||
|
||||
if !isRollback {
|
||||
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("runtime/%s_%s.tar.gz", runtime.Name, time.Now().Format("20060102150405")))
|
||||
if err := handleRuntimeBackup(runtime, path.Dir(rollbackFile), path.Base(rollbackFile), ""); err != nil {
|
||||
if err := handleRuntimeBackup(runtime, path.Dir(rollbackFile), path.Base(rollbackFile), "", secret); err != nil {
|
||||
return fmt.Errorf("backup runtime %s for rollback before recover failed, err: %v", runtime.Name, err)
|
||||
}
|
||||
defer func() {
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleRuntimeRecover(runtime, rollbackFile, true); err != nil {
|
||||
if err := handleRuntimeRecover(runtime, rollbackFile, true, secret); err != nil {
|
||||
global.LOG.Errorf("rollback runtime %s from %s failed, err: %v", runtime.Name, rollbackFile, err)
|
||||
return
|
||||
}
|
||||
@ -100,7 +100,7 @@ func handleRuntimeRecover(runtime *model.Runtime, recoverFile string, isRollback
|
||||
_ = fileOp.Rename(runtimeDir, backPath)
|
||||
_ = fileOp.CreateDir(runtimeDir, 0755)
|
||||
|
||||
if err := handleUnTar(tmpPath+"/runtime.tar.gz", fmt.Sprintf("%s/%s", constant.RuntimeDir, runtime.Type)); err != nil {
|
||||
if err := handleUnTar(tmpPath+"/runtime.tar.gz", fmt.Sprintf("%s/%s", constant.RuntimeDir, runtime.Type), secret); err != nil {
|
||||
global.LOG.Errorf("handle recover from runtime.tar.gz failed, err: %v", err)
|
||||
_ = fileOp.DeleteDir(runtimeDir)
|
||||
_ = fileOp.Rename(backPath, runtimeDir)
|
||||
|
@ -35,7 +35,7 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error {
|
||||
itemDir := fmt.Sprintf("website/%s", req.Name)
|
||||
backupDir := path.Join(localDir, itemDir)
|
||||
fileName := fmt.Sprintf("%s_%s.tar.gz", website.PrimaryDomain, timeNow+common.RandStrAndNum(5))
|
||||
if err := handleWebsiteBackup(&website, backupDir, fileName, ""); err != nil {
|
||||
if err := handleWebsiteBackup(&website, backupDir, fileName, "", req.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -65,16 +65,16 @@ func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error {
|
||||
return err
|
||||
}
|
||||
global.LOG.Infof("recover website %s from backup file %s", req.Name, req.File)
|
||||
if err := handleWebsiteRecover(&website, req.File, false); err != nil {
|
||||
if err := handleWebsiteRecover(&website, req.File, false, req.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback bool) error {
|
||||
func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback bool, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "")
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil {
|
||||
if err := handleUnTar(recoverFile, path.Dir(recoverFile), secret); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
@ -107,13 +107,13 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
isOk := false
|
||||
if !isRollback {
|
||||
rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s_%s.tar.gz", website.Alias, time.Now().Format("20060102150405")))
|
||||
if err := handleWebsiteBackup(website, path.Dir(rollbackFile), path.Base(rollbackFile), ""); err != nil {
|
||||
if err := handleWebsiteBackup(website, path.Dir(rollbackFile), path.Base(rollbackFile), "", ""); err != nil {
|
||||
return fmt.Errorf("backup website %s for rollback before recover failed, err: %v", website.Alias, err)
|
||||
}
|
||||
defer func() {
|
||||
if !isOk {
|
||||
global.LOG.Info("recover failed, start to rollback now")
|
||||
if err := handleWebsiteRecover(website, rollbackFile, true); err != nil {
|
||||
if err := handleWebsiteRecover(website, rollbackFile, true, secret); err != nil {
|
||||
global.LOG.Errorf("rollback website %s from %s failed, err: %v", website.Alias, rollbackFile, err)
|
||||
return
|
||||
}
|
||||
@ -141,7 +141,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true); err != nil {
|
||||
if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true, ""); err != nil {
|
||||
global.LOG.Errorf("handle recover from app.tar.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
@ -155,7 +155,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
return err
|
||||
}
|
||||
if runtime.Type == constant.RuntimeNode {
|
||||
if err := handleRuntimeRecover(runtime, fmt.Sprintf("%s/%s.runtime.tar.gz", tmpPath, website.Alias), true); err != nil {
|
||||
if err := handleRuntimeRecover(runtime, fmt.Sprintf("%s/%s.runtime.tar.gz", tmpPath, website.Alias), true, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put runtime.tar.gz into tmp dir successful")
|
||||
@ -163,7 +163,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
}
|
||||
|
||||
siteDir := fmt.Sprintf("%s/openresty/%s/www/sites", constant.AppInstallDir, nginxInfo.Name)
|
||||
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir); err != nil {
|
||||
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir, ""); err != nil {
|
||||
global.LOG.Errorf("handle recover from web.tar.gz failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
@ -182,7 +182,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleWebsiteBackup(website *model.Website, backupDir, fileName string, excludes string) error {
|
||||
func handleWebsiteBackup(website *model.Website, backupDir, fileName string, excludes string, secret string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", ""))
|
||||
if !fileOp.Stat(tmpDir) {
|
||||
@ -216,7 +216,7 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string, exc
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handleAppBackup(&app, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes); err != nil {
|
||||
if err := handleAppBackup(&app, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), excludes, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put app.tar.gz into tmp dir successful")
|
||||
@ -226,7 +226,7 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string, exc
|
||||
return err
|
||||
}
|
||||
if runtime.Type == constant.RuntimeNode {
|
||||
if err := handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias), excludes); err != nil {
|
||||
if err := handleRuntimeBackup(runtime, tmpDir, fmt.Sprintf("%s.runtime.tar.gz", website.Alias), excludes, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put runtime.tar.gz into tmp dir successful")
|
||||
@ -234,11 +234,11 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string, exc
|
||||
}
|
||||
|
||||
websiteDir := fmt.Sprintf("%s/openresty/%s/www/sites/%s", constant.AppInstallDir, nginxInfo.Name, website.Alias)
|
||||
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), excludes); err != nil {
|
||||
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), excludes, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
global.LOG.Info("put web.tar.gz into tmp dir successful, now start to tar tmp dir")
|
||||
if err := handleTar(tmpDir, backupDir, fileName, ""); err != nil {
|
||||
if err := handleTar(tmpDir, backupDir, fileName, "", secret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -173,6 +173,7 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error {
|
||||
if cronjob.ID != 0 {
|
||||
return constant.ErrRecordExist
|
||||
}
|
||||
cronjob.Secret = cronjobDto.Secret
|
||||
if err := copier.Copy(&cronjob, &cronjobDto); err != nil {
|
||||
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||
}
|
||||
@ -279,6 +280,7 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error {
|
||||
upMap["backup_accounts"] = req.BackupAccounts
|
||||
upMap["default_download"] = req.DefaultDownload
|
||||
upMap["retain_copies"] = req.RetainCopies
|
||||
upMap["secret"] = req.Secret
|
||||
return cronjobRepo.Update(id, upMap)
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ func (u *CronjobService) handleApp(cronjob model.Cronjob, startTime time.Time) e
|
||||
record.Source, record.BackupType = loadRecordPath(cronjob, accountMap)
|
||||
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("app/%s/%s", app.App.Key, app.Name))
|
||||
record.FileName = fmt.Sprintf("app_%s_%s.tar.gz", app.Name, startTime.Format("20060102150405")+common.RandStrAndNum(5))
|
||||
if err := handleAppBackup(&app, backupDir, record.FileName, cronjob.ExclusionRules); err != nil {
|
||||
if err := handleAppBackup(&app, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName))
|
||||
@ -74,7 +74,7 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, startTime time.Tim
|
||||
record.Source, record.BackupType = loadRecordPath(cronjob, accountMap)
|
||||
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("website/%s", web.PrimaryDomain))
|
||||
record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", web.PrimaryDomain, startTime.Format("20060102150405")+common.RandStrAndNum(5))
|
||||
if err := handleWebsiteBackup(&web, backupDir, record.FileName, cronjob.ExclusionRules); err != nil {
|
||||
if err := handleWebsiteBackup(&web, backupDir, record.FileName, cronjob.ExclusionRules, cronjob.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
downloadPath, err := u.uploadCronjobBackFile(cronjob, accountMap, path.Join(backupDir, record.FileName))
|
||||
@ -138,7 +138,7 @@ func (u *CronjobService) handleDirectory(cronjob model.Cronjob, startTime time.T
|
||||
}
|
||||
fileName := fmt.Sprintf("directory%s_%s.tar.gz", strings.ReplaceAll(cronjob.SourceDir, "/", "_"), startTime.Format("20060102150405")+common.RandStrAndNum(5))
|
||||
backupDir := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name))
|
||||
if err := handleTar(cronjob.SourceDir, backupDir, fileName, cronjob.ExclusionRules); err != nil {
|
||||
if err := handleTar(cronjob.SourceDir, backupDir, fileName, cronjob.ExclusionRules, cronjob.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
var record model.BackupRecord
|
||||
@ -169,7 +169,7 @@ func (u *CronjobService) handleSystemLog(cronjob model.Cronjob, startTime time.T
|
||||
nameItem := startTime.Format("20060102150405") + common.RandStrAndNum(5)
|
||||
fileName := fmt.Sprintf("system_log_%s.tar.gz", nameItem)
|
||||
backupDir := path.Join(global.CONF.System.TmpDir, "log", nameItem)
|
||||
if err := handleBackupLogs(backupDir, fileName); err != nil {
|
||||
if err := handleBackupLogs(backupDir, fileName, cronjob.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
var record model.BackupRecord
|
||||
@ -210,7 +210,7 @@ func (u *CronjobService) handleSnapshot(cronjob model.Cronjob, startTime time.Ti
|
||||
From: record.BackupType,
|
||||
DefaultDownload: cronjob.DefaultDownload,
|
||||
}
|
||||
name, err := NewISnapshotService().HandleSnapshot(true, logPath, req, startTime.Format("20060102150405")+common.RandStrAndNum(5))
|
||||
name, err := NewISnapshotService().HandleSnapshot(true, logPath, req, startTime.Format("20060102150405")+common.RandStrAndNum(5), cronjob.Secret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -303,7 +303,7 @@ func loadRecordPath(cronjob model.Cronjob, accountMap map[string]cronjobUploadHe
|
||||
return source, backupType
|
||||
}
|
||||
|
||||
func handleBackupLogs(targetDir, fileName string) error {
|
||||
func handleBackupLogs(targetDir, fileName string, secret string) error {
|
||||
websites, err := websiteRepo.List()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -376,7 +376,7 @@ func handleBackupLogs(targetDir, fileName string) error {
|
||||
}
|
||||
global.LOG.Debug("backup ssh log successful!")
|
||||
|
||||
if err := handleTar(targetDir, path.Dir(targetDir), fileName, ""); err != nil {
|
||||
if err := handleTar(targetDir, path.Dir(targetDir), fileName, "", secret); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
|
@ -130,7 +130,7 @@ func (u *CronjobService) handleNtpSync() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleTar(sourceDir, targetDir, name, exclusionRules string) error {
|
||||
func handleTar(sourceDir, targetDir, name, exclusionRules string, secret string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
@ -158,8 +158,14 @@ func handleTar(sourceDir, targetDir, name, exclusionRules string) error {
|
||||
path = sourceDir
|
||||
}
|
||||
|
||||
commands := fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s", targetDir+"/"+name, excludeRules, path)
|
||||
global.LOG.Debug(commands)
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "| openssl enc -aes-256-cbc -salt -k " + secret + " -out"
|
||||
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s %s", " -"+excludeRules, path, extraCmd, targetDir+"/"+name)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s", targetDir+"/"+name, excludeRules, path)
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
stdout, err := cmd.ExecWithTimeOut(commands, 24*time.Hour)
|
||||
if err != nil {
|
||||
if len(stdout) != 0 {
|
||||
@ -170,15 +176,20 @@ func handleTar(sourceDir, targetDir, name, exclusionRules string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleUnTar(sourceFile, targetDir string) error {
|
||||
func handleUnTar(sourceFile, targetDir string, secret string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
commands := fmt.Sprintf("tar zxvfC %s %s", sourceFile, targetDir)
|
||||
global.LOG.Debug(commands)
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "openssl enc -d -aes-256-cbc -k " + secret + " -in " + sourceFile + " | "
|
||||
commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1")
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zxvf %s %s", sourceFile+" -C ", targetDir+" > /dev/null 2>&1")
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
stdout, err := cmd.ExecWithTimeOut(commands, 24*time.Hour)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("do handle untar failed, stdout: %s, err: %v", stdout, err)
|
||||
|
@ -218,12 +218,12 @@ func (f *FileService) Compress(c request.FileCompress) error {
|
||||
if !c.Replace && fo.Stat(filepath.Join(c.Dst, c.Name)) {
|
||||
return buserr.New(constant.ErrFileIsExit)
|
||||
}
|
||||
return fo.Compress(c.Files, c.Dst, c.Name, files.CompressType(c.Type))
|
||||
return fo.Compress(c.Files, c.Dst, c.Name, files.CompressType(c.Type), c.Secret)
|
||||
}
|
||||
|
||||
func (f *FileService) DeCompress(c request.FileDeCompress) error {
|
||||
fo := files.NewFileOp()
|
||||
return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type))
|
||||
return fo.Decompress(c.Path, c.Dst, files.CompressType(c.Type), c.Secret)
|
||||
}
|
||||
|
||||
func (f *FileService) GetContent(op request.FileContentReq) (response.FileInfo, error) {
|
||||
@ -325,7 +325,7 @@ func (f *FileService) FileDownload(d request.FileDownload) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
fo := files.NewFileOp()
|
||||
if err := fo.Compress(d.Paths, tempPath, d.Name, files.CompressType(d.Type)); err != nil {
|
||||
if err := fo.Compress(d.Paths, tempPath, d.Name, files.CompressType(d.Type), ""); err != nil {
|
||||
return "", err
|
||||
}
|
||||
filePath = filepath.Join(tempPath, d.Name)
|
||||
|
@ -39,7 +39,7 @@ type ISnapshotService interface {
|
||||
UpdateDescription(req dto.UpdateDescription) error
|
||||
readFromJson(path string) (SnapshotJson, error)
|
||||
|
||||
HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string) (string, error)
|
||||
HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string, secret string) (string, error)
|
||||
}
|
||||
|
||||
func NewISnapshotService() ISnapshotService {
|
||||
@ -123,7 +123,7 @@ type SnapshotJson struct {
|
||||
}
|
||||
|
||||
func (u *SnapshotService) SnapshotCreate(req dto.SnapshotCreate) error {
|
||||
if _, err := u.HandleSnapshot(false, "", req, time.Now().Format("20060102150405")); err != nil {
|
||||
if _, err := u.HandleSnapshot(false, "", req, time.Now().Format("20060102150405"), req.Secret); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -180,7 +180,7 @@ func (u *SnapshotService) readFromJson(path string) (SnapshotJson, error) {
|
||||
return snap, nil
|
||||
}
|
||||
|
||||
func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string) (string, error) {
|
||||
func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto.SnapshotCreate, timeNow string, secret string) (string, error) {
|
||||
localDir, err := loadLocalDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -274,7 +274,7 @@ func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto
|
||||
return
|
||||
}
|
||||
if snapStatus.Compress != constant.StatusDone {
|
||||
snapCompress(itemHelper, rootDir)
|
||||
snapCompress(itemHelper, rootDir, secret)
|
||||
}
|
||||
if snapStatus.Compress != constant.StatusDone {
|
||||
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed})
|
||||
@ -305,7 +305,7 @@ func (u *SnapshotService) HandleSnapshot(isCronjob bool, logPath string, req dto
|
||||
return snap.Name, fmt.Errorf("snapshot %s 1panel data failed", snap.Name)
|
||||
}
|
||||
loadLogByStatus(snapStatus, logPath)
|
||||
snapCompress(itemHelper, rootDir)
|
||||
snapCompress(itemHelper, rootDir, secret)
|
||||
if snapStatus.Compress != constant.StatusDone {
|
||||
_ = snapshotRepo.Update(snap.ID, map[string]interface{}{"status": constant.StatusFailed})
|
||||
loadLogByStatus(snapStatus, logPath)
|
||||
@ -383,15 +383,20 @@ func updateRecoverStatus(id uint, isRecover bool, interruptStep, status, message
|
||||
}
|
||||
}
|
||||
|
||||
func (u *SnapshotService) handleUnTar(sourceDir, targetDir string) error {
|
||||
func (u *SnapshotService) handleUnTar(sourceDir, targetDir string, secret string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
commands := fmt.Sprintf("tar -zxf %s -C %s .", sourceDir, targetDir)
|
||||
global.LOG.Debug(commands)
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "openssl enc -d -aes-256-cbc -k " + secret + " -in " + sourceDir + " | "
|
||||
commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, targetDir+" > /dev/null 2>&1")
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zxvf %s %s", sourceDir+" -C ", targetDir+" > /dev/null 2>&1")
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute)
|
||||
if err != nil {
|
||||
if len(stdout) != 0 {
|
||||
|
@ -131,7 +131,7 @@ func snapBackup(snap snapHelper, localDir, targetDir string) {
|
||||
defer snap.Wg.Done()
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"backup_data": constant.Running})
|
||||
status := constant.StatusDone
|
||||
if err := handleSnapTar(localDir, targetDir, "1panel_backup.tar.gz", "./system;./system_snapshot;"); err != nil {
|
||||
if err := handleSnapTar(localDir, targetDir, "1panel_backup.tar.gz", "./system;./system_snapshot;", ""); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
snap.Status.BackupData = status
|
||||
@ -158,7 +158,7 @@ func snapPanelData(snap snapHelper, localDir, targetDir string) {
|
||||
sysIP, _ := settingRepo.Get(settingRepo.WithByKey("SystemIP"))
|
||||
_ = settingRepo.Update("SystemIP", "")
|
||||
checkPointOfWal()
|
||||
if err := handleSnapTar(dataDir, targetDir, "1panel_data.tar.gz", exclusionRules); err != nil {
|
||||
if err := handleSnapTar(dataDir, targetDir, "1panel_data.tar.gz", exclusionRules, ""); err != nil {
|
||||
status = err.Error()
|
||||
}
|
||||
_ = snapshotRepo.Update(snap.SnapID, map[string]interface{}{"status": constant.StatusWaiting})
|
||||
@ -168,11 +168,11 @@ func snapPanelData(snap snapHelper, localDir, targetDir string) {
|
||||
_ = settingRepo.Update("SystemIP", sysIP.Value)
|
||||
}
|
||||
|
||||
func snapCompress(snap snapHelper, rootDir string) {
|
||||
func snapCompress(snap snapHelper, rootDir string, secret string) {
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": constant.StatusRunning})
|
||||
tmpDir := path.Join(global.CONF.System.TmpDir, "system")
|
||||
fileName := fmt.Sprintf("%s.tar.gz", path.Base(rootDir))
|
||||
if err := snap.FileOp.Compress([]string{rootDir}, tmpDir, fileName, files.TarGz); err != nil {
|
||||
if err := handleSnapTar(rootDir, tmpDir, fileName, "", secret); err != nil {
|
||||
snap.Status.Compress = err.Error()
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": err.Error()})
|
||||
return
|
||||
@ -221,7 +221,7 @@ func snapUpload(snap snapHelper, accounts string, file string) {
|
||||
_ = os.Remove(source)
|
||||
}
|
||||
|
||||
func handleSnapTar(sourceDir, targetDir, name, exclusionRules string) error {
|
||||
func handleSnapTar(sourceDir, targetDir, name, exclusionRules string, secret string) error {
|
||||
if _, err := os.Stat(targetDir); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
@ -243,9 +243,25 @@ func handleSnapTar(sourceDir, targetDir, name, exclusionRules string) error {
|
||||
exStr += exclude
|
||||
exMap[exclude] = struct{}{}
|
||||
}
|
||||
|
||||
commands := fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s -C %s .", targetDir+"/"+name, exStr, sourceDir)
|
||||
global.LOG.Debug(commands)
|
||||
path := ""
|
||||
if strings.Contains(sourceDir, "/") {
|
||||
itemDir := strings.ReplaceAll(sourceDir[strings.LastIndex(sourceDir, "/"):], "/", "")
|
||||
aheadDir := sourceDir[:strings.LastIndex(sourceDir, "/")]
|
||||
if len(aheadDir) == 0 {
|
||||
aheadDir = "/"
|
||||
}
|
||||
path += fmt.Sprintf("-C %s %s", aheadDir, itemDir)
|
||||
} else {
|
||||
path = sourceDir
|
||||
}
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "| openssl enc -aes-256-cbc -salt -k " + secret + " -out"
|
||||
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s %s %s", " -"+exStr, path, extraCmd, targetDir+"/"+name)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar --warning=no-file-changed --ignore-failed-read -zcf %s %s -C %s .", targetDir+"/"+name, exStr, sourceDir)
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
stdout, err := cmd.ExecWithTimeOut(commands, 30*time.Minute)
|
||||
if err != nil {
|
||||
if len(stdout) != 0 {
|
||||
|
@ -30,14 +30,6 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) {
|
||||
_ = os.MkdirAll(baseDir, os.ModePerm)
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "Backup" {
|
||||
if err := backupBeforeRecover(snap); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "Backup", constant.StatusFailed, fmt.Sprintf("handle backup before recover failed, err: %v", err))
|
||||
return
|
||||
}
|
||||
global.LOG.Debug("handle backup before recover successful!")
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "Download" || req.ReDownload {
|
||||
if err := handleDownloadSnapshot(snap, baseDir); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "Backup", constant.StatusFailed, err.Error())
|
||||
@ -47,13 +39,21 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "Decompress" {
|
||||
if err := handleUnTar(fmt.Sprintf("%s/%s.tar.gz", baseDir, snap.Name), baseDir); err != nil {
|
||||
if err := u.handleUnTar(fmt.Sprintf("%s/%s.tar.gz", baseDir, snap.Name), baseDir, req.Secret); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "Decompress", constant.StatusFailed, fmt.Sprintf("decompress file failed, err: %v", err))
|
||||
return
|
||||
}
|
||||
global.LOG.Debug("decompress snapshot file successful!", baseDir)
|
||||
req.IsNew = true
|
||||
}
|
||||
if req.IsNew || snap.InterruptStep == "Backup" {
|
||||
if err := backupBeforeRecover(snap, ""); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "Backup", constant.StatusFailed, fmt.Sprintf("handle backup before recover failed, err: %v", err))
|
||||
return
|
||||
}
|
||||
global.LOG.Debug("handle backup before recover successful!")
|
||||
req.IsNew = true
|
||||
}
|
||||
snapFileDir = fmt.Sprintf("%s/%s", baseDir, snap.Name)
|
||||
} else {
|
||||
snapFileDir = fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name)
|
||||
@ -114,7 +114,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
}
|
||||
|
||||
if req.IsNew || snap.InterruptStep == "1PanelBackups" {
|
||||
if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_backup.tar.gz"), snapJson.BackupDataDir); err != nil {
|
||||
if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_backup.tar.gz"), snapJson.BackupDataDir, ""); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "1PanelBackups", constant.StatusFailed, err.Error())
|
||||
return
|
||||
}
|
||||
@ -124,7 +124,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
|
||||
if req.IsNew || snap.InterruptStep == "1PanelData" {
|
||||
checkPointOfWal()
|
||||
if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel")); err != nil {
|
||||
if err := u.handleUnTar(path.Join(snapFileDir, "/1panel/1panel_data.tar.gz"), path.Join(snapJson.BaseDir, "1panel"), ""); err != nil {
|
||||
updateRecoverStatus(snap.ID, isRecover, "1PanelData", constant.StatusFailed, err.Error())
|
||||
return
|
||||
}
|
||||
@ -146,7 +146,7 @@ func (u *SnapshotService) HandleSnapshotRecover(snap model.Snapshot, isRecover b
|
||||
_, _ = cmd.Exec("systemctl daemon-reload && systemctl restart 1panel.service")
|
||||
}
|
||||
|
||||
func backupBeforeRecover(snap model.Snapshot) error {
|
||||
func backupBeforeRecover(snap model.Snapshot, secret string) error {
|
||||
baseDir := fmt.Sprintf("%s/1panel_original/original_%s", global.CONF.System.BaseDir, snap.Name)
|
||||
var wg sync.WaitGroup
|
||||
var status model.SnapshotStatus
|
||||
|
@ -117,7 +117,7 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
defer func() {
|
||||
_ = os.Remove(rootDir)
|
||||
}()
|
||||
if err := handleUnTar(rootDir+"/"+fileName, rootDir); err != nil {
|
||||
if err := handleUnTar(rootDir+"/"+fileName, rootDir, ""); err != nil {
|
||||
global.LOG.Errorf("decompress file failed, err: %v", err)
|
||||
_ = settingRepo.Update("SystemStatus", "Free")
|
||||
return
|
||||
@ -175,7 +175,7 @@ func (u *UpgradeService) handleBackup(fileOp files.FileOp, originalDir string) e
|
||||
return err
|
||||
}
|
||||
checkPointOfWal()
|
||||
if err := handleTar(path.Join(global.CONF.System.BaseDir, "1panel/db"), originalDir, "db.tar.gz", "db/1Panel.db-*"); err != nil {
|
||||
if err := handleTar(path.Join(global.CONF.System.BaseDir, "1panel/db"), originalDir, "db.tar.gz", "db/1Panel.db-*", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -191,7 +191,7 @@ func (u *UpgradeService) handleRollback(originalDir string, errStep int) {
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(path.Join(originalDir, "db.tar.gz")); err == nil {
|
||||
if err := handleUnTar(path.Join(originalDir, "db.tar.gz"), global.CONF.System.DbPath); err != nil {
|
||||
if err := handleUnTar(path.Join(originalDir, "db.tar.gz"), global.CONF.System.DbPath, ""); err != nil {
|
||||
global.LOG.Errorf("rollback 1panel db failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) {
|
||||
return nil, err
|
||||
}
|
||||
fileName := websiteSSL.PrimaryDomain + ".zip"
|
||||
if err = fileOp.Compress([]string{path.Join(dir, "fullchain.pem"), path.Join(dir, "privkey.pem")}, dir, fileName, files.SdkZip); err != nil {
|
||||
if err = fileOp.Compress([]string{path.Join(dir, "fullchain.pem"), path.Join(dir, "privkey.pem")}, dir, fileName, files.SdkZip, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.Open(path.Join(dir, fileName))
|
||||
|
@ -88,6 +88,7 @@ func Init() {
|
||||
migrations.AddMonitorMenu,
|
||||
migrations.AddFtp,
|
||||
migrations.AddProxy,
|
||||
migrations.AddCronJobColumn,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -238,3 +238,13 @@ var AddProxy = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddCronJobColumn = &gormigrate.Migration{
|
||||
ID: "20240524-add-cronjob-command",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Cronjob{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
type ShellArchiver interface {
|
||||
Extract(filePath, dstDir string) error
|
||||
Compress(sourcePaths []string, dstFile string) error
|
||||
Extract(filePath, dstDir string, secret string) error
|
||||
Compress(sourcePaths []string, dstFile string, secret string) error
|
||||
}
|
||||
|
||||
func NewShellArchiver(compressType CompressType) (ShellArchiver, error) {
|
||||
@ -18,6 +18,8 @@ func NewShellArchiver(compressType CompressType) (ShellArchiver, error) {
|
||||
return nil, err
|
||||
}
|
||||
return NewTarArchiver(compressType), nil
|
||||
case TarGz:
|
||||
return NewTarGzArchiver(), nil
|
||||
case Zip:
|
||||
if err := checkCmdAvailability("zip"); err != nil {
|
||||
return nil, err
|
||||
|
@ -476,7 +476,7 @@ func getFormat(cType CompressType) archiver.CompressedArchive {
|
||||
return format
|
||||
}
|
||||
|
||||
func (f FileOp) Compress(srcRiles []string, dst string, name string, cType CompressType) error {
|
||||
func (f FileOp) Compress(srcRiles []string, dst string, name string, cType CompressType, secret string) error {
|
||||
format := getFormat(cType)
|
||||
|
||||
fileMaps := make(map[string]string, len(srcRiles))
|
||||
@ -505,7 +505,13 @@ func (f FileOp) Compress(srcRiles []string, dst string, name string, cType Compr
|
||||
return nil
|
||||
}
|
||||
_ = f.DeleteFile(dstFile)
|
||||
return NewZipArchiver().Compress(srcRiles, dstFile)
|
||||
return NewZipArchiver().Compress(srcRiles, dstFile, "")
|
||||
case TarGz:
|
||||
err = NewTarGzArchiver().Compress(srcRiles, dstFile, secret)
|
||||
if err != nil {
|
||||
_ = f.DeleteFile(dstFile)
|
||||
return err
|
||||
}
|
||||
default:
|
||||
err = format.Archive(context.Background(), out, files)
|
||||
if err != nil {
|
||||
@ -583,14 +589,22 @@ func (f FileOp) decompressWithSDK(srcFile string, dst string, cType CompressType
|
||||
return format.Extract(context.Background(), input, nil, handler)
|
||||
}
|
||||
|
||||
func (f FileOp) Decompress(srcFile string, dst string, cType CompressType) error {
|
||||
func (f FileOp) Decompress(srcFile string, dst string, cType CompressType, secret string) error {
|
||||
if err := f.decompressWithSDK(srcFile, dst, cType); err != nil {
|
||||
if cType == Tar || cType == Zip {
|
||||
shellArchiver, err := NewShellArchiver(cType)
|
||||
if err != nil {
|
||||
return err
|
||||
if cType == Tar || cType == Zip || cType == TarGz {
|
||||
if secret != "" {
|
||||
shellArchiver, err := NewShellArchiver(TarGz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return shellArchiver.Extract(srcFile, dst, secret)
|
||||
} else {
|
||||
shellArchiver, err := NewShellArchiver(cType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return shellArchiver.Extract(srcFile, dst, secret)
|
||||
}
|
||||
return shellArchiver.Extract(srcFile, dst)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ func NewTarArchiver(compressType CompressType) ShellArchiver {
|
||||
}
|
||||
}
|
||||
|
||||
func (t TarArchiver) Extract(FilePath string, dstDir string) error {
|
||||
func (t TarArchiver) Extract(FilePath string, dstDir string, secret string) error {
|
||||
return cmd.ExecCmd(fmt.Sprintf("%s %s %s -C %s", t.Cmd, t.getOptionStr("extract"), FilePath, dstDir))
|
||||
}
|
||||
|
||||
func (t TarArchiver) Compress(sourcePaths []string, dstFile string) error {
|
||||
func (t TarArchiver) Compress(sourcePaths []string, dstFile string, secret string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
58
backend/utils/files/tar_gz.go
Normal file
58
backend/utils/files/tar_gz.go
Normal file
@ -0,0 +1,58 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type TarGzArchiver struct {
|
||||
}
|
||||
|
||||
func NewTarGzArchiver() ShellArchiver {
|
||||
return &TarGzArchiver{}
|
||||
}
|
||||
|
||||
func (t TarGzArchiver) Extract(filePath, dstDir string, secret string) error {
|
||||
var err error
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "openssl enc -d -aes-256-cbc -k " + secret + " -in " + filePath + " | "
|
||||
commands = fmt.Sprintf("%s tar -zxvf - -C %s", extraCmd, dstDir+" > /dev/null 2>&1")
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zxvf %s %s", filePath+" -C ", dstDir+" > /dev/null 2>&1")
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
if err = cmd.ExecCmd(commands); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t TarGzArchiver) Compress(sourcePaths []string, dstFile string, secret string) error {
|
||||
var err error
|
||||
path := ""
|
||||
itemDir := ""
|
||||
for _, item := range sourcePaths {
|
||||
itemDir += filepath.Base(item) + " "
|
||||
}
|
||||
aheadDir := dstFile[:strings.LastIndex(dstFile, "/")]
|
||||
if len(aheadDir) == 0 {
|
||||
aheadDir = "/"
|
||||
}
|
||||
path += fmt.Sprintf("- -C %s %s", aheadDir, itemDir)
|
||||
commands := ""
|
||||
if secret != "" {
|
||||
extraCmd := "| openssl enc -aes-256-cbc -salt -k " + secret + " -out"
|
||||
commands = fmt.Sprintf("tar -zcf %s %s %s", path, extraCmd, dstFile)
|
||||
} else {
|
||||
commands = fmt.Sprintf("tar -zcf %s %s", dstFile, path)
|
||||
}
|
||||
global.LOG.Debug(strings.ReplaceAll(commands, secret, "******"))
|
||||
if err = cmd.ExecCmd(commands); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -17,14 +17,14 @@ func NewZipArchiver() ShellArchiver {
|
||||
return &ZipArchiver{}
|
||||
}
|
||||
|
||||
func (z ZipArchiver) Extract(filePath, dstDir string) error {
|
||||
func (z ZipArchiver) Extract(filePath, dstDir string, secret string) error {
|
||||
if err := checkCmdAvailability("unzip"); err != nil {
|
||||
return err
|
||||
}
|
||||
return cmd.ExecCmd(fmt.Sprintf("unzip -qo %s -d %s", filePath, dstDir))
|
||||
}
|
||||
|
||||
func (z ZipArchiver) Compress(sourcePaths []string, dstFile string) error {
|
||||
func (z ZipArchiver) Compress(sourcePaths []string, dstFile string, _ string) error {
|
||||
var err error
|
||||
tmpFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("%s%s.zip", common.RandStr(50), time.Now().Format("20060102150405")))
|
||||
op := NewFileOp()
|
||||
|
@ -57,6 +57,7 @@ export namespace Backup {
|
||||
type: string;
|
||||
name: string;
|
||||
detailName: string;
|
||||
secret: string;
|
||||
}
|
||||
export interface Recover {
|
||||
source: string;
|
||||
@ -64,5 +65,6 @@ export namespace Backup {
|
||||
name: string;
|
||||
detailName: string;
|
||||
file: string;
|
||||
secret: string;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ export namespace Cronjob {
|
||||
backupAccountList: Array<string>;
|
||||
retainCopies: number;
|
||||
status: string;
|
||||
secret: string;
|
||||
}
|
||||
export interface CronjobCreate {
|
||||
name: string;
|
||||
@ -44,6 +45,7 @@ export namespace Cronjob {
|
||||
backupAccounts: string;
|
||||
defaultDownload: string;
|
||||
retainCopies: number;
|
||||
secret: string;
|
||||
}
|
||||
export interface SpecObj {
|
||||
specType: string;
|
||||
@ -68,6 +70,7 @@ export namespace Cronjob {
|
||||
backupAccounts: string;
|
||||
defaultDownload: string;
|
||||
retainCopies: number;
|
||||
secret: string;
|
||||
}
|
||||
export interface CronjobDelete {
|
||||
ids: Array<number>;
|
||||
|
@ -80,12 +80,14 @@ export namespace File {
|
||||
dst: string;
|
||||
name: string;
|
||||
replace: boolean;
|
||||
secret: string;
|
||||
}
|
||||
|
||||
export interface FileDeCompress {
|
||||
path: string;
|
||||
dst: string;
|
||||
type: string;
|
||||
secret: string;
|
||||
}
|
||||
|
||||
export interface FileEdit {
|
||||
|
@ -113,6 +113,7 @@ export namespace Setting {
|
||||
fromAccounts: Array<string>;
|
||||
defaultDownload: string;
|
||||
description: string;
|
||||
secret: string;
|
||||
}
|
||||
export interface SnapshotImport {
|
||||
from: string;
|
||||
@ -123,6 +124,7 @@ export namespace Setting {
|
||||
id: number;
|
||||
isNew: boolean;
|
||||
reDownload: boolean;
|
||||
secret: string;
|
||||
}
|
||||
export interface SnapshotInfo {
|
||||
id: number;
|
||||
@ -141,6 +143,7 @@ export namespace Setting {
|
||||
rollbackStatus: string;
|
||||
rollbackMessage: string;
|
||||
lastRollbackedAt: string;
|
||||
secret: string;
|
||||
}
|
||||
export interface SnapshotStatus {
|
||||
panel: string;
|
||||
|
@ -43,6 +43,14 @@
|
||||
<el-button type="primary" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
<el-form-item
|
||||
:label="$t('setting.compressPassword')"
|
||||
prop="secret"
|
||||
style="margin-top: 10px"
|
||||
v-if="type === 'app' || type === 'website'"
|
||||
>
|
||||
<el-input v-model="secret"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-table-column type="selection" fix />
|
||||
<el-table-column :label="$t('commons.table.name')" prop="fileName" show-overflow-tooltip />
|
||||
@ -105,6 +113,7 @@ const name = ref();
|
||||
const detailName = ref();
|
||||
const backupPath = ref();
|
||||
const status = ref();
|
||||
const secret = ref();
|
||||
|
||||
interface DialogProps {
|
||||
type: string;
|
||||
@ -180,6 +189,7 @@ const onBackup = async () => {
|
||||
type: type.value,
|
||||
name: name.value,
|
||||
detailName: detailName.value,
|
||||
secret: secret.value,
|
||||
};
|
||||
loading.value = true;
|
||||
await handleBackup(params)
|
||||
@ -209,6 +219,7 @@ const onRecover = async (row: Backup.RecordInfo) => {
|
||||
name: name.value,
|
||||
detailName: detailName.value,
|
||||
file: row.fileDir + '/' + row.fileName,
|
||||
secret: secret.value,
|
||||
};
|
||||
loading.value = true;
|
||||
await handleRecover(params)
|
||||
|
@ -68,6 +68,14 @@
|
||||
>
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
<el-form-item
|
||||
:label="$t('setting.compressPassword')"
|
||||
prop="secret"
|
||||
style="margin-top: 10px"
|
||||
v-if="type === 'app' || type === 'website'"
|
||||
>
|
||||
<el-input v-model="secret"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-table-column type="selection" fix />
|
||||
<el-table-column :label="$t('commons.table.name')" show-overflow-tooltip prop="name" />
|
||||
@ -129,6 +137,7 @@ const type = ref();
|
||||
const name = ref();
|
||||
const detailName = ref();
|
||||
const remark = ref();
|
||||
const secret = ref();
|
||||
interface DialogProps {
|
||||
type: string;
|
||||
name: string;
|
||||
@ -191,6 +200,7 @@ const onRecover = async (row: File.File) => {
|
||||
name: name.value,
|
||||
detailName: detailName.value,
|
||||
file: baseDir.value + row.name,
|
||||
secret: secret.value,
|
||||
};
|
||||
loading.value = true;
|
||||
await handleRecoverByUpload(params)
|
||||
|
@ -1541,6 +1541,7 @@ const message = {
|
||||
ifShow: 'Whether to Show',
|
||||
menu: 'Menu',
|
||||
confirmMessage: 'The page will be refreshed to update the advanced menu list. Continue?',
|
||||
compressPassword: 'Compression Password',
|
||||
},
|
||||
license: {
|
||||
community: 'Community Edition: ',
|
||||
|
@ -1435,6 +1435,7 @@ const message = {
|
||||
ifShow: '是否顯示',
|
||||
menu: '選單',
|
||||
confirmMessage: '即將刷新頁面更新高級功能菜單列表,是否繼續?',
|
||||
compressPassword: '壓縮密碼',
|
||||
},
|
||||
license: {
|
||||
community: '社區版:',
|
||||
|
@ -1436,6 +1436,7 @@ const message = {
|
||||
ifShow: '是否显示',
|
||||
menu: '菜单',
|
||||
confirmMessage: '即将刷新页面更新高级功能菜单列表,是否继续?',
|
||||
compressPassword: '压缩密码',
|
||||
},
|
||||
license: {
|
||||
community: '社区版:',
|
||||
|
@ -300,6 +300,13 @@
|
||||
</el-link>
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('setting.compressPassword')"
|
||||
prop="secret"
|
||||
v-if="isBackup() && dialogData.rowData!.type !== 'database'"
|
||||
>
|
||||
<el-input v-model="dialogData.rowData!.secret" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('cronjob.default_download_path')" prop="defaultDownload">
|
||||
<el-select class="selectClass" v-model="dialogData.rowData!.defaultDownload">
|
||||
<div v-for="item in accountOptions" :key="item.label">
|
||||
|
@ -37,6 +37,9 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.compressPassword')" prop="secret" v-if="form.type === 'tar.gz'">
|
||||
<el-input v-model="form.secret"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="form.replace" :label="$t('file.replace')"></el-checkbox>
|
||||
</el-form-item>
|
||||
@ -79,7 +82,7 @@ const rules = reactive<FormRules>({
|
||||
|
||||
const fileForm = ref<FormInstance>();
|
||||
const loading = ref(false);
|
||||
const form = ref<File.FileCompress>({ files: [], type: 'zip', dst: '', name: '', replace: false });
|
||||
const form = ref<File.FileCompress>({ files: [], type: 'zip', dst: '', name: '', replace: false, secret: '' });
|
||||
const options = ref<string[]>([]);
|
||||
const open = ref(false);
|
||||
const title = ref('');
|
||||
|
@ -30,6 +30,9 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.compressPassword')" prop="secret" v-if="name.includes('tar.gz')">
|
||||
<el-input v-model="form.secret"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -146,6 +146,9 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.compressPassword')" prop="secret">
|
||||
<el-input v-model="snapInfo.secret"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.description')" prop="description">
|
||||
<el-input type="textarea" clearable v-model="snapInfo.description" />
|
||||
</el-form-item>
|
||||
@ -231,6 +234,7 @@ let snapInfo = reactive<Setting.SnapshotCreate>({
|
||||
defaultDownload: '',
|
||||
fromAccounts: [],
|
||||
description: '',
|
||||
secret: '',
|
||||
});
|
||||
const cleanData = ref();
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
<el-col :span="22">
|
||||
<span class="card-title">{{ $t('setting.recover') }}</span>
|
||||
<el-divider class="divider" />
|
||||
<el-form-item :label="$t('setting.compressPassword')" prop="secret">
|
||||
<el-input v-model="snapInfo.secret"></el-input>
|
||||
</el-form-item>
|
||||
<div v-if="!snapInfo.recoverStatus && !snapInfo.lastRecoveredAt">
|
||||
<el-alert center class="alert" style="height: 257px" :closable="false">
|
||||
<el-button size="large" round plain type="primary" @click="recoverSnapshot(true)">
|
||||
@ -197,7 +200,12 @@ const handleClose = () => {
|
||||
|
||||
const doRecover = async (isNew: boolean) => {
|
||||
loading.value = true;
|
||||
await snapshotRecover({ id: snapInfo.value.id, isNew: isNew, reDownload: reDownload.value })
|
||||
await snapshotRecover({
|
||||
id: snapInfo.value.id,
|
||||
isNew: isNew,
|
||||
reDownload: reDownload.value,
|
||||
secret: snapInfo.value.secret,
|
||||
})
|
||||
.then(() => {
|
||||
emit('search');
|
||||
loading.value = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user