mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-27 18:44:13 +08:00
feat: delete the test upload file of the backup account (#7758)
This commit is contained in:
parent
680e237ef3
commit
e66eb00bd0
@ -113,17 +113,20 @@ type CronjobInfo struct {
|
||||
ContainerName string `json:"containerName"`
|
||||
User string `json:"user"`
|
||||
|
||||
AppID string `json:"appID"`
|
||||
Website string `json:"website"`
|
||||
ExclusionRules string `json:"exclusionRules"`
|
||||
DBType string `json:"dbType"`
|
||||
DBName string `json:"dbName"`
|
||||
URL string `json:"url"`
|
||||
IsDir bool `json:"isDir"`
|
||||
SourceDir string `json:"sourceDir"`
|
||||
SourceAccounts []string `json:"sourceAccounts"`
|
||||
DownloadAccount string `json:"downloadAccount"`
|
||||
RetainCopies int `json:"retainCopies"`
|
||||
AppID string `json:"appID"`
|
||||
Website string `json:"website"`
|
||||
ExclusionRules string `json:"exclusionRules"`
|
||||
DBType string `json:"dbType"`
|
||||
DBName string `json:"dbName"`
|
||||
URL string `json:"url"`
|
||||
IsDir bool `json:"isDir"`
|
||||
SourceDir string `json:"sourceDir"`
|
||||
RetainCopies int `json:"retainCopies"`
|
||||
|
||||
SourceAccounts []string `json:"sourceAccounts"`
|
||||
DownloadAccount string `json:"downloadAccount"`
|
||||
SourceAccountIDs string `json:"sourceAccountIDs"`
|
||||
DownloadAccountID uint `json:"downloadAccountID"`
|
||||
|
||||
LastRecordStatus string `json:"lastRecordStatus"`
|
||||
LastRecordTime string `json:"lastRecordTime"`
|
||||
|
@ -314,7 +314,7 @@ func (u *BackupService) RefreshToken(req dto.OperateByID) error {
|
||||
}
|
||||
|
||||
func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, error) {
|
||||
client, err := newClient(backup)
|
||||
client, err := newClient(backup, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -340,7 +340,12 @@ func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, erro
|
||||
if backup.Type != constant.Sftp && backup.Type != constant.Local && targetPath != "/" {
|
||||
targetPath = strings.TrimPrefix(targetPath, "/")
|
||||
}
|
||||
return client.Upload(fileItem, targetPath)
|
||||
|
||||
if _, err := client.Upload(fileItem, targetPath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, _ = client.Delete(path.Join(backup.BackupPath, "test"))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (u *BackupService) Sync(req dto.SyncFromMaster) error {
|
||||
@ -408,7 +413,7 @@ func (u *BackupService) CheckUsed(id uint) error {
|
||||
|
||||
func NewBackupClientWithID(id uint) (*model.BackupAccount, cloud_storage.CloudStorageClient, error) {
|
||||
account, _ := backupRepo.Get(repo.WithByID(id))
|
||||
backClient, err := newClient(&account)
|
||||
backClient, err := newClient(&account, true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -433,7 +438,7 @@ func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
|
||||
accounts, _ = backupRepo.List(repo.WithByIDs(idItems))
|
||||
clientMap := make(map[string]backupClientHelper)
|
||||
for _, item := range accounts {
|
||||
backClient, err := newClient(&item)
|
||||
backClient, err := newClient(&item, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -448,7 +453,7 @@ func NewBackupClientMap(ids []string) (map[string]backupClientHelper, error) {
|
||||
return clientMap, nil
|
||||
}
|
||||
|
||||
func newClient(account *model.BackupAccount) (cloud_storage.CloudStorageClient, error) {
|
||||
func newClient(account *model.BackupAccount, isEncrypt bool) (cloud_storage.CloudStorageClient, error) {
|
||||
varMap := make(map[string]interface{})
|
||||
if len(account.Vars) != 0 {
|
||||
if err := json.Unmarshal([]byte(account.Vars), &varMap); err != nil {
|
||||
@ -457,8 +462,10 @@ func newClient(account *model.BackupAccount) (cloud_storage.CloudStorageClient,
|
||||
}
|
||||
varMap["bucket"] = account.Bucket
|
||||
varMap["backupPath"] = account.BackupPath
|
||||
account.AccessKey, _ = encrypt.StringDecrypt(account.AccessKey)
|
||||
account.Credential, _ = encrypt.StringDecrypt(account.Credential)
|
||||
if isEncrypt {
|
||||
account.AccessKey, _ = encrypt.StringDecrypt(account.AccessKey)
|
||||
account.Credential, _ = encrypt.StringDecrypt(account.Credential)
|
||||
}
|
||||
switch account.Type {
|
||||
case constant.Sftp, constant.WebDAV:
|
||||
varMap["username"] = account.AccessKey
|
||||
|
@ -357,7 +357,11 @@ func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, erro
|
||||
if backup.Type != constant.Sftp && backup.Type != constant.Local && targetPath != "/" {
|
||||
targetPath = strings.TrimPrefix(targetPath, "/")
|
||||
}
|
||||
return client.Upload(fileItem, targetPath)
|
||||
if _, err := client.Upload(fileItem, targetPath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, _ = client.Delete(path.Join(backup.BackupPath, "test"))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func syncAccountToAgent(backup model.BackupAccount, operation string) {
|
||||
|
@ -207,14 +207,14 @@ func (t *Task) DeleteLogFile() {
|
||||
|
||||
func (t *Task) LogWithStatus(msg string, err error) {
|
||||
if err != nil {
|
||||
t.Logger.Printf(i18n.GetWithNameAndErr("FailedStatus", msg, err))
|
||||
t.Logger.Print(i18n.GetWithNameAndErr("FailedStatus", msg, err))
|
||||
} else {
|
||||
t.Logger.Printf(i18n.GetWithName("SuccessStatus", msg))
|
||||
t.Logger.Print(i18n.GetWithName("SuccessStatus", msg))
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Task) Log(msg string) {
|
||||
t.Logger.Printf(msg)
|
||||
t.Logger.Print(msg)
|
||||
}
|
||||
|
||||
func (t *Task) Logf(format string, v ...any) {
|
||||
@ -222,22 +222,22 @@ func (t *Task) Logf(format string, v ...any) {
|
||||
}
|
||||
|
||||
func (t *Task) LogFailed(msg string) {
|
||||
t.Logger.Printf(msg + i18n.GetMsgByKey("Failed"))
|
||||
t.Logger.Print(msg + i18n.GetMsgByKey("Failed"))
|
||||
}
|
||||
|
||||
func (t *Task) LogFailedWithErr(msg string, err error) {
|
||||
t.Logger.Printf(fmt.Sprintf("%s %s : %s", msg, i18n.GetMsgByKey("Failed"), err.Error()))
|
||||
t.Logger.Printf("%s %s : %s", msg, i18n.GetMsgByKey("Failed"), err.Error())
|
||||
}
|
||||
|
||||
func (t *Task) LogSuccess(msg string) {
|
||||
t.Logger.Printf(msg + i18n.GetMsgByKey("Success"))
|
||||
t.Logger.Print(msg + i18n.GetMsgByKey("Success"))
|
||||
}
|
||||
func (t *Task) LogSuccessF(format string, v ...any) {
|
||||
t.Logger.Printf(fmt.Sprintf(format, v...) + i18n.GetMsgByKey("Success"))
|
||||
t.Logger.Print(fmt.Sprintf(format, v...) + i18n.GetMsgByKey("Success"))
|
||||
}
|
||||
|
||||
func (t *Task) LogStart(msg string) {
|
||||
t.Logger.Printf(fmt.Sprintf("%s%s", i18n.GetMsgByKey("Start"), msg))
|
||||
t.Logger.Printf("%s%s", i18n.GetMsgByKey("Start"), msg)
|
||||
}
|
||||
|
||||
func (t *Task) LogWithOps(operate, msg string) {
|
||||
|
@ -2,6 +2,7 @@ package i18n
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
@ -64,9 +65,10 @@ func GetErrMsg(key string, maps map[string]interface{}) string {
|
||||
}
|
||||
|
||||
func GetMsgByKey(key string) string {
|
||||
content, _ := global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
content, err := global.I18n.Localize(&i18n.LocalizeConfig{
|
||||
MessageID: key,
|
||||
})
|
||||
fmt.Println(err)
|
||||
return content
|
||||
}
|
||||
|
||||
@ -132,6 +134,7 @@ func Init() {
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ru.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ms.yaml")
|
||||
_, _ = bundle.LoadMessageFileFS(fs, "lang/ko.yaml")
|
||||
global.I18n = i18n.NewLocalizer(bundle, "en")
|
||||
}
|
||||
|
||||
func UseI18nForCmd(lang string) {
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "Backup account connection test failed {{ .err}}"
|
||||
ErrBackupLocal: "Local backup account does not support this operation!"
|
||||
ErrBackupPublic: "Non-public backup account detected, please check and retry!"
|
||||
ErrOSSConn: "Cannot retrieve latest version, please check if the server can connect to external network."
|
||||
ErrEntrance: "Security entrance error, please check and retry!"
|
||||
|
||||
#license
|
||||
ErrLicense: "License format error, please check and retry!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "バックアップアカウントの接続テストに失敗し
|
||||
ErrBackupLocal: "ローカルサーバーのバックアップアカウントはこの操作をサポートしていません!"
|
||||
ErrBackupPublic: "バックアップアカウントが公開ではないことが検出されました、確認して再試行してください!"
|
||||
ErrOSSConn: "最新バージョンを取得できませんでした、サーバーが外部ネットワークに接続できるか確認してください。"
|
||||
ErrEntrance: "セキュアエントランス情報エラー、確認して再試行してください!"
|
||||
|
||||
#license
|
||||
ErrLicense: "ライセンスフォーマットエラー、確認して再試行してください!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "백업 계정 연결 테스트 실패 {{ .err}}"
|
||||
ErrBackupLocal: "로컬 서버 백업 계정은 현재 작업을 지원하지 않습니다!"
|
||||
ErrBackupPublic: "이 백업 계정이 공용이 아님을 감지했습니다. 다시 확인하고 시도해 주세요!"
|
||||
ErrOSSConn: "최신 버전을 가져올 수 없습니다. 서버가 외부 네트워크에 연결되어 있는지 확인하세요."
|
||||
ErrEntrance: "보안 입구 정보가 잘못되었습니다. 다시 확인하고 시도해 주세요!"
|
||||
|
||||
#license
|
||||
ErrLicense: "라이선스 형식이 잘못되었습니다. 다시 확인하고 시도해 주세요!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "Cubaan sambungan akaun sandaran gagal {{ .err}}"
|
||||
ErrBackupLocal: "Akaun sandaran pelayan tempatan tidak menyokong operasi ini!"
|
||||
ErrBackupPublic: "Akaun sandaran ini didapati bukan awam, sila semak dan cuba lagi!"
|
||||
ErrOSSConn: "Tidak dapat mendapatkan versi terkini, sila pastikan pelayan boleh disambung ke rangkaian luar."
|
||||
ErrEntrance: "Maklumat pintu masuk selamat salah, sila semak dan cuba lagi!"
|
||||
|
||||
#license
|
||||
ErrLicense: "Format lesen salah, sila semak dan cuba lagi!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "Falha na conexão de teste da conta de backup {{ .err}}"
|
||||
ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação!"
|
||||
ErrBackupPublic: "Detectamos que a conta de backup não é pública, verifique e tente novamente!"
|
||||
ErrOSSConn: "Não foi possível obter a versão mais recente, verifique se o servidor pode se conectar à rede externa."
|
||||
ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!"
|
||||
|
||||
#license
|
||||
ErrLicense: "Erro no formato da licença, verifique e tente novamente!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "Falha na conexão de teste da conta de backup {{ .err}}"
|
||||
ErrBackupLocal: "A conta de backup do servidor local não suporta essa operação!"
|
||||
ErrBackupPublic: "Detectamos que a conta de backup não é pública, verifique e tente novamente!"
|
||||
ErrOSSConn: "Não foi possível obter a versão mais recente, verifique se o servidor pode se conectar à rede externa."
|
||||
ErrEntrance: "Erro nas informações de entrada de segurança, verifique e tente novamente!"
|
||||
|
||||
#license
|
||||
ErrLicense: "Erro no formato da licença, verifique e tente novamente!"
|
||||
|
@ -28,7 +28,6 @@ ErrBackupCheck: "備份帳號測試連接失敗 {{ .err}}"
|
||||
ErrBackupLocal: "本地伺服器備份帳號暫不支持該操作!"
|
||||
ErrBackupPublic: "檢測到該備份帳號為非公用,請檢查後重試!"
|
||||
ErrOSSConn: "無法獲取最新版本,請確認伺服器是否能夠連接外部網絡。"
|
||||
ErrEntrance: "安全入口信息錯誤,請檢查後重試!"
|
||||
|
||||
#license
|
||||
ErrLicense: "許可證格式錯誤,請檢查後重試!"
|
||||
|
@ -19,7 +19,7 @@ ErrApiConfigKeyTimeInvalid: "API 接口时间戳错误: {{ .detail }}"
|
||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||
ErrCmdTimeout: "命令执行超时!"
|
||||
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
||||
ErrGroupIsDefault: '默认分组,无法删除'
|
||||
ErrGroupIsDefault: "默认分组,无法删除"
|
||||
ErrLocalDelete: "无法删除本地节点!"
|
||||
|
||||
#backup
|
||||
@ -28,7 +28,6 @@ ErrBackupCheck: "备份账号测试连接失败 {{ .err}}"
|
||||
ErrBackupLocal: "本地服务器备份账号暂不支持该操作!"
|
||||
ErrBackupPublic: "检测到该备份账号为非公用,请检查后重试!"
|
||||
ErrOSSConn: "无法获取最新版本,请确认服务器是否能够连接外部网络。"
|
||||
ErrEntrance: "安全入口信息错误,请检查后重试!"
|
||||
|
||||
#license
|
||||
ErrLicense: "许可证格式错误,请检查后重试!"
|
||||
|
@ -88,6 +88,69 @@ func (a aliClient) Upload(src, target string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (a aliClient) Delete(pathItem string) (bool, error) {
|
||||
pathItem = path.Join("root", pathItem)
|
||||
fileInfo, err := a.loadFileWithName(pathItem)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
client := resty.New()
|
||||
data := map[string]interface{}{
|
||||
"drive_id": a.driveID,
|
||||
"file_id": fileInfo.FileID,
|
||||
}
|
||||
url := "https://api.alipan.com/v2/file/delete"
|
||||
resp, err := client.R().
|
||||
SetHeader("Authorization", a.token).
|
||||
SetBody(data).
|
||||
Post(url)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if resp.StatusCode() != 204 {
|
||||
return false, fmt.Errorf("delete file %s failed, err: %v", pathItem, string(resp.Body()))
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (a aliClient) loadFileWithName(pathItem string) (fileInfo, error) {
|
||||
pathItems := strings.Split(pathItem, "/")
|
||||
var (
|
||||
fileInfos []fileInfo
|
||||
err error
|
||||
)
|
||||
parentID := "root"
|
||||
for i := 0; i < len(pathItems); i++ {
|
||||
if len(pathItems[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
fileInfos, err = a.loadFileWithParentID(parentID)
|
||||
if err != nil {
|
||||
return fileInfo{}, err
|
||||
}
|
||||
isEnd := false
|
||||
if i == len(pathItems)-2 {
|
||||
isEnd = true
|
||||
}
|
||||
exist := false
|
||||
for _, item := range fileInfos {
|
||||
if item.Name == pathItems[i+1] {
|
||||
if isEnd {
|
||||
return item, nil
|
||||
} else {
|
||||
parentID = item.FileID
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
return fileInfo{}, errors.New("no such file or dir")
|
||||
}
|
||||
|
||||
}
|
||||
return fileInfo{}, errors.New("no such file or dir")
|
||||
}
|
||||
|
||||
func (a aliClient) loadFileWithParentID(parentID string) ([]fileInfo, error) {
|
||||
client := resty.New()
|
||||
data := map[string]interface{}{
|
||||
|
@ -94,3 +94,10 @@ func (c cosClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c cosClient) Delete(path string) (bool, error) {
|
||||
if _, err := c.clientWithBucket.Object.Delete(context.Background(), path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -72,6 +72,23 @@ func (g *googleDriveClient) Upload(src, target string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (g *googleDriveClient) Delete(pathItem string) (bool, error) {
|
||||
pathItem = path.Join("root", pathItem)
|
||||
fileInfo, err := g.loadFileWithName(pathItem)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(fileInfo.ID) == 0 {
|
||||
return false, fmt.Errorf("no such file %s", pathItem)
|
||||
}
|
||||
res, err := g.googleRequest("https://www.googleapis.com/drive/v3/files/"+fileInfo.ID, http.MethodDelete, nil, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
fmt.Println(string(res))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type googleFileResp struct {
|
||||
Files []googleFile `json:"files"`
|
||||
}
|
||||
@ -147,6 +164,44 @@ func (g *googleDriveClient) mkdir(parentID, name string) (string, error) {
|
||||
return mkdirResp.ID, nil
|
||||
}
|
||||
|
||||
func (g *googleDriveClient) loadFileWithName(pathItem string) (googleFile, error) {
|
||||
pathItems := strings.Split(pathItem, "/")
|
||||
var (
|
||||
fileInfos []googleFile
|
||||
err error
|
||||
)
|
||||
parentID := "root"
|
||||
for i := 0; i < len(pathItems); i++ {
|
||||
if len(pathItems[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
fileInfos, err = g.loadFileWithParentID(parentID)
|
||||
if err != nil {
|
||||
return googleFile{}, err
|
||||
}
|
||||
isEnd := false
|
||||
if i == len(pathItems)-2 {
|
||||
isEnd = true
|
||||
}
|
||||
exist := false
|
||||
for _, item := range fileInfos {
|
||||
if item.Name == pathItems[i+1] {
|
||||
if isEnd {
|
||||
return item, nil
|
||||
} else {
|
||||
parentID = item.ID
|
||||
exist = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
return googleFile{}, errors.New("no such file or dir")
|
||||
}
|
||||
|
||||
}
|
||||
return googleFile{}, errors.New("no such file or dir")
|
||||
}
|
||||
|
||||
func (g *googleDriveClient) loadFileWithParentID(parentID string) ([]googleFile, error) {
|
||||
query := map[string]string{
|
||||
"fields": "files(id,name,mimeType,size)",
|
||||
|
@ -64,3 +64,10 @@ func (k kodoClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (k kodoClient) Delete(path string) (bool, error) {
|
||||
if err := k.client.Delete(k.bucket, path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -38,3 +38,10 @@ func (c localClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c localClient) Delete(file string) (bool, error) {
|
||||
if err := os.RemoveAll(file); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -76,3 +76,21 @@ func (m minIoClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m minIoClient) Delete(path string) (bool, error) {
|
||||
object, err := m.client.GetObject(context.Background(), m.bucket, path, minio.GetObjectOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
info, err := object.Stat()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err = m.client.RemoveObject(context.Background(), m.bucket, path, minio.RemoveObjectOptions{
|
||||
GovernanceBypass: true,
|
||||
VersionID: info.VersionID,
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -80,6 +80,19 @@ func (o oneDriveClient) Upload(src, target string) (bool, error) {
|
||||
return isOk, err
|
||||
}
|
||||
|
||||
func (o oneDriveClient) Delete(path string) (bool, error) {
|
||||
path = "/" + strings.TrimPrefix(path, "/")
|
||||
req, err := o.client.NewRequest("DELETE", fmt.Sprintf("me/drive/root:%s", path), nil)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("new request for delete file failed, err: %v \n", err)
|
||||
}
|
||||
if err := o.client.Do(context.Background(), req, false, nil); err != nil {
|
||||
return false, fmt.Errorf("do request for delete file failed, err: %v \n", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (o *oneDriveClient) loadIDByPath(path string) (string, error) {
|
||||
pathItem := "root:" + path
|
||||
if path == "/" {
|
||||
|
@ -53,3 +53,14 @@ func (o ossClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (o ossClient) Delete(path string) (bool, error) {
|
||||
bucket, err := o.client.Bucket(o.bucketStr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := bucket.DeleteObject(path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -81,3 +81,17 @@ func (s s3Client) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s s3Client) Delete(path string) (bool, error) {
|
||||
svc := s3.New(&s.Sess)
|
||||
if _, err := svc.DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(s.bucket), Key: aws.String(path)}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := svc.WaitUntilObjectNotExists(&s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path),
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -108,3 +108,21 @@ func (s sftpClient) ListBuckets() ([]interface{}, error) {
|
||||
var result []interface{}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s sftpClient) Delete(filePath string) (bool, error) {
|
||||
sshClient, err := ssh.Dial("tcp", s.connInfo, s.config)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
client, err := sftp.NewClient(sshClient)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer client.Close()
|
||||
defer sshClient.Close()
|
||||
|
||||
if err := client.Remove(filePath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -45,3 +45,12 @@ func (s upClient) Upload(src, target string) (bool, error) {
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s upClient) Delete(path string) (bool, error) {
|
||||
if err := s.client.Delete(&upyun.DeleteObjectConfig{
|
||||
Path: path,
|
||||
}); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -3,12 +3,13 @@ package client
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/constant"
|
||||
|
||||
"github.com/studio-b12/gowebdav"
|
||||
)
|
||||
|
||||
@ -61,3 +62,10 @@ func (s webDAVClient) ListBuckets() ([]interface{}, error) {
|
||||
var result []interface{}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) Delete(pathItem string) (bool, error) {
|
||||
if err := s.client.Remove(path.Join(s.Bucket, pathItem)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
type CloudStorageClient interface {
|
||||
ListBuckets() ([]interface{}, error)
|
||||
Upload(src, target string) (bool, error)
|
||||
Delete(path string) (bool, error)
|
||||
}
|
||||
|
||||
func NewCloudStorageClient(backupType string, vars map[string]interface{}) (CloudStorageClient, error) {
|
||||
|
@ -26,8 +26,6 @@
|
||||
"@codemirror/language": "^6.10.2",
|
||||
"@codemirror/legacy-modes": "^6.4.0",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@codemirror/lang-php": "^6.0.1",
|
||||
"@element-plus/icons-vue": "^1.1.4",
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@vue-office/docx": "^1.6.2",
|
||||
|
@ -31,6 +31,10 @@ export namespace Cronjob {
|
||||
|
||||
sourceAccounts: Array<string>;
|
||||
downloadAccount: string;
|
||||
sourceAccountIDs: string;
|
||||
downloadAccountID: number;
|
||||
sourceAccountItems: Array<number>;
|
||||
|
||||
retainCopies: number;
|
||||
status: string;
|
||||
secret: string;
|
||||
|
@ -92,7 +92,6 @@ const nodeChangeRef = ref<DropdownInstance>();
|
||||
const version = ref();
|
||||
|
||||
bus.on('refreshTask', () => {
|
||||
console.log('on bus message');
|
||||
checkTask();
|
||||
});
|
||||
|
||||
|
@ -409,11 +409,11 @@
|
||||
</div>
|
||||
|
||||
<div v-if="isBackup()">
|
||||
<el-form-item :label="$t('setting.backupAccount')" prop="sourceAccounts">
|
||||
<el-form-item :label="$t('setting.backupAccount')" prop="sourceAccountItems">
|
||||
<el-select
|
||||
multiple
|
||||
class="selectClass"
|
||||
v-model="dialogData.rowData!.sourceAccounts"
|
||||
v-model="dialogData.rowData!.sourceAccountItems"
|
||||
@change="changeAccount"
|
||||
>
|
||||
<div v-for="item in backupOptions" :key="item.id">
|
||||
@ -585,6 +585,16 @@ const acceptParams = (params: DialogProps): void => {
|
||||
if (dialogData.value.rowData?.specCustom && dialogData.value.rowData?.spec) {
|
||||
dialogData.value.rowData.specs = dialogData.value.rowData.spec.split(',');
|
||||
}
|
||||
if (dialogData.value.rowData.sourceAccountIDs) {
|
||||
let list = [];
|
||||
dialogData.value.rowData.sourceAccountItems = [];
|
||||
list = dialogData.value.rowData.sourceAccountIDs.split(',');
|
||||
for (const item of list) {
|
||||
if (item) {
|
||||
dialogData.value.rowData.sourceAccountItems.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
dialogData.value.rowData.specs = dialogData.value.rowData.specs || [];
|
||||
dialogData.value.rowData.files = [];
|
||||
if (!dialogData.value.rowData.isDir) {
|
||||
@ -787,7 +797,7 @@ const rules = reactive({
|
||||
url: [Rules.requiredInput],
|
||||
files: [{ validator: verifyFiles, trigger: 'blur', required: true }],
|
||||
sourceDir: [Rules.requiredInput],
|
||||
sourceAccounts: [Rules.requiredSelect],
|
||||
sourceAccountItems: [Rules.requiredSelect],
|
||||
downloadAccountID: [Rules.requiredSelect],
|
||||
retainCopies: [Rules.number],
|
||||
alertCount: [Rules.integerNumber, { validator: checkSendCount, trigger: 'blur' }],
|
||||
@ -917,8 +927,8 @@ const loadBackups = async () => {
|
||||
}
|
||||
backupOptions.value.push({ id: item.id, type: i18n.global.t('setting.' + item.type), name: item.name });
|
||||
}
|
||||
if (!dialogData.value.rowData!.sourceAccounts) {
|
||||
dialogData.value.rowData!.sourceAccounts = local === 0 ? [local] : [];
|
||||
if (!dialogData.value.rowData!.sourceAccountItems) {
|
||||
dialogData.value.rowData!.sourceAccountItems = local === 0 ? [local] : [];
|
||||
}
|
||||
changeAccount();
|
||||
};
|
||||
@ -928,7 +938,7 @@ const changeAccount = async () => {
|
||||
let isInAccounts = false;
|
||||
for (const item of backupOptions.value) {
|
||||
let exist = false;
|
||||
for (const ac of dialogData.value.rowData.sourceAccounts) {
|
||||
for (const ac of dialogData.value.rowData.sourceAccountItems) {
|
||||
if (item.id == ac) {
|
||||
exist = true;
|
||||
break;
|
||||
@ -1010,7 +1020,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
dialogData.value.rowData.sourceDir = files.join(',');
|
||||
}
|
||||
dialogData.value.rowData.sourceAccountIDs = dialogData.value.rowData.sourceAccounts.join(',');
|
||||
dialogData.value.rowData.sourceAccountIDs = dialogData.value.rowData.sourceAccountItems.join(',');
|
||||
dialogData.value.rowData.spec = specs.join(',');
|
||||
if (!formEl) return;
|
||||
formEl.validate(async (valid) => {
|
||||
@ -1055,8 +1065,30 @@ defineExpose({
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-input-group__append) {
|
||||
padding: 0 10px;
|
||||
.specClass {
|
||||
width: 17% !important;
|
||||
margin-left: 20px;
|
||||
.append {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.specClass {
|
||||
width: 100% !important;
|
||||
margin-top: 20px;
|
||||
margin-left: 0;
|
||||
.append {
|
||||
width: 43px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.specTypeClass {
|
||||
width: 22% !important;
|
||||
}
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.specTypeClass {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
.selectClass {
|
||||
width: 100%;
|
||||
|
Loading…
x
Reference in New Issue
Block a user