mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 备份账号增加 Onedrive (#1421)
This commit is contained in:
parent
ae38239b47
commit
3fa4a240f7
@ -8,6 +8,7 @@ type BackupOperate struct {
|
|||||||
Bucket string `json:"bucket"`
|
Bucket string `json:"bucket"`
|
||||||
AccessKey string `json:"accessKey"`
|
AccessKey string `json:"accessKey"`
|
||||||
Credential string `json:"credential"`
|
Credential string `json:"credential"`
|
||||||
|
BackupPath string `json:"backupPath"`
|
||||||
Vars string `json:"vars" validate:"required"`
|
Vars string `json:"vars" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ type BackupInfo struct {
|
|||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Bucket string `json:"bucket"`
|
Bucket string `json:"bucket"`
|
||||||
|
BackupPath string `json:"backupPath"`
|
||||||
Vars string `json:"vars"`
|
Vars string `json:"vars"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ type BackupAccount struct {
|
|||||||
Bucket string `gorm:"type:varchar(256)" json:"bucket"`
|
Bucket string `gorm:"type:varchar(256)" json:"bucket"`
|
||||||
AccessKey string `gorm:"type:varchar(256)" json:"accessKey"`
|
AccessKey string `gorm:"type:varchar(256)" json:"accessKey"`
|
||||||
Credential string `gorm:"type:varchar(256)" json:"credential"`
|
Credential string `gorm:"type:varchar(256)" json:"credential"`
|
||||||
|
BackupPath string `gorm:"type:varchar(256)" json:"backupPath"`
|
||||||
Vars string `gorm:"type:longText" json:"vars"`
|
Vars string `gorm:"type:longText" json:"vars"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
@ -62,6 +65,7 @@ func (u *BackupService) List() ([]dto.BackupInfo, error) {
|
|||||||
dtobas = append(dtobas, u.loadByType("MINIO", ops))
|
dtobas = append(dtobas, u.loadByType("MINIO", ops))
|
||||||
dtobas = append(dtobas, u.loadByType("COS", ops))
|
dtobas = append(dtobas, u.loadByType("COS", ops))
|
||||||
dtobas = append(dtobas, u.loadByType("KODO", ops))
|
dtobas = append(dtobas, u.loadByType("KODO", ops))
|
||||||
|
dtobas = append(dtobas, u.loadByType("OneDrive", ops))
|
||||||
return dtobas, err
|
return dtobas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +100,6 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
|
|||||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
varMap["type"] = backup.Type
|
|
||||||
varMap["bucket"] = backup.Bucket
|
varMap["bucket"] = backup.Bucket
|
||||||
switch backup.Type {
|
switch backup.Type {
|
||||||
case constant.Sftp:
|
case constant.Sftp:
|
||||||
@ -105,8 +108,10 @@ func (u *BackupService) DownloadRecord(info dto.DownloadRecord) (string, error)
|
|||||||
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
||||||
varMap["accessKey"] = backup.AccessKey
|
varMap["accessKey"] = backup.AccessKey
|
||||||
varMap["secretKey"] = backup.Credential
|
varMap["secretKey"] = backup.Credential
|
||||||
|
case constant.OneDrive:
|
||||||
|
varMap["accessToken"] = backup.Credential
|
||||||
}
|
}
|
||||||
backClient, err := cloud_storage.NewCloudStorageClient(varMap)
|
backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
|
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
|
||||||
}
|
}
|
||||||
@ -134,6 +139,12 @@ func (u *BackupService) Create(backupDto dto.BackupOperate) error {
|
|||||||
if err := copier.Copy(&backup, &backupDto); err != nil {
|
if err := copier.Copy(&backup, &backupDto); err != nil {
|
||||||
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
return errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if backupDto.Type == constant.OneDrive {
|
||||||
|
if err := u.loadAccessToken(&backup); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := backupRepo.Create(&backup); err != nil {
|
if err := backupRepo.Create(&backup); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -145,7 +156,6 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err
|
|||||||
if err := json.Unmarshal([]byte(backupDto.Vars), &varMap); err != nil {
|
if err := json.Unmarshal([]byte(backupDto.Vars), &varMap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
varMap["type"] = backupDto.Type
|
|
||||||
switch backupDto.Type {
|
switch backupDto.Type {
|
||||||
case constant.Sftp:
|
case constant.Sftp:
|
||||||
varMap["username"] = backupDto.AccessKey
|
varMap["username"] = backupDto.AccessKey
|
||||||
@ -154,7 +164,7 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err
|
|||||||
varMap["accessKey"] = backupDto.AccessKey
|
varMap["accessKey"] = backupDto.AccessKey
|
||||||
varMap["secretKey"] = backupDto.Credential
|
varMap["secretKey"] = backupDto.Credential
|
||||||
}
|
}
|
||||||
client, err := cloud_storage.NewCloudStorageClient(varMap)
|
client, err := cloud_storage.NewCloudStorageClient(backupDto.Type, varMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -215,6 +225,15 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
|||||||
upMap["bucket"] = req.Bucket
|
upMap["bucket"] = req.Bucket
|
||||||
upMap["credential"] = req.Credential
|
upMap["credential"] = req.Credential
|
||||||
upMap["vars"] = req.Vars
|
upMap["vars"] = req.Vars
|
||||||
|
backup.Vars = req.Vars
|
||||||
|
|
||||||
|
if req.Type == constant.OneDrive {
|
||||||
|
if err := u.loadAccessToken(&backup); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
upMap["credential"] = backup.Credential
|
||||||
|
upMap["vars"] = backup.Vars
|
||||||
|
}
|
||||||
if err := backupRepo.Update(req.ID, upMap); err != nil {
|
if err := backupRepo.Update(req.ID, upMap); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -251,7 +270,6 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl
|
|||||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
varMap["type"] = backup.Type
|
|
||||||
if backup.Type == "LOCAL" {
|
if backup.Type == "LOCAL" {
|
||||||
return nil, errors.New("not support")
|
return nil, errors.New("not support")
|
||||||
}
|
}
|
||||||
@ -263,9 +281,11 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl
|
|||||||
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo:
|
||||||
varMap["accessKey"] = backup.AccessKey
|
varMap["accessKey"] = backup.AccessKey
|
||||||
varMap["secretKey"] = backup.Credential
|
varMap["secretKey"] = backup.Credential
|
||||||
|
case constant.OneDrive:
|
||||||
|
varMap["accessToken"] = backup.Credential
|
||||||
}
|
}
|
||||||
|
|
||||||
backClient, err := cloud_storage.NewCloudStorageClient(varMap)
|
backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -286,6 +306,53 @@ func (u *BackupService) loadByType(accountType string, accounts []model.BackupAc
|
|||||||
return dto.BackupInfo{Type: accountType}
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("client_id", constant.OneDriveClientID)
|
||||||
|
data.Set("client_secret", constant.OneDriveClientSecret)
|
||||||
|
data.Set("grant_type", "authorization_code")
|
||||||
|
data.Set("code", varMap["code"].(string))
|
||||||
|
data.Set("redirect_uri", constant.OneDriveRedirectURI)
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest("POST", "https://login.microsoftonline.com/common/oauth2/v2.0/token", strings.NewReader(data.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("new http post client for access token failed, err: %v", err)
|
||||||
|
}
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("request for access token failed, err: %v", err)
|
||||||
|
}
|
||||||
|
delete(varMap, "code")
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read data from response body failed, err: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
token := map[string]interface{}{}
|
||||||
|
if err := json.Unmarshal(respBody, &token); err != nil {
|
||||||
|
return fmt.Errorf("unmarshal data from response body failed, err: %v", err)
|
||||||
|
}
|
||||||
|
accessToken, ok := token["refresh_token"].(string)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("no such access token in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
itemVars, err := json.Marshal(varMap)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("json marshal var map failed, err: %v", err)
|
||||||
|
}
|
||||||
|
backup.Credential = accessToken
|
||||||
|
backup.Vars = string(itemVars)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadLocalDir() (string, error) {
|
func loadLocalDir() (string, error) {
|
||||||
backup, err := backupRepo.Get(commonRepo.WithByType("LOCAL"))
|
backup, err := backupRepo.Get(commonRepo.WithByType("LOCAL"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -100,9 +100,9 @@ func (u *CronjobService) CleanRecord(req dto.CronjobClean) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
u.HandleRmExpired(backup.Type, localDir, &cronjob, client)
|
u.HandleRmExpired(backup.Type, backup.BackupPath, localDir, &cronjob, client)
|
||||||
} else {
|
} else {
|
||||||
u.HandleRmExpired(backup.Type, "", &cronjob, nil)
|
u.HandleRmExpired(backup.Type, backup.BackupPath, "", &cronjob, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(req.CronjobID)))
|
delRecords, err := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(req.CronjobID)))
|
||||||
|
@ -33,16 +33,16 @@ func (u *CronjobService) HandleJob(cronjob *model.Cronjob) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
message, err = u.handleShell(cronjob.Type, cronjob.Name, cronjob.Script)
|
message, err = u.handleShell(cronjob.Type, cronjob.Name, cronjob.Script)
|
||||||
u.HandleRmExpired("LOCAL", "", cronjob, nil)
|
u.HandleRmExpired("LOCAL", "", "", cronjob, nil)
|
||||||
case "curl":
|
case "curl":
|
||||||
if len(cronjob.URL) == 0 {
|
if len(cronjob.URL) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message, err = u.handleShell(cronjob.Type, cronjob.Name, fmt.Sprintf("curl '%s'", cronjob.URL))
|
message, err = u.handleShell(cronjob.Type, cronjob.Name, fmt.Sprintf("curl '%s'", cronjob.URL))
|
||||||
u.HandleRmExpired("LOCAL", "", cronjob, nil)
|
u.HandleRmExpired("LOCAL", "", "", cronjob, nil)
|
||||||
case "ntp":
|
case "ntp":
|
||||||
err = u.handleNtpSync()
|
err = u.handleNtpSync()
|
||||||
u.HandleRmExpired("LOCAL", "", cronjob, nil)
|
u.HandleRmExpired("LOCAL", "", "", cronjob, nil)
|
||||||
case "website":
|
case "website":
|
||||||
record.File, err = u.handleBackup(cronjob, record.StartTime)
|
record.File, err = u.handleBackup(cronjob, record.StartTime)
|
||||||
case "database":
|
case "database":
|
||||||
@ -142,19 +142,25 @@ func (u *CronjobService) handleBackup(cronjob *model.Cronjob, startTime time.Tim
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if len(backup.BackupPath) != 0 {
|
||||||
|
itemPath := strings.TrimPrefix(backup.BackupPath, "/")
|
||||||
|
itemPath = strings.TrimSuffix(itemPath, "/") + "/"
|
||||||
|
itemFileDir = itemPath + itemFileDir
|
||||||
|
}
|
||||||
if _, err = client.Upload(backupDir+"/"+fileName, itemFileDir+"/"+fileName); err != nil {
|
if _, err = client.Upload(backupDir+"/"+fileName, itemFileDir+"/"+fileName); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u.HandleRmExpired(backup.Type, localDir, cronjob, client)
|
u.HandleRmExpired(backup.Type, backup.BackupPath, localDir, cronjob, client)
|
||||||
if backup.Type == "LOCAL" || cronjob.KeepLocal {
|
if backup.Type == "LOCAL" || cronjob.KeepLocal {
|
||||||
return fmt.Sprintf("%s/%s/%s/%s", localDir, cronjob.Type, cronjob.Name, fileName), nil
|
return fmt.Sprintf("%s/%s", backupDir, fileName), nil
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s/%s", itemFileDir, fileName), nil
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s/%s", cronjob.Type, cronjob.Name, fileName), nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *CronjobService) HandleRmExpired(backType, localDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) {
|
func (u *CronjobService) HandleRmExpired(backType, backupPath, localDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) {
|
||||||
global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies)
|
global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies)
|
||||||
records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID)), commonRepo.WithOrderBy("created_at desc"))
|
records, _ := cronjobRepo.ListRecord(cronjobRepo.WithByJobID(int(cronjob.ID)), commonRepo.WithOrderBy("created_at desc"))
|
||||||
if len(records) > int(cronjob.RetainCopies) {
|
if len(records) > int(cronjob.RetainCopies) {
|
||||||
@ -163,7 +169,7 @@ func (u *CronjobService) HandleRmExpired(backType, localDir string, cronjob *mod
|
|||||||
files := strings.Split(records[i].File, ",")
|
files := strings.Split(records[i].File, ",")
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if backType != "LOCAL" {
|
if backType != "LOCAL" {
|
||||||
_, _ = backClient.Delete(strings.ReplaceAll(file, localDir+"/", ""))
|
_, _ = backClient.Delete(backupPath + "/" + strings.TrimPrefix(file, localDir+"/"))
|
||||||
_ = os.Remove(file)
|
_ = os.Remove(file)
|
||||||
} else {
|
} else {
|
||||||
_ = os.Remove(file)
|
_ = os.Remove(file)
|
||||||
@ -270,12 +276,11 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, app *repo.RootInf
|
|||||||
}
|
}
|
||||||
record.DetailName = dbName
|
record.DetailName = dbName
|
||||||
record.FileDir = backupDir
|
record.FileDir = backupDir
|
||||||
itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "")
|
itemFileDir := strings.TrimPrefix(backupDir, localDir+"/")
|
||||||
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
||||||
record.Source = backup.Type
|
record.Source = backup.Type
|
||||||
record.FileDir = itemFileDir
|
record.FileDir = itemFileDir
|
||||||
}
|
}
|
||||||
paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName))
|
|
||||||
|
|
||||||
if err := backupRepo.CreateRecord(&record); err != nil {
|
if err := backupRepo.CreateRecord(&record); err != nil {
|
||||||
global.LOG.Errorf("save backup record failed, err: %v", err)
|
global.LOG.Errorf("save backup record failed, err: %v", err)
|
||||||
@ -287,12 +292,22 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, app *repo.RootInf
|
|||||||
_ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName))
|
_ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName))
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if len(backup.BackupPath) != 0 {
|
||||||
|
itemPath := strings.TrimPrefix(backup.BackupPath, "/")
|
||||||
|
itemPath = strings.TrimSuffix(itemPath, "/") + "/"
|
||||||
|
itemFileDir = itemPath + itemFileDir
|
||||||
|
}
|
||||||
if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil {
|
if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil {
|
||||||
return paths, err
|
return paths, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if backup.Type == "LOCAL" || cronjob.KeepLocal {
|
||||||
|
paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName))
|
||||||
|
} else {
|
||||||
|
paths = append(paths, fmt.Sprintf("%s/%s", itemFileDir, record.FileName))
|
||||||
}
|
}
|
||||||
u.HandleRmExpired(backup.Type, localDir, &cronjob, client)
|
}
|
||||||
|
u.HandleRmExpired(backup.Type, backup.BackupPath, localDir, &cronjob, client)
|
||||||
return paths, nil
|
return paths, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +373,7 @@ func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime t
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
u.HandleRmExpired("LOCAL", "", cronjob, nil)
|
u.HandleRmExpired("LOCAL", "", "", cronjob, nil)
|
||||||
return strings.Join(filePaths, ","), nil
|
return strings.Join(filePaths, ","), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,10 +414,10 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, backup model.Backu
|
|||||||
}
|
}
|
||||||
backupDir := fmt.Sprintf("%s/website/%s", localDir, website.PrimaryDomain)
|
backupDir := fmt.Sprintf("%s/website/%s", localDir, website.PrimaryDomain)
|
||||||
record.FileDir = backupDir
|
record.FileDir = backupDir
|
||||||
itemFileDir := strings.ReplaceAll(backupDir, localDir+"/", "")
|
itemFileDir := strings.TrimPrefix(backupDir, localDir+"/")
|
||||||
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
if !cronjob.KeepLocal && backup.Type != "LOCAL" {
|
||||||
record.Source = backup.Type
|
record.Source = backup.Type
|
||||||
record.FileDir = strings.ReplaceAll(backupDir, localDir+"/", "")
|
record.FileDir = strings.TrimPrefix(backupDir, localDir+"/")
|
||||||
}
|
}
|
||||||
record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", website.PrimaryDomain, startTime.Format("20060102150405"))
|
record.FileName = fmt.Sprintf("website_%s_%s.tar.gz", website.PrimaryDomain, startTime.Format("20060102150405"))
|
||||||
paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName))
|
paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName))
|
||||||
@ -420,11 +435,21 @@ func (u *CronjobService) handleWebsite(cronjob model.Cronjob, backup model.Backu
|
|||||||
_ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName))
|
_ = os.RemoveAll(fmt.Sprintf("%s/%s", backupDir, record.FileName))
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
if len(backup.BackupPath) != 0 {
|
||||||
|
itemPath := strings.TrimPrefix(backup.BackupPath, "/")
|
||||||
|
itemPath = strings.TrimSuffix(itemPath, "/") + "/"
|
||||||
|
itemFileDir = itemPath + itemFileDir
|
||||||
|
}
|
||||||
if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil {
|
if _, err = client.Upload(backupDir+"/"+record.FileName, itemFileDir+"/"+record.FileName); err != nil {
|
||||||
return paths, err
|
return paths, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if backup.Type == "LOCAL" || cronjob.KeepLocal {
|
||||||
|
paths = append(paths, fmt.Sprintf("%s/%s", record.FileDir, record.FileName))
|
||||||
|
} else {
|
||||||
|
paths = append(paths, fmt.Sprintf("%s/%s", itemFileDir, record.FileName))
|
||||||
}
|
}
|
||||||
u.HandleRmExpired(backup.Type, localDir, &cronjob, client)
|
}
|
||||||
|
u.HandleRmExpired(backup.Type, backup.BackupPath, localDir, &cronjob, client)
|
||||||
return paths, nil
|
return paths, nil
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,12 @@ const (
|
|||||||
S3 = "S3"
|
S3 = "S3"
|
||||||
OSS = "OSS"
|
OSS = "OSS"
|
||||||
Sftp = "SFTP"
|
Sftp = "SFTP"
|
||||||
|
OneDrive = "OneDrive"
|
||||||
MinIo = "MINIO"
|
MinIo = "MINIO"
|
||||||
Cos = "COS"
|
Cos = "COS"
|
||||||
Kodo = "KODO"
|
Kodo = "KODO"
|
||||||
|
|
||||||
|
OneDriveClientID = "5446cfe3-4c79-47a0-ae25-fc645478e2d9"
|
||||||
|
OneDriveClientSecret = "ITh8Q~0UKJNXAvz6HE~pd3DTnGJOgDEEpnDOJbqY"
|
||||||
|
OneDriveRedirectURI = "http://localhost/login/authorized"
|
||||||
)
|
)
|
||||||
|
@ -31,6 +31,7 @@ func Init() {
|
|||||||
migrations.AddBindAndAllowIPs,
|
migrations.AddBindAndAllowIPs,
|
||||||
migrations.UpdateCronjobWithSecond,
|
migrations.UpdateCronjobWithSecond,
|
||||||
migrations.UpdateWebsite,
|
migrations.UpdateWebsite,
|
||||||
|
migrations.AddBackupAccountDir,
|
||||||
})
|
})
|
||||||
if err := m.Migrate(); err != nil {
|
if err := m.Migrate(); err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
|
@ -390,3 +390,13 @@ var UpdateWebsite = &gormigrate.Migration{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AddBackupAccountDir = &gormigrate.Migration{
|
||||||
|
ID: "20200620-add-backup-dir",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
if err := tx.AutoMigrate(&model.BackupAccount{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
327
backend/utils/cloud_storage/client/onedrive.go
Normal file
327
backend/utils/cloud_storage/client/onedrive.go
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
odsdk "github.com/goh-chunlin/go-onedrive/onedrive"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type oneDriveClient struct {
|
||||||
|
Vars map[string]interface{}
|
||||||
|
client odsdk.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOneDriveClient(vars map[string]interface{}) (*oneDriveClient, error) {
|
||||||
|
token := ""
|
||||||
|
if _, ok := vars["accessToken"]; ok {
|
||||||
|
token = vars["accessToken"].(string)
|
||||||
|
} else {
|
||||||
|
return nil, constant.ErrInvalidParams
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
newToken, err := refreshToken(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_ = global.DB.Model(&model.Group{}).Where("type = ?", "OneDrive").Updates(map[string]interface{}{"credential": newToken}).Error
|
||||||
|
|
||||||
|
ts := oauth2.StaticTokenSource(
|
||||||
|
&oauth2.Token{AccessToken: newToken},
|
||||||
|
)
|
||||||
|
tc := oauth2.NewClient(ctx, ts)
|
||||||
|
|
||||||
|
client := odsdk.NewClient(tc)
|
||||||
|
return &oneDriveClient{client: *client}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive oneDriveClient) ListBuckets() ([]interface{}, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive oneDriveClient) Exist(path string) (bool, error) {
|
||||||
|
path = "/" + strings.TrimPrefix(path, "/")
|
||||||
|
fileID, err := onedrive.loadIDByPath(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(fileID) != 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive oneDriveClient) Delete(path string) (bool, error) {
|
||||||
|
path = "/" + strings.TrimPrefix(path, "/")
|
||||||
|
fileID, err := onedrive.loadIDByPath(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := onedrive.client.DriveItems.Delete(context.Background(), "", fileID); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive oneDriveClient) Upload(src, target string) (bool, error) {
|
||||||
|
target = "/" + strings.TrimPrefix(target, "/")
|
||||||
|
if _, err := onedrive.loadIDByPath(path.Dir(target)); err != nil {
|
||||||
|
if !strings.Contains(err.Error(), "itemNotFound") {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err := onedrive.createFolder(path.Dir(target)); err != nil {
|
||||||
|
return false, fmt.Errorf("create dir before upload failed, err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
file, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
fileInfo, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
return false, errors.New("Only file is allowed to be uploaded here.")
|
||||||
|
}
|
||||||
|
fileName := fileInfo.Name()
|
||||||
|
fileSize := fileInfo.Size()
|
||||||
|
|
||||||
|
folderID, err := onedrive.loadIDByPath(path.Dir(target))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/createUploadSession", url.PathEscape(folderID), fileName)
|
||||||
|
sessionCreationRequestInside := NewUploadSessionCreationRequest{
|
||||||
|
ConflictBehavior: "rename",
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCreationRequest := struct {
|
||||||
|
Item NewUploadSessionCreationRequest `json:"item"`
|
||||||
|
DeferCommit bool `json:"deferCommit"`
|
||||||
|
}{sessionCreationRequestInside, false}
|
||||||
|
|
||||||
|
sessionCreationReq, err := onedrive.client.NewRequest("POST", apiURL, sessionCreationRequest)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionCreationResp *NewUploadSessionCreationResponse
|
||||||
|
err = onedrive.client.Do(ctx, sessionCreationReq, false, &sessionCreationResp)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("session creation failed %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSessionUploadUrl := sessionCreationResp.UploadURL
|
||||||
|
|
||||||
|
sizePerSplit := int64(3200 * 1024)
|
||||||
|
buffer := make([]byte, 3200*1024)
|
||||||
|
splitCount := fileSize / sizePerSplit
|
||||||
|
if fileSize%sizePerSplit != 0 {
|
||||||
|
splitCount += 1
|
||||||
|
}
|
||||||
|
bfReader := bufio.NewReader(file)
|
||||||
|
var fileUploadResp *UploadSessionUploadResponse
|
||||||
|
for splitNow := int64(0); splitNow < splitCount; splitNow++ {
|
||||||
|
length, err := bfReader.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if int64(length) < sizePerSplit {
|
||||||
|
bufferLast := buffer[:length]
|
||||||
|
buffer = bufferLast
|
||||||
|
}
|
||||||
|
sessionFileUploadReq, err := onedrive.NewSessionFileUploadRequest(fileSessionUploadUrl, splitNow*sizePerSplit, fileSize, bytes.NewReader(buffer))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err := onedrive.client.Do(ctx, sessionFileUploadReq, false, &fileUploadResp); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fileUploadResp.Id == "" {
|
||||||
|
return false, errors.New("something went wrong. file upload incomplete. consider upload the file in a step-by-step manner")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive oneDriveClient) Download(src, target string) (bool, error) {
|
||||||
|
src = "/" + strings.TrimPrefix(src, "/")
|
||||||
|
req, err := onedrive.client.NewRequest("GET", fmt.Sprintf("me/drive/root:%s", src), nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("new request for file id failed, err: %v", err)
|
||||||
|
}
|
||||||
|
var driveItem *odsdk.DriveItem
|
||||||
|
if err := onedrive.client.Do(context.Background(), req, false, &driveItem); err != nil {
|
||||||
|
return false, fmt.Errorf("do request for file id failed, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Get(driveItem.DownloadURL)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(target)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
buffer := make([]byte, 2*1024*1024)
|
||||||
|
|
||||||
|
_, err = io.CopyBuffer(out, resp.Body, buffer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive *oneDriveClient) ListObjects(prefix string) ([]interface{}, error) {
|
||||||
|
prefix = "/" + strings.TrimPrefix(prefix, "/")
|
||||||
|
folderID, err := onedrive.loadIDByPath(prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := onedrive.client.NewRequest("GET", fmt.Sprintf("me/drive/items/%s/children", folderID), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("new request for delete failed, err: %v", err)
|
||||||
|
}
|
||||||
|
var driveItems *odsdk.OneDriveDriveItemsResponse
|
||||||
|
if err := onedrive.client.Do(context.Background(), req, false, &driveItems); err != nil {
|
||||||
|
return nil, fmt.Errorf("do request for delete failed, err: %v", err)
|
||||||
|
}
|
||||||
|
for _, item := range driveItems.DriveItems {
|
||||||
|
return nil, fmt.Errorf("id: %v, name: %s \n", item.Id, item.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemList []interface{}
|
||||||
|
for _, item := range driveItems.DriveItems {
|
||||||
|
itemList = append(itemList, item.Name)
|
||||||
|
}
|
||||||
|
return itemList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive *oneDriveClient) loadIDByPath(path string) (string, error) {
|
||||||
|
req, err := onedrive.client.NewRequest("GET", fmt.Sprintf("me/drive/root:%s", path), nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("new request for file id failed, err: %v", err)
|
||||||
|
}
|
||||||
|
var driveItem *odsdk.DriveItem
|
||||||
|
if err := onedrive.client.Do(context.Background(), req, false, &driveItem); err != nil {
|
||||||
|
return "", fmt.Errorf("do request for file id failed, err: %v", err)
|
||||||
|
}
|
||||||
|
return driveItem.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func refreshToken(oldToken string) (string, error) {
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("client_id", constant.OneDriveClientID)
|
||||||
|
data.Set("client_secret", constant.OneDriveClientSecret)
|
||||||
|
data.Set("grant_type", "refresh_token")
|
||||||
|
data.Set("refresh_token", oldToken)
|
||||||
|
data.Set("redirect_uri", constant.OneDriveRedirectURI)
|
||||||
|
client := &http.Client{}
|
||||||
|
req, err := http.NewRequest("POST", "https://login.microsoftonline.com/common/oauth2/v2.0/token", strings.NewReader(data.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("new http post client for access token failed, err: %v", err)
|
||||||
|
}
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("request for access token failed, err: %v", err)
|
||||||
|
}
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("read data from response body failed, err: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
tokenMap := map[string]interface{}{}
|
||||||
|
if err := json.Unmarshal(respBody, &tokenMap); err != nil {
|
||||||
|
return "", fmt.Errorf("unmarshal data from response body failed, err: %v", err)
|
||||||
|
}
|
||||||
|
accessToken, ok := tokenMap["access_token"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("no such access token in response")
|
||||||
|
}
|
||||||
|
return accessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive *oneDriveClient) createFolder(parent string) error {
|
||||||
|
if _, err := onedrive.loadIDByPath(path.Dir(parent)); err != nil {
|
||||||
|
if !strings.Contains(err.Error(), "itemNotFound") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_ = onedrive.createFolder(path.Dir(parent))
|
||||||
|
}
|
||||||
|
item2, err := onedrive.loadIDByPath(path.Dir(parent))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := onedrive.client.DriveItems.CreateNewFolder(context.Background(), "", item2, path.Base(parent)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewUploadSessionCreationRequest struct {
|
||||||
|
ConflictBehavior string `json:"@microsoft.graph.conflictBehavior,omitempty"`
|
||||||
|
}
|
||||||
|
type NewUploadSessionCreationResponse struct {
|
||||||
|
UploadURL string `json:"uploadUrl"`
|
||||||
|
ExpirationDateTime string `json:"expirationDateTime"`
|
||||||
|
}
|
||||||
|
type UploadSessionUploadResponse struct {
|
||||||
|
ExpirationDateTime string `json:"expirationDateTime"`
|
||||||
|
NextExpectedRanges []string `json:"nextExpectedRanges"`
|
||||||
|
DriveItem
|
||||||
|
}
|
||||||
|
type DriveItem struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
DownloadURL string `json:"@microsoft.graph.downloadUrl"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
WebURL string `json:"webUrl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (onedrive *oneDriveClient) NewSessionFileUploadRequest(absoluteUrl string, grandOffset, grandTotalSize int64, byteReader *bytes.Reader) (*http.Request, error) {
|
||||||
|
apiUrl, err := onedrive.client.BaseURL.Parse(absoluteUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
absoluteUrl = apiUrl.String()
|
||||||
|
contentLength := byteReader.Size()
|
||||||
|
req, err := http.NewRequest("PUT", absoluteUrl, byteReader)
|
||||||
|
req.Header.Set("Content-Length", strconv.FormatInt(contentLength, 10))
|
||||||
|
preliminaryLength := grandOffset
|
||||||
|
preliminaryRange := grandOffset + contentLength - 1
|
||||||
|
if preliminaryRange >= grandTotalSize {
|
||||||
|
preliminaryRange = grandTotalSize - 1
|
||||||
|
preliminaryLength = preliminaryRange - grandOffset + 1
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", preliminaryLength, preliminaryRange, grandTotalSize))
|
||||||
|
|
||||||
|
return req, err
|
||||||
|
}
|
@ -14,24 +14,23 @@ type CloudStorageClient interface {
|
|||||||
Download(src, target string) (bool, error)
|
Download(src, target string) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCloudStorageClient(vars map[string]interface{}) (CloudStorageClient, error) {
|
func NewCloudStorageClient(backupType string, vars map[string]interface{}) (CloudStorageClient, error) {
|
||||||
if vars["type"] == constant.S3 {
|
switch backupType {
|
||||||
|
case constant.S3:
|
||||||
return client.NewS3Client(vars)
|
return client.NewS3Client(vars)
|
||||||
}
|
case constant.OSS:
|
||||||
if vars["type"] == constant.OSS {
|
|
||||||
return client.NewOssClient(vars)
|
return client.NewOssClient(vars)
|
||||||
}
|
case constant.Sftp:
|
||||||
if vars["type"] == constant.Sftp {
|
|
||||||
return client.NewSftpClient(vars)
|
return client.NewSftpClient(vars)
|
||||||
}
|
case constant.MinIo:
|
||||||
if vars["type"] == constant.MinIo {
|
|
||||||
return client.NewMinIoClient(vars)
|
return client.NewMinIoClient(vars)
|
||||||
}
|
case constant.Cos:
|
||||||
if vars["type"] == constant.Cos {
|
|
||||||
return client.NewCosClient(vars)
|
return client.NewCosClient(vars)
|
||||||
}
|
case constant.Kodo:
|
||||||
if vars["type"] == constant.Kodo {
|
|
||||||
return client.NewKodoClient(vars)
|
return client.NewKodoClient(vars)
|
||||||
}
|
case constant.OneDrive:
|
||||||
|
return client.NewOneDriveClient(vars)
|
||||||
|
default:
|
||||||
return nil, constant.ErrNotSupportType
|
return nil, constant.ErrNotSupportType
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ export namespace Backup {
|
|||||||
accessKey: string;
|
accessKey: string;
|
||||||
bucket: string;
|
bucket: string;
|
||||||
credential: string;
|
credential: string;
|
||||||
|
backupPath: string;
|
||||||
vars: string;
|
vars: string;
|
||||||
varsJson: object;
|
varsJson: object;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
@ -17,6 +18,7 @@ export namespace Backup {
|
|||||||
accessKey: string;
|
accessKey: string;
|
||||||
bucket: string;
|
bucket: string;
|
||||||
credential: string;
|
credential: string;
|
||||||
|
backupPath: string;
|
||||||
vars: string;
|
vars: string;
|
||||||
}
|
}
|
||||||
export interface RecordDownload {
|
export interface RecordDownload {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "panel"; /* Project id 3575356 */
|
font-family: "panel"; /* Project id 3575356 */
|
||||||
src: url('iconfont.woff2?t=1684465849452') format('woff2'),
|
src: url('iconfont.woff2?t=1687338712846') format('woff2'),
|
||||||
url('iconfont.woff?t=1684465849452') format('woff'),
|
url('iconfont.woff?t=1687338712846') format('woff'),
|
||||||
url('iconfont.ttf?t=1684465849452') format('truetype'),
|
url('iconfont.ttf?t=1687338712846') format('truetype'),
|
||||||
url('iconfont.svg?t=1684465849452#panel') format('svg');
|
url('iconfont.svg?t=1687338712846#panel') format('svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
@ -14,6 +14,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-onedrive:before {
|
||||||
|
content: "\e601";
|
||||||
|
}
|
||||||
|
|
||||||
.p-caidan:before {
|
.p-caidan:before {
|
||||||
content: "\e61d";
|
content: "\e61d";
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -5,6 +5,13 @@
|
|||||||
"css_prefix_text": "p-",
|
"css_prefix_text": "p-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "13015332",
|
||||||
|
"name": "onedrive",
|
||||||
|
"font_class": "onedrive",
|
||||||
|
"unicode": "e601",
|
||||||
|
"unicode_decimal": 58881
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "7708032",
|
"icon_id": "7708032",
|
||||||
"name": "菜单",
|
"name": "菜单",
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
/>
|
/>
|
||||||
<missing-glyph />
|
<missing-glyph />
|
||||||
|
|
||||||
|
<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" />
|
||||||
|
|
||||||
<glyph glyph-name="caidan" unicode="" d="M896 663.272727h-744.727273a34.909091 34.909091 0 0 0 0 69.818182h744.727273a34.909091 34.909091 0 0 0 0-69.818182zM896 11.636364h-744.727273a34.909091 34.909091 0 0 0 0 69.818181h744.727273a34.909091 34.909091 0 0 0 0-69.818181zM709.818182 337.454545h-558.545455a34.909091 34.909091 0 0 0 0 69.818182h558.545455a34.909091 34.909091 0 0 0 0-69.818182z" horiz-adv-x="1024" />
|
<glyph glyph-name="caidan" unicode="" d="M896 663.272727h-744.727273a34.909091 34.909091 0 0 0 0 69.818182h744.727273a34.909091 34.909091 0 0 0 0-69.818182zM896 11.636364h-744.727273a34.909091 34.909091 0 0 0 0 69.818181h744.727273a34.909091 34.909091 0 0 0 0-69.818181zM709.818182 337.454545h-558.545455a34.909091 34.909091 0 0 0 0 69.818182h558.545455a34.909091 34.909091 0 0 0 0-69.818182z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
<glyph glyph-name="yanzhengma1" unicode="" d="M544 627h124c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32H544v-116a32.5 32.5 0 0 0-0.056-1.916C670.218 429.588 768 321.96299999999997 768 191.5 768 50.39099999999996 653.609-64 512.5-64 371.391-64 257 50.39099999999996 257 191.5c0 130.12 97.27 237.523 223.064 253.46A32.488 32.488 0 0 0 480 447V800c0 17.673 14.327 32 32 32 17.673 0 32-14.327 32-32v-45h192c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32H544v-64z m-31.5-627C618.263 0 704 85.73699999999997 704 191.5S618.263 383 512.5 383 321 297.26300000000003 321 191.5 406.737 0 512.5 0z" horiz-adv-x="1024" />
|
<glyph glyph-name="yanzhengma1" unicode="" d="M544 627h124c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32H544v-116a32.5 32.5 0 0 0-0.056-1.916C670.218 429.588 768 321.96299999999997 768 191.5 768 50.39099999999996 653.609-64 512.5-64 371.391-64 257 50.39099999999996 257 191.5c0 130.12 97.27 237.523 223.064 253.46A32.488 32.488 0 0 0 480 447V800c0 17.673 14.327 32 32 32 17.673 0 32-14.327 32-32v-45h192c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32H544v-64z m-31.5-627C618.263 0 704 85.73699999999997 704 191.5S618.263 383 512.5 383 321 297.26300000000003 321 191.5 406.737 0 512.5 0z" horiz-adv-x="1024" />
|
||||||
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 66 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -989,6 +989,11 @@ const message = {
|
|||||||
S3: 'Amazon S3',
|
S3: 'Amazon S3',
|
||||||
MINIO: 'MINIO',
|
MINIO: 'MINIO',
|
||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
|
OneDrive: 'Microsoft OneDrive',
|
||||||
|
backupDir: 'Backup dir',
|
||||||
|
isCN: 'Domestic version',
|
||||||
|
code: 'Auth code',
|
||||||
|
loadCode: 'Acquire',
|
||||||
COS: 'Tencent COS',
|
COS: 'Tencent COS',
|
||||||
KODO: 'Qiniu Kodo',
|
KODO: 'Qiniu Kodo',
|
||||||
domainHelper: 'The accelerated domain name must contain http:// or https://',
|
domainHelper: 'The accelerated domain name must contain http:// or https://',
|
||||||
|
@ -967,6 +967,11 @@ const message = {
|
|||||||
S3: '亚马逊 S3 云存储',
|
S3: '亚马逊 S3 云存储',
|
||||||
MINIO: 'MINIO',
|
MINIO: 'MINIO',
|
||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
|
OneDrive: '微软 OneDrive',
|
||||||
|
backupDir: '备份路径',
|
||||||
|
isCN: '国内版',
|
||||||
|
code: '授权码',
|
||||||
|
loadCode: '获取',
|
||||||
COS: '腾讯云 COS',
|
COS: '腾讯云 COS',
|
||||||
KODO: '七牛云 Kodo',
|
KODO: '七牛云 Kodo',
|
||||||
domainHelper: '加速域名必须包含 http:// 或者 https://',
|
domainHelper: '加速域名必须包含 http:// 或者 https://',
|
||||||
|
@ -66,6 +66,9 @@
|
|||||||
<el-form-item label="Bucket">
|
<el-form-item label="Bucket">
|
||||||
{{ s3Data.bucket }}
|
{{ s3Data.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ s3Data.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, s3Data.createdAt) }}
|
{{ dateFormat(0, 0, s3Data.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -102,6 +105,9 @@
|
|||||||
<el-form-item label="Bucket">
|
<el-form-item label="Bucket">
|
||||||
{{ ossData.bucket }}
|
{{ ossData.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ ossData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, ossData.createdAt) }}
|
{{ dateFormat(0, 0, ossData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -139,6 +145,9 @@
|
|||||||
<el-form-item label="Bucket">
|
<el-form-item label="Bucket">
|
||||||
{{ cosData.bucket }}
|
{{ cosData.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ cosData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, cosData.createdAt) }}
|
{{ dateFormat(0, 0, cosData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -149,6 +158,47 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-alert>
|
</el-alert>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
|
<div>
|
||||||
|
<svg-icon style="font-size: 7px" iconName="p-onedrive"></svg-icon>
|
||||||
|
<span style="font-size: 14px; font-weight: 500"> {{ $t('setting.OneDrive') }}</span>
|
||||||
|
<div style="float: right">
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
plain
|
||||||
|
:disabled="oneDriveData.id === 0"
|
||||||
|
@click="onOpenDialog('edit', 'SFTP', oneDriveData)"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button round :disabled="oneDriveData.id === 0" @click="onDelete(oneDriveData)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-divider class="devider" />
|
||||||
|
<div v-if="oneDriveData.id !== 0" style="margin-left: 20px">
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ oneDriveData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
|
{{ dateFormat(0, 0, oneDriveData.createdAt) }}
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-alert v-else center class="alert" style="height: 167px" :closable="false">
|
||||||
|
<el-button
|
||||||
|
size="large"
|
||||||
|
round
|
||||||
|
plain
|
||||||
|
type="primary"
|
||||||
|
@click="onOpenDialog('create', 'OneDrive')"
|
||||||
|
>
|
||||||
|
{{ $t('setting.createBackupAccount', [$t('setting.OneDrive')]) }}
|
||||||
|
</el-button>
|
||||||
|
</el-alert>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
<div>
|
<div>
|
||||||
<svg-icon style="font-size: 7px" iconName="p-qiniuyun"></svg-icon>
|
<svg-icon style="font-size: 7px" iconName="p-qiniuyun"></svg-icon>
|
||||||
@ -175,6 +225,9 @@
|
|||||||
<el-form-item label="Bucket">
|
<el-form-item label="Bucket">
|
||||||
{{ kodoData.bucket }}
|
{{ kodoData.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ kodoData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, kodoData.createdAt) }}
|
{{ dateFormat(0, 0, kodoData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -185,8 +238,6 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-alert>
|
</el-alert>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="20" style="margin-top: 20px">
|
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
<div>
|
<div>
|
||||||
<svg-icon style="font-size: 7px" iconName="p-minio"></svg-icon>
|
<svg-icon style="font-size: 7px" iconName="p-minio"></svg-icon>
|
||||||
@ -212,6 +263,9 @@
|
|||||||
<el-form-item label="Bucket">
|
<el-form-item label="Bucket">
|
||||||
{{ minioData.bucket }}
|
{{ minioData.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ minioData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, minioData.createdAt) }}
|
{{ dateFormat(0, 0, minioData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -222,6 +276,8 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-alert>
|
</el-alert>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||||
<div>
|
<div>
|
||||||
<svg-icon style="font-size: 7px" iconName="p-SFTP"></svg-icon>
|
<svg-icon style="font-size: 7px" iconName="p-SFTP"></svg-icon>
|
||||||
@ -251,6 +307,9 @@
|
|||||||
<el-form-item :label="$t('setting.path')">
|
<el-form-item :label="$t('setting.path')">
|
||||||
{{ sftpData.bucket }}
|
{{ sftpData.bucket }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.backupDir')">
|
||||||
|
{{ sftpData.backupPath }}
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, sftpData.createdAt) }}
|
{{ dateFormat(0, 0, sftpData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -284,6 +343,7 @@ const localData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
dir: '',
|
dir: '',
|
||||||
@ -296,6 +356,7 @@ const ossData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
region: '',
|
region: '',
|
||||||
@ -309,6 +370,7 @@ const minioData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
region: '',
|
region: '',
|
||||||
@ -322,6 +384,7 @@ const sftpData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
address: '',
|
address: '',
|
||||||
@ -329,12 +392,26 @@ const sftpData = ref<Backup.BackupInfo>({
|
|||||||
},
|
},
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
});
|
});
|
||||||
|
const oneDriveData = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'OneDrive',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
redirectURI: '',
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
const s3Data = ref<Backup.BackupInfo>({
|
const s3Data = ref<Backup.BackupInfo>({
|
||||||
id: 0,
|
id: 0,
|
||||||
type: 'S3',
|
type: 'S3',
|
||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
region: '',
|
region: '',
|
||||||
@ -348,6 +425,7 @@ const cosData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
region: '',
|
region: '',
|
||||||
@ -360,6 +438,7 @@ const kodoData = ref<Backup.BackupInfo>({
|
|||||||
accessKey: '',
|
accessKey: '',
|
||||||
bucket: '',
|
bucket: '',
|
||||||
credential: '',
|
credential: '',
|
||||||
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
domain: '',
|
domain: '',
|
||||||
@ -396,6 +475,9 @@ const search = async () => {
|
|||||||
case 'KODO':
|
case 'KODO':
|
||||||
kodoData.value = bac;
|
kodoData.value = bac;
|
||||||
break;
|
break;
|
||||||
|
case 'OneDrive':
|
||||||
|
oneDriveData.value = bac;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -45,6 +45,21 @@
|
|||||||
>
|
>
|
||||||
<el-input show-password clearable v-model.trim="dialogData.rowData!.credential" />
|
<el-input show-password clearable v-model.trim="dialogData.rowData!.credential" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="dialogData.rowData!.type === 'OneDrive'">
|
||||||
|
<el-checkbox v-model="dialogData.rowData!.varsJson['isCN']" :label="$t('setting.isCN')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="dialogData.rowData!.type === 'OneDrive'"
|
||||||
|
:label="$t('setting.code')"
|
||||||
|
prop="varsJson.code"
|
||||||
|
:rules="Rules.requiredInput"
|
||||||
|
>
|
||||||
|
<el-input clearable v-model.trim="dialogData.rowData!.varsJson['code']">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="jumpAzure">{{ $t('setting.loadCode') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="dialogData.rowData!.type === 'S3' || dialogData.rowData!.type === 'COS'"
|
v-if="dialogData.rowData!.type === 'S3' || dialogData.rowData!.type === 'COS'"
|
||||||
label="Region"
|
label="Region"
|
||||||
@ -136,6 +151,13 @@
|
|||||||
<el-input v-model="dialogData.rowData!.bucket" />
|
<el-input v-model="dialogData.rowData!.bucket" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
<el-form-item
|
||||||
|
v-if="dialogData.rowData!.type !== 'LOCAL'"
|
||||||
|
:label="$t('setting.backupDir')"
|
||||||
|
prop="backupPath"
|
||||||
|
>
|
||||||
|
<el-input clearable v-model.trim="dialogData.rowData!.backupPath" />
|
||||||
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
@ -206,6 +228,16 @@ const handleClose = () => {
|
|||||||
drawerVisiable.value = false;
|
drawerVisiable.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const jumpAzure = () => {
|
||||||
|
let commonUrl =
|
||||||
|
'response_type=code&client_id=5446cfe3-4c79-47a0-ae25-fc645478e2d9&redirect_uri=http://localhost/login/authorized&scope=offline_access+Files.ReadWrite.All+User.Read';
|
||||||
|
if (!dialogData.value.rowData!.varsJson['isCN']) {
|
||||||
|
window.open('https://login.microsoftonline.com/common/oauth2/v2.0/authorize?' + commonUrl, '_blank');
|
||||||
|
} else {
|
||||||
|
window.open('https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize?' + commonUrl, '_blank');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadDir = async (path: string) => {
|
const loadDir = async (path: string) => {
|
||||||
dialogData.value.rowData!.varsJson['dir'] = path;
|
dialogData.value.rowData!.varsJson['dir'] = path;
|
||||||
};
|
};
|
||||||
|
12
go.mod
12
go.mod
@ -22,6 +22,7 @@ require (
|
|||||||
github.com/go-gormigrate/gormigrate/v2 v2.0.2
|
github.com/go-gormigrate/gormigrate/v2 v2.0.2
|
||||||
github.com/go-playground/validator/v10 v10.14.0
|
github.com/go-playground/validator/v10 v10.14.0
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
github.com/go-sql-driver/mysql v1.6.0
|
||||||
|
github.com/goh-chunlin/go-onedrive v1.1.1
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
@ -51,6 +52,7 @@ require (
|
|||||||
github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f
|
github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f
|
||||||
golang.org/x/crypto v0.9.0
|
golang.org/x/crypto v0.9.0
|
||||||
golang.org/x/net v0.10.0
|
golang.org/x/net v0.10.0
|
||||||
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
|
||||||
golang.org/x/sys v0.8.0
|
golang.org/x/sys v0.8.0
|
||||||
golang.org/x/text v0.9.0
|
golang.org/x/text v0.9.0
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
@ -113,7 +115,7 @@ require (
|
|||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/glebarez/go-sqlite v1.21.1 // indirect
|
github.com/glebarez/go-sqlite v1.21.1 // indirect
|
||||||
github.com/go-logr/logr v1.2.3 // indirect
|
github.com/go-logr/logr v1.2.4 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
@ -141,6 +143,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||||
|
github.com/h2non/filetype v1.1.1 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
@ -208,7 +211,7 @@ require (
|
|||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/stretchr/testify v1.8.3 // indirect
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
github.com/therootcompany/xz v1.0.1 // indirect
|
github.com/therootcompany/xz v1.0.1 // indirect
|
||||||
github.com/theupdateframework/notary v0.7.0 // indirect
|
github.com/theupdateframework/notary v0.7.0 // indirect
|
||||||
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect
|
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 // indirect
|
||||||
@ -229,7 +232,7 @@ require (
|
|||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.29.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.29.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
go.opentelemetry.io/otel v1.15.1 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect
|
||||||
@ -237,13 +240,12 @@ require (
|
|||||||
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
|
go.opentelemetry.io/otel/internal/metric v0.27.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v0.27.0 // indirect
|
go.opentelemetry.io/otel/metric v0.27.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.4.1 // indirect
|
go.opentelemetry.io/otel/sdk v1.4.1 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
go.opentelemetry.io/otel/trace v1.15.1 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
|
||||||
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/image v0.5.0 // indirect
|
golang.org/x/image v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
|
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/term v0.8.0 // indirect
|
golang.org/x/term v0.8.0 // indirect
|
||||||
golang.org/x/time v0.1.0 // indirect
|
golang.org/x/time v0.1.0 // indirect
|
||||||
|
20
go.sum
20
go.sum
@ -299,8 +299,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
|
|||||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
@ -349,6 +349,8 @@ github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
|||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/goh-chunlin/go-onedrive v1.1.1 h1:HGtHk5iG0MZ92zYUtaY04czfZPBIJUr12UuFc+PW8m4=
|
||||||
|
github.com/goh-chunlin/go-onedrive v1.1.1/go.mod h1:N8qIGHD7tryO734epiBKk5oXcpGwxKET/u3LuBHciTs=
|
||||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
@ -461,6 +463,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaW
|
|||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
|
github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4=
|
||||||
|
github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
@ -827,8 +831,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
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/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
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/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY=
|
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY=
|
||||||
@ -915,8 +920,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0 h1:SLme4Po
|
|||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.29.0/go.mod h1:tLYsuf2v8fZreBVwp9gVMhefZlLFZaUiNVSq8QxXRII=
|
||||||
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
|
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
|
||||||
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
|
go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4=
|
||||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8=
|
||||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8=
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8=
|
||||||
@ -933,8 +938,8 @@ go.opentelemetry.io/otel/sdk v1.4.1 h1:J7EaW71E0v87qflB4cDolaqq3AcujGrtyIPGQoZOB
|
|||||||
go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE=
|
go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE=
|
||||||
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
|
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
|
||||||
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
|
go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc=
|
||||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY=
|
||||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c=
|
go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c=
|
||||||
go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ=
|
go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ=
|
||||||
@ -1015,6 +1020,7 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
|||||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user