mirror of https://github.com/1Panel-dev/1Panel
appstorecrontabdatabasedockerdocker-composedocker-containerdocker-imagedocker-uifilemanagerlamplnmppanel
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
652 lines
20 KiB
652 lines
20 KiB
package service |
|
|
|
import ( |
|
"bufio" |
|
"context" |
|
"encoding/base64" |
|
"encoding/json" |
|
"fmt" |
|
"os" |
|
"path" |
|
"sort" |
|
"strings" |
|
"sync" |
|
"time" |
|
|
|
"github.com/1Panel-dev/1Panel/backend/app/dto" |
|
"github.com/1Panel-dev/1Panel/backend/app/model" |
|
"github.com/1Panel-dev/1Panel/backend/buserr" |
|
"github.com/1Panel-dev/1Panel/backend/constant" |
|
"github.com/1Panel-dev/1Panel/backend/global" |
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage" |
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage/client" |
|
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files" |
|
"github.com/jinzhu/copier" |
|
"github.com/pkg/errors" |
|
) |
|
|
|
type BackupService struct{} |
|
|
|
type IBackupService interface { |
|
List() ([]dto.BackupInfo, error) |
|
SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error) |
|
SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) |
|
LoadOneDriveInfo() (dto.OneDriveInfo, error) |
|
DownloadRecord(info dto.DownloadRecord) (string, error) |
|
Create(backupDto dto.BackupOperate) error |
|
GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) |
|
Update(ireq dto.BackupOperate) error |
|
Delete(id uint) error |
|
DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error |
|
BatchDeleteRecord(ids []uint) error |
|
NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) |
|
ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) |
|
|
|
ListFiles(req dto.BackupSearchFile) []string |
|
|
|
MysqlBackup(db dto.CommonBackup) error |
|
PostgresqlBackup(db dto.CommonBackup) error |
|
MysqlRecover(db dto.CommonRecover) error |
|
PostgresqlRecover(db dto.CommonRecover) error |
|
MysqlRecoverByUpload(req dto.CommonRecover) error |
|
PostgresqlRecoverByUpload(req dto.CommonRecover) error |
|
|
|
RedisBackup(db dto.CommonBackup) error |
|
RedisRecover(db dto.CommonRecover) error |
|
|
|
WebsiteBackup(db dto.CommonBackup) error |
|
WebsiteRecover(req dto.CommonRecover) error |
|
|
|
AppBackup(db dto.CommonBackup) (*model.BackupRecord, error) |
|
AppRecover(req dto.CommonRecover) error |
|
|
|
Run() |
|
} |
|
|
|
func NewIBackupService() IBackupService { |
|
return &BackupService{} |
|
} |
|
|
|
func (u *BackupService) List() ([]dto.BackupInfo, error) { |
|
ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc")) |
|
var dtobas []dto.BackupInfo |
|
dtobas = append(dtobas, u.loadByType("LOCAL", ops)) |
|
dtobas = append(dtobas, u.loadByType("OSS", ops)) |
|
dtobas = append(dtobas, u.loadByType("S3", ops)) |
|
dtobas = append(dtobas, u.loadByType("SFTP", ops)) |
|
dtobas = append(dtobas, u.loadByType("MINIO", ops)) |
|
dtobas = append(dtobas, u.loadByType("COS", ops)) |
|
dtobas = append(dtobas, u.loadByType("KODO", ops)) |
|
dtobas = append(dtobas, u.loadByType("OneDrive", ops)) |
|
dtobas = append(dtobas, u.loadByType("WebDAV", ops)) |
|
return dtobas, err |
|
} |
|
|
|
func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, []dto.BackupRecords, error) { |
|
total, records, err := backupRepo.PageRecord( |
|
search.Page, search.PageSize, |
|
commonRepo.WithOrderBy("created_at desc"), |
|
commonRepo.WithByName(search.Name), |
|
commonRepo.WithByType(search.Type), |
|
backupRepo.WithByDetailName(search.DetailName), |
|
) |
|
if err != nil { |
|
return 0, nil, err |
|
} |
|
|
|
datas, err := u.loadRecordSize(records) |
|
sort.Slice(datas, func(i, j int) bool { |
|
return datas[i].CreatedAt.After(datas[j].CreatedAt) |
|
}) |
|
return total, datas, err |
|
} |
|
|
|
func (u *BackupService) ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) { |
|
records, err := backupRepo.ListRecord( |
|
commonRepo.WithOrderBy("created_at asc"), |
|
commonRepo.WithByName(name), |
|
commonRepo.WithByType("app"), |
|
backupRepo.WithFileNameStartWith(fileName), |
|
backupRepo.WithByDetailName(detailName), |
|
) |
|
if err != nil { |
|
return nil, err |
|
} |
|
return records, err |
|
} |
|
|
|
func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) { |
|
total, records, err := backupRepo.PageRecord( |
|
search.Page, search.PageSize, |
|
commonRepo.WithOrderBy("created_at desc"), |
|
backupRepo.WithByCronID(search.CronjobID), |
|
) |
|
if err != nil { |
|
return 0, nil, err |
|
} |
|
|
|
datas, err := u.loadRecordSize(records) |
|
sort.Slice(datas, func(i, j int) bool { |
|
return datas[i].CreatedAt.After(datas[j].CreatedAt) |
|
}) |
|
return total, datas, err |
|
} |
|
|
|
type loadSizeHelper struct { |
|
isOk bool |
|
backupPath string |
|
client cloud_storage.CloudStorageClient |
|
} |
|
|
|
func (u *BackupService) LoadOneDriveInfo() (dto.OneDriveInfo, error) { |
|
var data dto.OneDriveInfo |
|
data.RedirectUri = constant.OneDriveRedirectURI |
|
clientID, err := settingRepo.Get(settingRepo.WithByKey("OneDriveID")) |
|
if err != nil { |
|
return data, err |
|
} |
|
idItem, err := base64.StdEncoding.DecodeString(clientID.Value) |
|
if err != nil { |
|
return data, err |
|
} |
|
data.ClientID = string(idItem) |
|
clientSecret, err := settingRepo.Get(settingRepo.WithByKey("OneDriveSc")) |
|
if err != nil { |
|
return data, err |
|
} |
|
secretItem, err := base64.StdEncoding.DecodeString(clientSecret.Value) |
|
if err != nil { |
|
return data, err |
|
} |
|
data.ClientSecret = string(secretItem) |
|
|
|
return data, err |
|
} |
|
|
|
func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error) { |
|
if info.Source == "LOCAL" { |
|
localDir, err := loadLocalDir() |
|
if err != nil { |
|
return "", err |
|
} |
|
return path.Join(localDir, info.FileDir, info.FileName), nil |
|
} |
|
backup, _ := backupRepo.Get(commonRepo.WithByType(info.Source)) |
|
if backup.ID == 0 { |
|
return "", constant.ErrRecordNotFound |
|
} |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { |
|
return "", err |
|
} |
|
varMap["bucket"] = backup.Bucket |
|
switch backup.Type { |
|
case constant.Sftp, constant.WebDAV: |
|
varMap["username"] = backup.AccessKey |
|
varMap["password"] = backup.Credential |
|
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: |
|
varMap["accessKey"] = backup.AccessKey |
|
varMap["secretKey"] = backup.Credential |
|
case constant.OneDrive: |
|
varMap["accessToken"] = backup.Credential |
|
} |
|
backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap) |
|
if err != nil { |
|
return "", fmt.Errorf("new cloud storage client failed, err: %v", err) |
|
} |
|
targetPath := fmt.Sprintf("%s/download/%s/%s", constant.DataDir, info.FileDir, info.FileName) |
|
if _, err := os.Stat(path.Dir(targetPath)); err != nil && os.IsNotExist(err) { |
|
if err = os.MkdirAll(path.Dir(targetPath), os.ModePerm); err != nil { |
|
global.LOG.Errorf("mkdir %s failed, err: %v", path.Dir(targetPath), err) |
|
} |
|
} |
|
srcPath := fmt.Sprintf("%s/%s", info.FileDir, info.FileName) |
|
if len(backup.BackupPath) != 0 { |
|
srcPath = path.Join(strings.TrimPrefix(backup.BackupPath, "/"), srcPath) |
|
} |
|
if exist, _ := backClient.Exist(srcPath); exist { |
|
isOK, err := backClient.Download(srcPath, targetPath) |
|
if !isOK { |
|
return "", fmt.Errorf("cloud storage download failed, err: %v", err) |
|
} |
|
} |
|
return targetPath, nil |
|
} |
|
|
|
func (u *BackupService) Create(req dto.BackupOperate) error { |
|
backup, _ := backupRepo.Get(commonRepo.WithByType(req.Type)) |
|
if backup.ID != 0 { |
|
return constant.ErrRecordExist |
|
} |
|
if err := copier.Copy(&backup, &req); err != nil { |
|
return errors.WithMessage(constant.ErrStructTransform, err.Error()) |
|
} |
|
|
|
if req.Type == constant.OneDrive { |
|
if err := u.loadAccessToken(&backup); err != nil { |
|
return err |
|
} |
|
} |
|
if req.Type != "LOCAL" { |
|
if _, err := u.checkBackupConn(&backup); err != nil { |
|
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err) |
|
} |
|
} |
|
if backup.Type == constant.OneDrive { |
|
StartRefreshOneDriveToken() |
|
} |
|
if err := backupRepo.Create(&backup); err != nil { |
|
return err |
|
} |
|
return nil |
|
} |
|
|
|
func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, error) { |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backupDto.Vars), &varMap); err != nil { |
|
return nil, err |
|
} |
|
switch backupDto.Type { |
|
case constant.Sftp, constant.WebDAV: |
|
varMap["username"] = backupDto.AccessKey |
|
varMap["password"] = backupDto.Credential |
|
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: |
|
varMap["accessKey"] = backupDto.AccessKey |
|
varMap["secretKey"] = backupDto.Credential |
|
} |
|
client, err := cloud_storage.NewCloudStorageClient(backupDto.Type, varMap) |
|
if err != nil { |
|
return nil, err |
|
} |
|
return client.ListBuckets() |
|
} |
|
|
|
func (u *BackupService) Delete(id uint) error { |
|
backup, _ := backupRepo.Get(commonRepo.WithByID(id)) |
|
if backup.ID == 0 { |
|
return constant.ErrRecordNotFound |
|
} |
|
if backup.Type == constant.OneDrive { |
|
global.Cron.Remove(global.OneDriveCronID) |
|
} |
|
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByDefaultDownload(backup.Type)) |
|
if len(cronjobs) != 0 { |
|
return buserr.New(constant.ErrBackupInUsed) |
|
} |
|
return backupRepo.Delete(commonRepo.WithByID(id)) |
|
} |
|
|
|
func (u *BackupService) DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error { |
|
if !withDeleteFile { |
|
return backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType(backupType), commonRepo.WithByName(name), backupRepo.WithByDetailName(detailName)) |
|
} |
|
|
|
records, err := backupRepo.ListRecord(commonRepo.WithByType(backupType), commonRepo.WithByName(name), backupRepo.WithByDetailName(detailName)) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
for _, record := range records { |
|
backupAccount, err := backupRepo.Get(commonRepo.WithByType(record.Source)) |
|
if err != nil { |
|
global.LOG.Errorf("load backup account %s info from db failed, err: %v", record.Source, err) |
|
continue |
|
} |
|
client, err := u.NewClient(&backupAccount) |
|
if err != nil { |
|
global.LOG.Errorf("new client for backup account %s failed, err: %v", record.Source, err) |
|
continue |
|
} |
|
if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil { |
|
global.LOG.Errorf("remove file %s from %s failed, err: %v", path.Join(record.FileDir, record.FileName), record.Source, err) |
|
} |
|
_ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByID(record.ID)) |
|
} |
|
return nil |
|
} |
|
|
|
func (u *BackupService) BatchDeleteRecord(ids []uint) error { |
|
records, err := backupRepo.ListRecord(commonRepo.WithIdsIn(ids)) |
|
if err != nil { |
|
return err |
|
} |
|
for _, record := range records { |
|
backupAccount, err := backupRepo.Get(commonRepo.WithByType(record.Source)) |
|
if err != nil { |
|
global.LOG.Errorf("load backup account %s info from db failed, err: %v", record.Source, err) |
|
continue |
|
} |
|
client, err := u.NewClient(&backupAccount) |
|
if err != nil { |
|
global.LOG.Errorf("new client for backup account %s failed, err: %v", record.Source, err) |
|
continue |
|
} |
|
if _, err = client.Delete(path.Join(record.FileDir, record.FileName)); err != nil { |
|
global.LOG.Errorf("remove file %s from %s failed, err: %v", path.Join(record.FileDir, record.FileName), record.Source, err) |
|
} |
|
} |
|
return backupRepo.DeleteRecord(context.Background(), commonRepo.WithIdsIn(ids)) |
|
} |
|
|
|
func (u *BackupService) Update(req dto.BackupOperate) error { |
|
backup, err := backupRepo.Get(commonRepo.WithByID(req.ID)) |
|
if err != nil { |
|
return constant.ErrRecordNotFound |
|
} |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(req.Vars), &varMap); err != nil { |
|
return err |
|
} |
|
|
|
oldVars := backup.Vars |
|
oldDir, err := loadLocalDir() |
|
if err != nil { |
|
return err |
|
} |
|
upMap := make(map[string]interface{}) |
|
upMap["bucket"] = req.Bucket |
|
upMap["access_key"] = req.AccessKey |
|
upMap["credential"] = req.Credential |
|
upMap["backup_path"] = req.BackupPath |
|
upMap["vars"] = req.Vars |
|
backup.Bucket = req.Bucket |
|
backup.Vars = req.Vars |
|
backup.Credential = req.Credential |
|
backup.AccessKey = req.AccessKey |
|
backup.BackupPath = req.BackupPath |
|
|
|
if req.Type == constant.OneDrive { |
|
if err := u.loadAccessToken(&backup); err != nil { |
|
return err |
|
} |
|
upMap["credential"] = backup.Credential |
|
upMap["vars"] = backup.Vars |
|
} |
|
if backup.Type != "LOCAL" { |
|
isOk, err := u.checkBackupConn(&backup) |
|
if err != nil || !isOk { |
|
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err) |
|
} |
|
} |
|
|
|
if err := backupRepo.Update(req.ID, upMap); err != nil { |
|
return err |
|
} |
|
if backup.Type == "LOCAL" { |
|
if dir, ok := varMap["dir"]; ok { |
|
if dirStr, isStr := dir.(string); isStr { |
|
if strings.HasSuffix(dirStr, "/") && dirStr != "/" { |
|
dirStr = dirStr[:strings.LastIndex(dirStr, "/")] |
|
} |
|
if err := copyDir(oldDir, dirStr); err != nil { |
|
_ = backupRepo.Update(req.ID, map[string]interface{}{"vars": oldVars}) |
|
return err |
|
} |
|
global.CONF.System.Backup = dirStr |
|
} |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
func (u *BackupService) ListFiles(req dto.BackupSearchFile) []string { |
|
var datas []string |
|
backup, err := backupRepo.Get(backupRepo.WithByType(req.Type)) |
|
if err != nil { |
|
return datas |
|
} |
|
client, err := u.NewClient(&backup) |
|
if err != nil { |
|
return datas |
|
} |
|
prefix := "system_snapshot" |
|
if len(backup.BackupPath) != 0 { |
|
prefix = path.Join(strings.TrimPrefix(backup.BackupPath, "/"), prefix) |
|
} |
|
files, err := client.ListObjects(prefix) |
|
if err != nil { |
|
global.LOG.Debugf("load files from %s failed, err: %v", req.Type, err) |
|
return datas |
|
} |
|
for _, file := range files { |
|
if len(file) != 0 { |
|
datas = append(datas, path.Base(file)) |
|
} |
|
} |
|
return datas |
|
} |
|
|
|
func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) { |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { |
|
return nil, err |
|
} |
|
varMap["bucket"] = backup.Bucket |
|
switch backup.Type { |
|
case constant.Sftp, constant.WebDAV: |
|
varMap["username"] = backup.AccessKey |
|
varMap["password"] = backup.Credential |
|
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: |
|
varMap["accessKey"] = backup.AccessKey |
|
varMap["secretKey"] = backup.Credential |
|
} |
|
|
|
backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return backClient, nil |
|
} |
|
|
|
func (u *BackupService) loadByType(accountType string, accounts []model.BackupAccount) dto.BackupInfo { |
|
for _, account := range accounts { |
|
if account.Type == accountType { |
|
var item dto.BackupInfo |
|
if err := copier.Copy(&item, &account); err != nil { |
|
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err) |
|
} |
|
if account.Type == constant.OneDrive { |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(item.Vars), &varMap); err != nil { |
|
return dto.BackupInfo{Type: accountType} |
|
} |
|
delete(varMap, "refresh_token") |
|
itemVars, _ := json.Marshal(varMap) |
|
item.Vars = string(itemVars) |
|
} |
|
return item |
|
} |
|
} |
|
return dto.BackupInfo{Type: accountType} |
|
} |
|
|
|
func (u *BackupService) loadAccessToken(backup *model.BackupAccount) error { |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { |
|
return fmt.Errorf("unmarshal backup vars failed, err: %v", err) |
|
} |
|
refreshToken, err := client.RefreshToken("authorization_code", "refreshToken", varMap) |
|
if err != nil { |
|
return err |
|
} |
|
delete(varMap, "code") |
|
varMap["refresh_status"] = constant.StatusSuccess |
|
varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout) |
|
varMap["refresh_token"] = refreshToken |
|
itemVars, err := json.Marshal(varMap) |
|
if err != nil { |
|
return fmt.Errorf("json marshal var map failed, err: %v", err) |
|
} |
|
backup.Vars = string(itemVars) |
|
return nil |
|
} |
|
|
|
func (u *BackupService) loadRecordSize(records []model.BackupRecord) ([]dto.BackupRecords, error) { |
|
var datas []dto.BackupRecords |
|
clientMap := make(map[string]loadSizeHelper) |
|
var wg sync.WaitGroup |
|
for i := 0; i < len(records); i++ { |
|
var item dto.BackupRecords |
|
if err := copier.Copy(&item, &records[i]); err != nil { |
|
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) |
|
} |
|
itemPath := path.Join(records[i].FileDir, records[i].FileName) |
|
if _, ok := clientMap[records[i].Source]; !ok { |
|
backup, err := backupRepo.Get(commonRepo.WithByType(records[i].Source)) |
|
if err != nil { |
|
global.LOG.Errorf("load backup model %s from db failed, err: %v", records[i].Source, err) |
|
clientMap[records[i].Source] = loadSizeHelper{} |
|
datas = append(datas, item) |
|
continue |
|
} |
|
client, err := u.NewClient(&backup) |
|
if err != nil { |
|
global.LOG.Errorf("load backup client %s from db failed, err: %v", records[i].Source, err) |
|
clientMap[records[i].Source] = loadSizeHelper{} |
|
datas = append(datas, item) |
|
continue |
|
} |
|
item.Size, _ = client.Size(path.Join(strings.TrimLeft(backup.BackupPath, "/"), itemPath)) |
|
datas = append(datas, item) |
|
clientMap[records[i].Source] = loadSizeHelper{backupPath: strings.TrimLeft(backup.BackupPath, "/"), client: client, isOk: true} |
|
continue |
|
} |
|
if clientMap[records[i].Source].isOk { |
|
wg.Add(1) |
|
go func(index int) { |
|
item.Size, _ = clientMap[records[index].Source].client.Size(path.Join(clientMap[records[index].Source].backupPath, itemPath)) |
|
datas = append(datas, item) |
|
wg.Done() |
|
}(i) |
|
} else { |
|
datas = append(datas, item) |
|
} |
|
} |
|
wg.Wait() |
|
return datas, nil |
|
} |
|
|
|
func loadLocalDir() (string, error) { |
|
backup, err := backupRepo.Get(commonRepo.WithByType("LOCAL")) |
|
if err != nil { |
|
return "", err |
|
} |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil { |
|
return "", err |
|
} |
|
if _, ok := varMap["dir"]; !ok { |
|
return "", errors.New("load local backup dir failed") |
|
} |
|
baseDir, ok := varMap["dir"].(string) |
|
if ok { |
|
if _, err := os.Stat(baseDir); err != nil && os.IsNotExist(err) { |
|
if err = os.MkdirAll(baseDir, os.ModePerm); err != nil { |
|
return "", fmt.Errorf("mkdir %s failed, err: %v", baseDir, err) |
|
} |
|
} |
|
return baseDir, nil |
|
} |
|
return "", fmt.Errorf("error type dir: %T", varMap["dir"]) |
|
} |
|
|
|
func copyDir(src, dst string) error { |
|
srcInfo, err := os.Stat(src) |
|
if err != nil { |
|
return err |
|
} |
|
if err = os.MkdirAll(dst, srcInfo.Mode()); err != nil { |
|
return err |
|
} |
|
files, err := os.ReadDir(src) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
fileOP := fileUtils.NewFileOp() |
|
for _, file := range files { |
|
srcPath := fmt.Sprintf("%s/%s", src, file.Name()) |
|
dstPath := fmt.Sprintf("%s/%s", dst, file.Name()) |
|
if file.IsDir() { |
|
if err = copyDir(srcPath, dstPath); err != nil { |
|
global.LOG.Errorf("copy dir %s to %s failed, err: %v", srcPath, dstPath, err) |
|
} |
|
} else { |
|
if err := fileOP.CopyFile(srcPath, dst); err != nil { |
|
global.LOG.Errorf("copy file %s to %s failed, err: %v", srcPath, dstPath, err) |
|
} |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) { |
|
client, err := u.NewClient(backup) |
|
if err != nil { |
|
return false, err |
|
} |
|
fileItem := path.Join(global.CONF.System.TmpDir, "test", "1panel") |
|
if _, err := os.Stat(path.Dir(fileItem)); err != nil && os.IsNotExist(err) { |
|
if err = os.MkdirAll(path.Dir(fileItem), os.ModePerm); err != nil { |
|
return false, err |
|
} |
|
} |
|
file, err := os.OpenFile(fileItem, os.O_WRONLY|os.O_CREATE, 0666) |
|
if err != nil { |
|
return false, err |
|
} |
|
defer file.Close() |
|
write := bufio.NewWriter(file) |
|
_, _ = write.WriteString("1Panel 备份账号测试文件。\n") |
|
_, _ = write.WriteString("1Panel 備份賬號測試文件。\n") |
|
_, _ = write.WriteString("1Panel Backs up account test files.\n") |
|
_, _ = write.WriteString("1Panelアカウントのテストファイルをバックアップします。\n") |
|
write.Flush() |
|
|
|
targetPath := strings.TrimPrefix(path.Join(backup.BackupPath, "test/1panel"), "/") |
|
return client.Upload(fileItem, targetPath) |
|
} |
|
|
|
func StartRefreshOneDriveToken() { |
|
service := NewIBackupService() |
|
oneDriveCronID, err := global.Cron.AddJob("0 3 */31 * *", service) |
|
if err != nil { |
|
global.LOG.Errorf("can not add OneDrive corn job: %s", err.Error()) |
|
return |
|
} |
|
global.OneDriveCronID = oneDriveCronID |
|
} |
|
|
|
func (u *BackupService) Run() { |
|
var backupItem model.BackupAccount |
|
_ = global.DB.Where("`type` = ?", "OneDrive").First(&backupItem) |
|
if backupItem.ID == 0 { |
|
return |
|
} |
|
global.LOG.Info("start to refresh token of OneDrive ...") |
|
varMap := make(map[string]interface{}) |
|
if err := json.Unmarshal([]byte(backupItem.Vars), &varMap); err != nil { |
|
global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err) |
|
return |
|
} |
|
refreshToken, err := client.RefreshToken("refresh_token", "refreshToken", varMap) |
|
varMap["refresh_status"] = constant.StatusSuccess |
|
varMap["refresh_time"] = time.Now().Format(constant.DateTimeLayout) |
|
if err != nil { |
|
varMap["refresh_status"] = constant.StatusFailed |
|
varMap["refresh_msg"] = err.Error() |
|
global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err) |
|
return |
|
} |
|
varMap["refresh_token"] = refreshToken |
|
|
|
varsItem, _ := json.Marshal(varMap) |
|
_ = global.DB.Model(&model.BackupAccount{}). |
|
Where("id = ?", backupItem.ID). |
|
Updates(map[string]interface{}{ |
|
"vars": varsItem, |
|
}).Error |
|
global.LOG.Info("Successfully refreshed OneDrive token.") |
|
}
|
|
|