mirror of
https://gitee.com/fit2cloud-feizhiyun/1Panel.git
synced 2024-11-29 18:37:41 +08:00
parent
833efb0136
commit
732080b0bf
@ -31,7 +31,7 @@ type CommonBackup struct {
|
||||
DetailName string `json:"detailName"`
|
||||
}
|
||||
type CommonRecover struct {
|
||||
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive"`
|
||||
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"`
|
||||
Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website"`
|
||||
Name string `json:"name"`
|
||||
DetailName string `json:"detailName"`
|
||||
@ -55,7 +55,7 @@ type BackupRecords struct {
|
||||
}
|
||||
|
||||
type DownloadRecord struct {
|
||||
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive"`
|
||||
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"`
|
||||
FileDir string `json:"fileDir" validate:"required"`
|
||||
FileName string `json:"fileName" validate:"required"`
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ type SnapshotStatus struct {
|
||||
|
||||
type SnapshotCreate struct {
|
||||
ID uint `json:"id"`
|
||||
From string `json:"from" validate:"required,oneof=OSS S3 SFTP MINIO COS KODO OneDrive"`
|
||||
From string `json:"from" validate:"required,oneof=OSS S3 SFTP MINIO COS KODO OneDrive WebDAV"`
|
||||
Description string `json:"description" validate:"max=256"`
|
||||
}
|
||||
type SnapshotRecover struct {
|
||||
|
@ -69,6 +69,7 @@ func (u *BackupService) List() ([]dto.BackupInfo, error) {
|
||||
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
|
||||
}
|
||||
|
||||
@ -117,7 +118,7 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
|
||||
}
|
||||
varMap["bucket"] = backup.Bucket
|
||||
switch backup.Type {
|
||||
case constant.Sftp:
|
||||
case constant.Sftp, constant.WebDAV:
|
||||
varMap["username"] = backup.AccessKey
|
||||
varMap["password"] = backup.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
||||
@ -166,8 +167,7 @@ func (u *BackupService) Create(req dto.BackupOperate) error {
|
||||
}
|
||||
}
|
||||
if req.Type != "LOCAL" {
|
||||
isOk, err := u.checkBackupConn(&backup)
|
||||
if err != nil || !isOk {
|
||||
if _, err := u.checkBackupConn(&backup); err != nil {
|
||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||
}
|
||||
}
|
||||
@ -183,7 +183,7 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err
|
||||
return nil, err
|
||||
}
|
||||
switch backupDto.Type {
|
||||
case constant.Sftp:
|
||||
case constant.Sftp, constant.WebDAV:
|
||||
varMap["username"] = backupDto.AccessKey
|
||||
varMap["password"] = backupDto.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
||||
@ -328,7 +328,7 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl
|
||||
}
|
||||
varMap["bucket"] = backup.Bucket
|
||||
switch backup.Type {
|
||||
case constant.Sftp:
|
||||
case constant.Sftp, constant.WebDAV:
|
||||
varMap["username"] = backup.AccessKey
|
||||
varMap["password"] = backup.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
||||
|
@ -11,6 +11,7 @@ const (
|
||||
MinIo = "MINIO"
|
||||
Cos = "COS"
|
||||
Kodo = "KODO"
|
||||
WebDAV = "WebDAV"
|
||||
|
||||
OneDriveRedirectURI = "http://localhost/login/authorized"
|
||||
)
|
||||
|
@ -1,75 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/db"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/log"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/viper"
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
)
|
||||
|
||||
func TestCron(t *testing.T) {
|
||||
viper.Init()
|
||||
log.Init()
|
||||
db.Init()
|
||||
|
||||
var backup model.BackupAccount
|
||||
if err := global.DB.Where("id = ?", 2).First(&backup).Error; err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
varMap["type"] = backup.Type
|
||||
varMap["bucket"] = backup.Bucket
|
||||
switch backup.Type {
|
||||
case constant.Sftp:
|
||||
varMap["password"] = backup.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo:
|
||||
varMap["secretKey"] = backup.Credential
|
||||
}
|
||||
endpoint := varMap["endpoint"].(string)
|
||||
accessKey := varMap["accessKey"].(string)
|
||||
secretKey := varMap["secretKey"].(string)
|
||||
client, err := oss.New(endpoint, accessKey, secretKey)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
bucket, err := client.Bucket(backup.Bucket)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
lor, err := bucket.ListObjects(oss.Prefix("directory/directory-test1/"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("my objects:", getObjectsFormResponse(lor))
|
||||
|
||||
name := "directory/directory-test1/20220928104331.tar.gz"
|
||||
targetPath := constant.DataDir + "/download/directory/directory-test1/"
|
||||
if _, err := os.Stat(targetPath); err != nil && os.IsNotExist(err) {
|
||||
if err = os.MkdirAll(targetPath, os.ModePerm); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
if err := bucket.GetObjectToFile(name, targetPath+"20220928104231.tar.gz"); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getObjectsFormResponse(lor oss.ListObjectsResult) string {
|
||||
var output string
|
||||
for _, object := range lor.Objects {
|
||||
output += object.Key + " "
|
||||
}
|
||||
return output
|
||||
}
|
@ -15,7 +15,9 @@ import (
|
||||
)
|
||||
|
||||
type sftpClient struct {
|
||||
Vars map[string]interface{}
|
||||
Bucket string
|
||||
Vars map[string]interface{}
|
||||
client *sftp.Client
|
||||
}
|
||||
|
||||
func NewSftpClient(vars map[string]interface{}) (*sftpClient, error) {
|
||||
@ -31,46 +33,45 @@ func NewSftpClient(vars map[string]interface{}) (*sftpClient, error) {
|
||||
if _, ok := vars["username"]; !ok {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
return &sftpClient{
|
||||
Vars: vars,
|
||||
}, nil
|
||||
var bucket string
|
||||
if _, ok := vars["bucket"]; ok {
|
||||
bucket = vars["bucket"].(string)
|
||||
} else {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sftpC, err := connect(vars["username"].(string), vars["password"].(string), vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sftpClient{Bucket: bucket, client: sftpC, Vars: vars}, nil
|
||||
}
|
||||
|
||||
func (s sftpClient) Upload(src, target string) (bool, error) {
|
||||
bucket, err := s.getBucket()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(s.Vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sftpC, err := connect(s.Vars["username"].(string), s.Vars["password"].(string), s.Vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer sftpC.Close()
|
||||
defer s.client.Close()
|
||||
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
targetFilePath := bucket + "/" + target
|
||||
remotePath, _ := path.Split(targetFilePath)
|
||||
_, err = sftpC.Stat(remotePath)
|
||||
if err != nil {
|
||||
targetFilePath := s.Bucket + "/" + target
|
||||
targetDir, _ := path.Split(targetFilePath)
|
||||
if _, err = s.client.Stat(targetDir); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = sftpC.MkdirAll(remotePath)
|
||||
if err != nil {
|
||||
if err = s.client.MkdirAll(targetDir); err != nil {
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
dstFile, err := sftpC.Create(targetFilePath)
|
||||
dstFile, err := s.client.Create(targetFilePath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -96,20 +97,8 @@ func (s sftpClient) ListBuckets() ([]interface{}, error) {
|
||||
}
|
||||
|
||||
func (s sftpClient) Download(src, target string) (bool, error) {
|
||||
bucket, err := s.getBucket()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(s.Vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sftpC, err := connect(s.Vars["username"].(string), s.Vars["password"].(string), s.Vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer sftpC.Close()
|
||||
srcFile, err := sftpC.Open(bucket + "/" + src)
|
||||
defer s.client.Close()
|
||||
srcFile, err := s.client.Open(s.Bucket + "/" + src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -128,20 +117,8 @@ func (s sftpClient) Download(src, target string) (bool, error) {
|
||||
}
|
||||
|
||||
func (s sftpClient) Exist(path string) (bool, error) {
|
||||
bucket, err := s.getBucket()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(s.Vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sftpC, err := connect(s.Vars["username"].(string), s.Vars["password"].(string), s.Vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer sftpC.Close()
|
||||
srcFile, err := sftpC.Open(bucket + "/" + path)
|
||||
defer s.client.Close()
|
||||
srcFile, err := s.client.Open(s.Bucket + "/" + path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
@ -154,33 +131,15 @@ func (s sftpClient) Exist(path string) (bool, error) {
|
||||
}
|
||||
|
||||
func (s sftpClient) Delete(filePath string) (bool, error) {
|
||||
bucket, err := s.getBucket()
|
||||
if err != nil {
|
||||
defer s.client.Close()
|
||||
targetFilePath := s.Bucket + "/" + filePath
|
||||
if err := s.client.Remove(targetFilePath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(s.Vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sftpC, err := connect(s.Vars["username"].(string), s.Vars["password"].(string), s.Vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer sftpC.Close()
|
||||
targetFilePath := bucket + "/" + filePath
|
||||
err = sftpC.Remove(targetFilePath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func connect(user, password, host string, port int) (*sftp.Client, error) {
|
||||
|
||||
var (
|
||||
auth []ssh.AuthMethod
|
||||
addr string
|
||||
@ -210,29 +169,9 @@ func connect(user, password, host string, port int) (*sftp.Client, error) {
|
||||
return sftpClient, nil
|
||||
}
|
||||
|
||||
func (s sftpClient) getBucket() (string, error) {
|
||||
if _, ok := s.Vars["bucket"]; ok {
|
||||
return s.Vars["bucket"].(string), nil
|
||||
} else {
|
||||
return "", constant.ErrInvalidParams
|
||||
}
|
||||
}
|
||||
|
||||
func (s sftpClient) ListObjects(prefix string) ([]string, error) {
|
||||
bucket, err := s.getBucket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
port, err := strconv.Atoi(strconv.FormatFloat(s.Vars["port"].(float64), 'G', -1, 64))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sftpC, err := connect(s.Vars["username"].(string), s.Vars["password"].(string), s.Vars["address"].(string), port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sftpC.Close()
|
||||
files, err := sftpC.ReadDir(bucket + "/" + prefix)
|
||||
defer s.client.Close()
|
||||
files, err := s.client.ReadDir(s.Bucket + "/" + prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/db"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/log"
|
||||
"github.com/1Panel-dev/1Panel/backend/init/viper"
|
||||
)
|
||||
|
||||
func TestCronS(t *testing.T) {
|
||||
viper.Init()
|
||||
log.Init()
|
||||
db.Init()
|
||||
|
||||
var backup model.BackupAccount
|
||||
if err := global.DB.Where("id = ?", 5).First(&backup).Error; err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
varMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
varMap["type"] = backup.Type
|
||||
varMap["bucket"] = backup.Bucket
|
||||
switch backup.Type {
|
||||
case constant.Sftp:
|
||||
varMap["password"] = backup.Credential
|
||||
case constant.OSS, constant.S3, constant.MinIo:
|
||||
varMap["secretKey"] = backup.Credential
|
||||
}
|
||||
client, err := NewS3Client(varMap)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
_, _ = client.ListObjects("directory/directory-test-s3")
|
||||
}
|
135
backend/utils/cloud_storage/client/webdav.go
Normal file
135
backend/utils/cloud_storage/client/webdav.go
Normal file
@ -0,0 +1,135 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/studio-b12/gowebdav"
|
||||
)
|
||||
|
||||
type webDAVClient struct {
|
||||
Bucket string
|
||||
client *gowebdav.Client
|
||||
Vars map[string]interface{}
|
||||
}
|
||||
|
||||
func NewWebDAVClient(vars map[string]interface{}) (*webDAVClient, error) {
|
||||
var (
|
||||
address string
|
||||
username string
|
||||
password string
|
||||
bucket string
|
||||
)
|
||||
if _, ok := vars["address"]; ok {
|
||||
address = vars["address"].(string)
|
||||
} else {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
if _, ok := vars["port"].(float64); !ok {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
if _, ok := vars["username"]; ok {
|
||||
username = vars["username"].(string)
|
||||
} else {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
if _, ok := vars["password"]; ok {
|
||||
password = vars["password"].(string)
|
||||
} else {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
if _, ok := vars["bucket"]; ok {
|
||||
bucket = vars["bucket"].(string)
|
||||
} else {
|
||||
return nil, constant.ErrInvalidParams
|
||||
}
|
||||
|
||||
client := gowebdav.NewClient(fmt.Sprintf("%s:%v", address, vars["port"]), username, password)
|
||||
if err := client.Connect(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &webDAVClient{Vars: vars, Bucket: bucket, client: client}, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) Upload(src, target string) (bool, error) {
|
||||
targetFilePath := s.Bucket + "/" + target
|
||||
fileInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// 50M
|
||||
if fileInfo.Size() > 52428800 {
|
||||
bytes, _ := os.ReadFile(src)
|
||||
if err := s.client.Write(targetFilePath, bytes, 0644); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
file, _ := os.Open(src)
|
||||
defer file.Close()
|
||||
|
||||
if err := s.client.WriteStream(targetFilePath, file, 0644); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) ListBuckets() ([]interface{}, error) {
|
||||
var result []interface{}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) Download(src, target string) (bool, error) {
|
||||
srcPath := s.Bucket + "/" + src
|
||||
info, err := s.client.Stat(srcPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
file, err := os.Create(target)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer file.Close()
|
||||
// 50M
|
||||
if info.Size() > 52428800 {
|
||||
reader, _ := s.client.ReadStream(srcPath)
|
||||
if _, err := io.Copy(file, reader); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
bytes, _ := s.client.Read(srcPath)
|
||||
if err := os.WriteFile(target, bytes, 0644); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func (s webDAVClient) Exist(path string) (bool, error) {
|
||||
if _, err := s.client.Stat(s.Bucket + "/" + path); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) Delete(filePath string) (bool, error) {
|
||||
if err := s.client.Remove(s.Bucket + "/" + filePath); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s webDAVClient) ListObjects(prefix string) ([]string, error) {
|
||||
files, err := s.client.ReadDir(s.Bucket + "/" + prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result []string
|
||||
for _, file := range files {
|
||||
result = append(result, file.Name())
|
||||
}
|
||||
return result, nil
|
||||
}
|
@ -22,6 +22,8 @@ func NewCloudStorageClient(backupType string, vars map[string]interface{}) (Clou
|
||||
return client.NewOssClient(vars)
|
||||
case constant.Sftp:
|
||||
return client.NewSftpClient(vars)
|
||||
case constant.WebDAV:
|
||||
return client.NewWebDAVClient(vars)
|
||||
case constant.MinIo:
|
||||
return client.NewMinIoClient(vars)
|
||||
case constant.Cos:
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Package docs GENERATED BY SWAG; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag
|
||||
// Code generated by swaggo/swag. DO NOT EDIT.
|
||||
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
@ -13769,7 +13769,8 @@ const docTemplate = `{
|
||||
"LOCAL",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
@ -14586,6 +14587,12 @@ const docTemplate = `{
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14606,6 +14613,15 @@ const docTemplate = `{
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14640,6 +14656,12 @@ const docTemplate = `{
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14662,6 +14684,15 @@ const docTemplate = `{
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14735,6 +14766,12 @@ const docTemplate = `{
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14747,6 +14784,15 @@ const docTemplate = `{
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14883,7 +14929,8 @@ const docTemplate = `{
|
||||
"LOCAL",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -16891,7 +16938,8 @@ const docTemplate = `{
|
||||
"MINIO",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
|
@ -13762,7 +13762,8 @@
|
||||
"LOCAL",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
@ -14579,6 +14580,12 @@
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14599,6 +14606,15 @@
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14633,6 +14649,12 @@
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14655,6 +14677,15 @@
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14728,6 +14759,12 @@
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14740,6 +14777,15 @@
|
||||
"port": {
|
||||
"type": "integer"
|
||||
},
|
||||
"rootCert": {
|
||||
"type": "string"
|
||||
},
|
||||
"skipVerify": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -14876,7 +14922,8 @@
|
||||
"LOCAL",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -16884,7 +16931,8 @@
|
||||
"MINIO",
|
||||
"COS",
|
||||
"KODO",
|
||||
"OneDrive"
|
||||
"OneDrive",
|
||||
"WebDAV"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
|
@ -273,6 +273,7 @@ definitions:
|
||||
- COS
|
||||
- KODO
|
||||
- OneDrive
|
||||
- WebDAV
|
||||
type: string
|
||||
type:
|
||||
enum:
|
||||
@ -818,6 +819,10 @@ definitions:
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
clientCert:
|
||||
type: string
|
||||
clientKey:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
from:
|
||||
@ -832,6 +837,12 @@ definitions:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
rootCert:
|
||||
type: string
|
||||
skipVerify:
|
||||
type: boolean
|
||||
ssl:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
username:
|
||||
@ -861,6 +872,10 @@ definitions:
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
clientCert:
|
||||
type: string
|
||||
clientKey:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
description:
|
||||
@ -876,6 +891,12 @@ definitions:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
rootCert:
|
||||
type: string
|
||||
skipVerify:
|
||||
type: boolean
|
||||
ssl:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
username:
|
||||
@ -920,6 +941,10 @@ definitions:
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
clientCert:
|
||||
type: string
|
||||
clientKey:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
@ -928,6 +953,12 @@ definitions:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
rootCert:
|
||||
type: string
|
||||
skipVerify:
|
||||
type: boolean
|
||||
ssl:
|
||||
type: boolean
|
||||
type:
|
||||
type: string
|
||||
username:
|
||||
@ -1023,6 +1054,7 @@ definitions:
|
||||
- COS
|
||||
- KODO
|
||||
- OneDrive
|
||||
- WebDAV
|
||||
type: string
|
||||
required:
|
||||
- fileDir
|
||||
@ -2380,6 +2412,7 @@ definitions:
|
||||
- COS
|
||||
- KODO
|
||||
- OneDrive
|
||||
- WebDAV
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
|
@ -1,9 +1,9 @@
|
||||
@font-face {
|
||||
font-family: "panel"; /* Project id 3575356 */
|
||||
src: url('iconfont.woff2?t=1695287081776') format('woff2'),
|
||||
url('iconfont.woff?t=1695287081776') format('woff'),
|
||||
url('iconfont.ttf?t=1695287081776') format('truetype'),
|
||||
url('iconfont.svg?t=1695287081776#panel') format('svg');
|
||||
src: url('iconfont.woff2?t=1701341406915') format('woff2'),
|
||||
url('iconfont.woff?t=1701341406915') format('woff'),
|
||||
url('iconfont.ttf?t=1701341406915') format('truetype'),
|
||||
url('iconfont.svg?t=1701341406915#panel') format('svg');
|
||||
}
|
||||
|
||||
.panel {
|
||||
@ -14,6 +14,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.p-webdav:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
.p-xiangqing:before {
|
||||
content: "\e677";
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -5,6 +5,13 @@
|
||||
"css_prefix_text": "p-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "23044673",
|
||||
"name": "webdav",
|
||||
"font_class": "webdav",
|
||||
"unicode": "e622",
|
||||
"unicode_decimal": 58914
|
||||
},
|
||||
{
|
||||
"icon_id": "10293150",
|
||||
"name": "详情",
|
||||
|
@ -14,6 +14,8 @@
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="webdav" unicode="" d="M512 846.451613c255.405419 0 462.451613-207.046194 462.451613-462.451613S767.405419-78.45161299999995 512-78.45161299999995 49.548387 128.59458099999995 49.548387 384 256.594581 846.451613 512 846.451613z m0-66.064516C293.07871 780.387097 115.612903 602.92129 115.612903 384s177.465806-396.387097 396.387097-396.387097 396.387097 177.465806 396.387097 396.387097S730.92129 780.387097 512 780.387097zM332.122839 565.677419a33.032258 33.032258 0 0 0 32.090838-25.236645l54.618839-224.916645 57.575226 225.296516A33.032258 33.032258 0 0 0 508.416 565.677419h17.061161a33.032258 33.032258 0 0 0 32.008258-24.856774l57.575226-225.296516 54.618839 224.916645A33.032258 33.032258 0 0 0 701.786839 565.677419h12.684387a29.217032 29.217032 0 0 0 28.110451-37.194322l-85.80129-302.146065A33.032258 33.032258 0 0 0 625.003355 202.322581h-19.059613a33.032258 33.032258 0 0 0-32.008258 24.87329L517.169548 450.064516 459.974194 227.14632300000005A33.032258 33.032258 0 0 0 427.982452 202.322581h-19.555097a33.032258 33.032258 0 0 0-31.777032 24.047484l-85.371871 302.113032A29.233548 29.233548 0 0 0 319.438452 565.677419h12.684387z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="xiangqing" unicode="" d="M512 654.27010918m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0ZM512 384m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0ZM512 113.72989082000004m-77.34417915 0a77.34417915 77.34417915 0 1 1 154.6883583 0 77.34417915 77.34417915 0 1 1-154.6883583 0Z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="onedrive" unicode="" d="M597.333333 320s188.885333 129.152 192.96 128.874667A280.021333 280.021333 0 0 1 285.141333 533.333333h2.858667zM405.674667 499.968A222.869333 222.869333 0 0 1 288 533.333333h-2.858667a224 224 0 0 1-180.885333-352L405.333333 213.333333l188.437334 173.973334zM790.293333 448.874667a180.373333 180.373333 0 0 1-12.288 0.448 181.461333 181.461333 0 0 1-72.149333-14.933334l-112.085333-47.146666L725.333333 234.666667l212.906667-53.696a182.016 182.016 0 0 1-147.946667 267.904zM779.285333 276.181333l-46.464 27.733334-106.538666 63.808-32.512 19.477333-85.738667-36.096-164.266667-69.077333-73.642666-30.933334-165.866667-69.76A223.658667 223.658667 0 0 1 288 85.333333h490.005333a181.994667 181.994667 0 0 1 160.234667 95.637334z" horiz-adv-x="1024" />
|
||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 67 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1204,6 +1204,7 @@ const message = {
|
||||
S3: 'Amazon S3',
|
||||
MINIO: 'MINIO',
|
||||
SFTP: 'SFTP',
|
||||
WebDAV: 'WebDAV',
|
||||
OneDrive: 'Microsoft OneDrive',
|
||||
backupDir: 'Backup dir',
|
||||
codeWarning: 'The current authorization code format is incorrect, please confirm again!',
|
||||
|
@ -1133,6 +1133,7 @@ const message = {
|
||||
S3: '亞馬遜 S3 雲存儲',
|
||||
MINIO: 'MINIO',
|
||||
SFTP: 'SFTP',
|
||||
WebDAV: 'WebDAV',
|
||||
OneDrive: '微軟 OneDrive',
|
||||
codeWarning: '當前授權碼格式錯誤,請重新確認!',
|
||||
backupDir: '備份路徑',
|
||||
|
@ -1134,6 +1134,7 @@ const message = {
|
||||
S3: '亚马逊 S3 云存储',
|
||||
MINIO: 'MINIO',
|
||||
SFTP: 'SFTP',
|
||||
WebDAV: 'WebDAV',
|
||||
OneDrive: '微软 OneDrive',
|
||||
codeWarning: '当前授权码格式错误,请重新确认!',
|
||||
backupDir: '备份路径',
|
||||
|
@ -365,6 +365,51 @@
|
||||
</el-button>
|
||||
</el-alert>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
<div>
|
||||
<svg-icon class="card-logo" iconName="p-webdav"></svg-icon>
|
||||
<span class="card-title"> WebDAV</span>
|
||||
<div style="float: right">
|
||||
<el-button
|
||||
round
|
||||
plain
|
||||
:disabled="webDAVData.id === 0"
|
||||
@click="onOpenDialog('edit', 'WebDAV', webDAVData)"
|
||||
>
|
||||
{{ $t('commons.button.edit') }}
|
||||
</el-button>
|
||||
<el-button round :disabled="webDAVData.id === 0" @click="onDelete(webDAVData)">
|
||||
{{ $t('commons.button.delete') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-divider class="divider" />
|
||||
<div v-if="webDAVData.id !== 0" style="margin-left: 20px">
|
||||
<el-form-item :label="$t('setting.address')">
|
||||
{{ webDAVData.varsJson['address'] }}
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.port')">
|
||||
{{ webDAVData.varsJson['port'] }}
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.path')">
|
||||
{{ webDAVData.bucket }}
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.createdAt')">
|
||||
{{ dateFormat(0, 0, webDAVData.createdAt) }}
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-alert v-else center class="alert" style="height: 257px" :closable="false">
|
||||
<el-button
|
||||
size="large"
|
||||
round
|
||||
plain
|
||||
type="primary"
|
||||
@click="onOpenDialog('create', 'WebDAV')"
|
||||
>
|
||||
{{ $t('setting.createBackupAccount', ['WebDAV']) }}
|
||||
</el-button>
|
||||
</el-alert>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</LayoutContent>
|
||||
@ -442,6 +487,20 @@ const sftpData = ref<Backup.BackupInfo>({
|
||||
},
|
||||
createdAt: new Date(),
|
||||
});
|
||||
const webDAVData = ref<Backup.BackupInfo>({
|
||||
id: 0,
|
||||
type: 'WebDAV',
|
||||
accessKey: '',
|
||||
bucket: '',
|
||||
credential: '',
|
||||
backupPath: '',
|
||||
vars: '',
|
||||
varsJson: {
|
||||
address: '',
|
||||
port: 10080,
|
||||
},
|
||||
createdAt: new Date(),
|
||||
});
|
||||
const oneDriveData = ref<Backup.BackupInfo>({
|
||||
id: 0,
|
||||
type: 'OneDrive',
|
||||
@ -530,6 +589,9 @@ const search = async () => {
|
||||
case 'OneDrive':
|
||||
oneDriveData.value = bac;
|
||||
break;
|
||||
case 'WebDAV':
|
||||
webDAVData.value = bac;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -195,10 +195,24 @@
|
||||
:title="$t('setting.archiveHelper')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-if="dialogData.rowData!.type === 'SFTP'">
|
||||
<el-form-item :label="$t('setting.address')" prop="varsJson.address" :rules="Rules.host">
|
||||
<div v-if="isSftpOrWebDAV(dialogData.rowData!.type)">
|
||||
<el-form-item
|
||||
v-if="dialogData.rowData!.type === 'SFTP'"
|
||||
:label="$t('setting.address')"
|
||||
prop="varsJson.address"
|
||||
:rules="Rules.host"
|
||||
>
|
||||
<el-input v-model.trim="dialogData.rowData!.varsJson['address']" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="dialogData.rowData!.type === 'WebDAV'"
|
||||
:label="$t('setting.address')"
|
||||
prop="varsJson.address"
|
||||
:rules="Rules.requiredInput"
|
||||
>
|
||||
<el-input v-model.trim="dialogData.rowData!.varsJson['address']" />
|
||||
<span class="input-help">https://172.16.10.111</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.port')" prop="varsJson.port" :rules="[Rules.port]">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
@ -230,7 +244,7 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item
|
||||
v-if="dialogData.rowData!.type !== 'LOCAL' && dialogData.rowData!.type !== 'SFTP'"
|
||||
v-if="dialogData.rowData!.type !== 'LOCAL' && !isSftpOrWebDAV(dialogData.rowData!.type)"
|
||||
:label="$t('setting.backupDir')"
|
||||
prop="backupPath"
|
||||
>
|
||||
@ -347,6 +361,10 @@ function hasEndpoint(val: string) {
|
||||
return val === 'OSS' || val === 'S3';
|
||||
}
|
||||
|
||||
function isSftpOrWebDAV(val: string) {
|
||||
return val === 'SFTP' || val === 'WebDAV';
|
||||
}
|
||||
|
||||
const toDoc = () => {
|
||||
window.open('https://1panel.cn/docs/user_manual/settings/', '_blank', 'noopener,noreferrer');
|
||||
};
|
||||
|
1
go.mod
1
go.mod
@ -44,6 +44,7 @@ require (
|
||||
github.com/spf13/afero v1.9.2
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/viper v1.14.0
|
||||
github.com/studio-b12/gowebdav v0.9.0
|
||||
github.com/subosito/gotenv v1.4.1
|
||||
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a
|
||||
github.com/swaggo/gin-swagger v1.5.3
|
||||
|
2
go.sum
2
go.sum
@ -753,6 +753,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/studio-b12/gowebdav v0.9.0 h1:1j1sc9gQnNxbXXM4M/CebPOX4aXYtr7MojAVcN4dHjU=
|
||||
github.com/studio-b12/gowebdav v0.9.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY=
|
||||
|
Loading…
Reference in New Issue
Block a user