mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: OneDrive 增加 Token 刷新机制 (#3637)
This commit is contained in:
parent
1e5cd23bbe
commit
6499d7f462
@ -49,6 +49,17 @@ func (b *BaseApi) CreateBackup(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags Backup Account
|
||||||
|
// @Summary Refresh OneDrive token
|
||||||
|
// @Description 刷新 OneDrive token
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /settings/backup/refresh/onedrive [post]
|
||||||
|
func (b *BaseApi) RefreshOneDriveToken(c *gin.Context) {
|
||||||
|
backupService.Run()
|
||||||
|
helper.SuccessWithData(c, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// @Tags Backup Account
|
// @Tags Backup Account
|
||||||
// @Summary List buckets
|
// @Summary List buckets
|
||||||
// @Description 获取 bucket 列表
|
// @Description 获取 bucket 列表
|
||||||
|
@ -6,12 +6,10 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
@ -19,6 +17,7 @@ import (
|
|||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage/client"
|
||||||
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
|
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -55,6 +54,8 @@ type IBackupService interface {
|
|||||||
|
|
||||||
AppBackup(db dto.CommonBackup) error
|
AppBackup(db dto.CommonBackup) error
|
||||||
AppRecover(req dto.CommonRecover) error
|
AppRecover(req dto.CommonRecover) error
|
||||||
|
|
||||||
|
Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIBackupService() IBackupService {
|
func NewIBackupService() IBackupService {
|
||||||
@ -205,6 +206,9 @@ func (u *BackupService) Create(req dto.BackupOperate) error {
|
|||||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if backup.Type == constant.OneDrive {
|
||||||
|
StartRefreshOneDriveToken()
|
||||||
|
}
|
||||||
if err := backupRepo.Create(&backup); err != nil {
|
if err := backupRepo.Create(&backup); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -232,6 +236,13 @@ func (u *BackupService) GetBuckets(backupDto dto.ForBuckets) ([]interface{}, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *BackupService) Delete(id uint) error {
|
func (u *BackupService) Delete(id uint) error {
|
||||||
|
backup, _ := backupRepo.Get(commonRepo.WithByID(id))
|
||||||
|
if backup.ID == 0 {
|
||||||
|
return constant.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
if backup.Type == constant.OneDrive {
|
||||||
|
global.Cron.Remove(global.OneDriveCronID)
|
||||||
|
}
|
||||||
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByBackupID(id))
|
cronjobs, _ := cronjobRepo.List(cronjobRepo.WithByBackupID(id))
|
||||||
if len(cronjobs) != 0 {
|
if len(cronjobs) != 0 {
|
||||||
return buserr.New(constant.ErrBackupInUsed)
|
return buserr.New(constant.ErrBackupInUsed)
|
||||||
@ -387,6 +398,15 @@ func (u *BackupService) loadByType(accountType string, accounts []model.BackupAc
|
|||||||
if err := copier.Copy(&item, &account); err != nil {
|
if err := copier.Copy(&item, &account); err != nil {
|
||||||
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
|
global.LOG.Errorf("copy backup account to dto backup info failed, err: %v", err)
|
||||||
}
|
}
|
||||||
|
if account.Type == constant.OneDrive {
|
||||||
|
varMap := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal([]byte(item.Vars), &varMap); err != nil {
|
||||||
|
return dto.BackupInfo{Type: accountType}
|
||||||
|
}
|
||||||
|
delete(varMap, "refresh_token")
|
||||||
|
itemVars, _ := json.Marshal(varMap)
|
||||||
|
item.Vars = string(itemVars)
|
||||||
|
}
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,44 +418,23 @@ func (u *BackupService) loadAccessToken(backup *model.BackupAccount) error {
|
|||||||
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
|
||||||
return fmt.Errorf("unmarshal backup vars failed, err: %v", err)
|
return fmt.Errorf("unmarshal backup vars failed, err: %v", err)
|
||||||
}
|
}
|
||||||
|
code, ok := varMap["code"]
|
||||||
data := url.Values{}
|
|
||||||
data.Set("client_id", global.CONF.System.OneDriveID)
|
|
||||||
data.Set("client_secret", global.CONF.System.OneDriveSc)
|
|
||||||
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 {
|
if !ok {
|
||||||
return errors.New("no such access token in response")
|
return errors.New("no such token in request, please retry!")
|
||||||
}
|
}
|
||||||
|
token, refreshToken, err := client.RefreshToken("authorization_code", code.(string))
|
||||||
itemVars, err := json.Marshal(varMap)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
backup.Credential = token
|
||||||
|
varMapItem := make(map[string]interface{})
|
||||||
|
varMapItem["refresh_status"] = constant.StatusSuccess
|
||||||
|
varMapItem["refresh_time"] = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
varMapItem["refresh_token"] = refreshToken
|
||||||
|
itemVars, err := json.Marshal(varMapItem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("json marshal var map failed, err: %v", err)
|
return fmt.Errorf("json marshal var map failed, err: %v", err)
|
||||||
}
|
}
|
||||||
backup.Credential = accessToken
|
|
||||||
backup.Vars = string(itemVars)
|
backup.Vars = string(itemVars)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -521,3 +520,56 @@ func (u *BackupService) checkBackupConn(backup *model.BackupAccount) (bool, erro
|
|||||||
targetPath := strings.TrimPrefix(path.Join(backup.BackupPath, "test/1panel"), "/")
|
targetPath := strings.TrimPrefix(path.Join(backup.BackupPath, "test/1panel"), "/")
|
||||||
return client.Upload(fileItem, targetPath)
|
return client.Upload(fileItem, targetPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StartRefreshOneDriveToken() {
|
||||||
|
service := NewIBackupService()
|
||||||
|
oneDriveCronID, err := global.Cron.AddJob("0 * * * *", service)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("can not add OneDrive corn job: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
global.OneDriveCronID = oneDriveCronID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *BackupService) Run() {
|
||||||
|
var backupItem model.BackupAccount
|
||||||
|
_ = global.DB.Where("`type` = ?", "OneDrive").First(&backupItem)
|
||||||
|
if backupItem.ID == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(backupItem.Credential) == 0 {
|
||||||
|
global.LOG.Error("OneDrive configuration lacks token information, please rebind.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
global.LOG.Info("start to refresh token of OneDrive ...")
|
||||||
|
varMap := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal([]byte(backupItem.Vars), &varMap); err != nil {
|
||||||
|
global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
refreshItem, ok := varMap["refresh_token"]
|
||||||
|
if !ok {
|
||||||
|
global.LOG.Error("Failed to refresh OneDrive token, please retry, err: no such refresh token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, refreshToken, err := client.RefreshToken("refresh_token", refreshItem.(string))
|
||||||
|
varMap["refresh_status"] = constant.StatusSuccess
|
||||||
|
varMap["refresh_time"] = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
if err != nil {
|
||||||
|
varMap["refresh_status"] = constant.StatusFailed
|
||||||
|
varMap["refresh_msg"] = err.Error()
|
||||||
|
global.LOG.Errorf("Failed to refresh OneDrive token, please retry, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
varMap["refresh_token"] = refreshToken
|
||||||
|
|
||||||
|
varsItem, _ := json.Marshal(varMap)
|
||||||
|
_ = global.DB.Model(&model.BackupAccount{}).
|
||||||
|
Where("id = ?", backupItem.ID).
|
||||||
|
Updates(map[string]interface{}{
|
||||||
|
"credential": token,
|
||||||
|
"vars": varsItem,
|
||||||
|
}).Error
|
||||||
|
global.LOG.Info("Successfully refreshed OneDrive token.")
|
||||||
|
}
|
||||||
|
@ -211,6 +211,6 @@ func StartMonitor(removeBefore bool, interval string) error {
|
|||||||
go service.saveIODataToDB(ctx, float64(intervalItem))
|
go service.saveIODataToDB(ctx, float64(intervalItem))
|
||||||
go service.saveNetDataToDB(ctx, float64(intervalItem))
|
go service.saveNetDataToDB(ctx, float64(intervalItem))
|
||||||
|
|
||||||
global.MonitorCronID = int(monitorID)
|
global.MonitorCronID = monitorID
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,12 @@ func Run() {
|
|||||||
if _, err := global.Cron.AddJob("@daily", job.NewAppStoreJob()); err != nil {
|
if _, err := global.Cron.AddJob("@daily", job.NewAppStoreJob()); err != nil {
|
||||||
global.LOG.Errorf("can not add appstore corn job: %s", err.Error())
|
global.LOG.Errorf("can not add appstore corn job: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var backup model.BackupAccount
|
||||||
|
_ = global.DB.Where("type = ?", "OneDrive").Find(&backup).Error
|
||||||
|
if backup.ID != 0 {
|
||||||
|
service.StartRefreshOneDriveToken()
|
||||||
|
}
|
||||||
global.Cron.Start()
|
global.Cron.Start()
|
||||||
|
|
||||||
var cronJobs []model.Cronjob
|
var cronJobs []model.Cronjob
|
||||||
|
@ -21,5 +21,6 @@ var (
|
|||||||
Viper *viper.Viper
|
Viper *viper.Viper
|
||||||
|
|
||||||
Cron *cron.Cron
|
Cron *cron.Cron
|
||||||
MonitorCronID int
|
MonitorCronID cron.EntryID
|
||||||
|
OneDriveCronID cron.EntryID
|
||||||
)
|
)
|
||||||
|
@ -66,6 +66,7 @@ func Init() {
|
|||||||
migrations.AddTableDatabasePostgresql,
|
migrations.AddTableDatabasePostgresql,
|
||||||
migrations.AddPostgresqlSuperUser,
|
migrations.AddPostgresqlSuperUser,
|
||||||
migrations.UpdateCronjobWithWebsite,
|
migrations.UpdateCronjobWithWebsite,
|
||||||
|
migrations.UpdateOneDriveToken,
|
||||||
})
|
})
|
||||||
if err := m.Migrate(); err != nil {
|
if err := m.Migrate(); err != nil {
|
||||||
global.LOG.Error(err)
|
global.LOG.Error(err)
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
package migrations
|
package migrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
"github.com/1Panel-dev/1Panel/backend/app/repo"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/service"
|
"github.com/1Panel-dev/1Panel/backend/app/service"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/cloud_storage/client"
|
||||||
"github.com/go-gormigrate/gormigrate/v2"
|
"github.com/go-gormigrate/gormigrate/v2"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -188,3 +194,58 @@ var UpdateCronjobWithWebsite = &gormigrate.Migration{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var UpdateOneDriveToken = &gormigrate.Migration{
|
||||||
|
ID: "20240117-update-onedrive-token",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
var (
|
||||||
|
backup model.BackupAccount
|
||||||
|
clientSetting model.Setting
|
||||||
|
secretSetting model.Setting
|
||||||
|
)
|
||||||
|
_ = tx.Where("type = ?", "OneDrive").First(&backup).Error
|
||||||
|
if backup.ID == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(backup.Credential) == 0 {
|
||||||
|
global.LOG.Error("OneDrive configuration lacks token information, please rebind.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = tx.Where("key = ?", "OneDriveID").First(&clientSetting).Error
|
||||||
|
if clientSetting.ID == 0 {
|
||||||
|
global.LOG.Error("system configuration lacks clientID information, please retry.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_ = tx.Where("key = ?", "OneDriveSc").First(&secretSetting).Error
|
||||||
|
if secretSetting.ID == 0 {
|
||||||
|
global.LOG.Error("system configuration lacks clientID information, please retry.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
idItem, _ := base64.StdEncoding.DecodeString(clientSetting.Value)
|
||||||
|
global.CONF.System.OneDriveID = string(idItem)
|
||||||
|
scItem, _ := base64.StdEncoding.DecodeString(secretSetting.Value)
|
||||||
|
global.CONF.System.OneDriveSc = string(scItem)
|
||||||
|
|
||||||
|
varMap := make(map[string]interface{})
|
||||||
|
token, refreshToken, err := client.RefreshToken("refresh_token", backup.Credential)
|
||||||
|
varMap["refresh_status"] = constant.StatusSuccess
|
||||||
|
varMap["refresh_time"] = time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
if err != nil {
|
||||||
|
varMap["refresh_msg"] = err.Error()
|
||||||
|
varMap["refresh_status"] = constant.StatusFailed
|
||||||
|
}
|
||||||
|
varMap["refresh_token"] = refreshToken
|
||||||
|
itemVars, _ := json.Marshal(varMap)
|
||||||
|
if err := tx.Model(&model.BackupAccount{}).
|
||||||
|
Where("id = ?", backup.ID).
|
||||||
|
Updates(map[string]interface{}{
|
||||||
|
"credential": token,
|
||||||
|
"vars": string(itemVars),
|
||||||
|
}).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -45,6 +45,7 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) {
|
|||||||
settingRouter.GET("/backup/search", baseApi.ListBackup)
|
settingRouter.GET("/backup/search", baseApi.ListBackup)
|
||||||
settingRouter.GET("/backup/onedrive", baseApi.LoadOneDriveInfo)
|
settingRouter.GET("/backup/onedrive", baseApi.LoadOneDriveInfo)
|
||||||
settingRouter.POST("/backup/backup", baseApi.Backup)
|
settingRouter.POST("/backup/backup", baseApi.Backup)
|
||||||
|
settingRouter.POST("/backup/refresh/onedrive", baseApi.RefreshOneDriveToken)
|
||||||
settingRouter.POST("/backup/recover", baseApi.Recover)
|
settingRouter.POST("/backup/recover", baseApi.Recover)
|
||||||
settingRouter.POST("/backup/recover/byupload", baseApi.RecoverByUpload)
|
settingRouter.POST("/backup/recover/byupload", baseApi.RecoverByUpload)
|
||||||
settingRouter.POST("/backup/search/files", baseApi.LoadFilesFromBackup)
|
settingRouter.POST("/backup/search/files", baseApi.LoadFilesFromBackup)
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -15,11 +14,10 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
odsdk "github.com/goh-chunlin/go-onedrive/onedrive"
|
odsdk "github.com/goh-chunlin/go-onedrive/onedrive"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
@ -31,15 +29,8 @@ type oneDriveClient struct {
|
|||||||
func NewOneDriveClient(vars map[string]interface{}) (*oneDriveClient, error) {
|
func NewOneDriveClient(vars map[string]interface{}) (*oneDriveClient, error) {
|
||||||
token := loadParamFromVars("accessToken", true, vars)
|
token := loadParamFromVars("accessToken", true, vars)
|
||||||
ctx := context.Background()
|
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(
|
ts := oauth2.StaticTokenSource(
|
||||||
&oauth2.Token{AccessToken: newToken},
|
&oauth2.Token{AccessToken: token},
|
||||||
)
|
)
|
||||||
tc := oauth2.NewClient(ctx, ts)
|
tc := oauth2.NewClient(ctx, ts)
|
||||||
|
|
||||||
@ -110,87 +101,24 @@ func (o oneDriveClient) Upload(src, target string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
file, err := os.Open(src)
|
folderID, err := o.loadIDByPath(path.Dir(target))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
fileInfo, err := os.Stat(src)
|
||||||
fileInfo, err := file.Stat()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if fileInfo.IsDir() {
|
if fileInfo.IsDir() {
|
||||||
return false, errors.New("Only file is allowed to be uploaded here.")
|
return false, errors.New("Only file is allowed to be uploaded here.")
|
||||||
}
|
}
|
||||||
fileName := fileInfo.Name()
|
var isOk bool
|
||||||
fileSize := fileInfo.Size()
|
if fileInfo.Size() > 4*1024*1024 {
|
||||||
|
isOk, err = o.upSmall(ctx, src, folderID, fileInfo.Size())
|
||||||
folderID, err := o.loadIDByPath(path.Dir(target))
|
} else {
|
||||||
if err != nil {
|
isOk, err = o.upBig(ctx, src, folderID, fileInfo.Size())
|
||||||
return false, err
|
|
||||||
}
|
}
|
||||||
apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/createUploadSession", url.PathEscape(folderID), fileName)
|
return isOk, err
|
||||||
sessionCreationRequestInside := NewUploadSessionCreationRequest{
|
|
||||||
ConflictBehavior: "rename",
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionCreationRequest := struct {
|
|
||||||
Item NewUploadSessionCreationRequest `json:"item"`
|
|
||||||
DeferCommit bool `json:"deferCommit"`
|
|
||||||
}{sessionCreationRequestInside, false}
|
|
||||||
|
|
||||||
sessionCreationReq, err := o.client.NewRequest("POST", apiURL, sessionCreationRequest)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var sessionCreationResp *NewUploadSessionCreationResponse
|
|
||||||
err = o.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)
|
|
||||||
httpClient := http.Client{
|
|
||||||
Timeout: time.Minute * 10,
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
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 := o.NewSessionFileUploadRequest(fileSessionUploadUrl, splitNow*sizePerSplit, fileSize, bytes.NewReader(buffer))
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
res, err := httpClient.Do(sessionFileUploadReq)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if res.StatusCode != 201 && res.StatusCode != 202 && res.StatusCode != 200 {
|
|
||||||
data, _ := io.ReadAll(res.Body)
|
|
||||||
res.Body.Close()
|
|
||||||
return false, errors.New(string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o oneDriveClient) Download(src, target string) (bool, error) {
|
func (o oneDriveClient) Download(src, target string) (bool, error) {
|
||||||
@ -264,38 +192,48 @@ func (o *oneDriveClient) loadIDByPath(path string) (string, error) {
|
|||||||
return driveItem.Id, nil
|
return driveItem.Id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshToken(oldToken string) (string, error) {
|
func RefreshToken(grantType, grantCode string) (string, string, error) {
|
||||||
data := url.Values{}
|
data := url.Values{}
|
||||||
data.Set("client_id", global.CONF.System.OneDriveID)
|
data.Set("client_id", global.CONF.System.OneDriveID)
|
||||||
data.Set("client_secret", global.CONF.System.OneDriveSc)
|
data.Set("client_secret", global.CONF.System.OneDriveSc)
|
||||||
data.Set("grant_type", "refresh_token")
|
data.Set("grant_type", "refresh_token")
|
||||||
data.Set("refresh_token", oldToken)
|
if grantType == "refresh_token" {
|
||||||
|
data.Set("grant_type", "refresh_token")
|
||||||
|
data.Set("refresh_token", grantCode)
|
||||||
|
} else {
|
||||||
|
data.Set("grant_type", "authorization_code")
|
||||||
|
data.Set("code", grantCode)
|
||||||
|
}
|
||||||
data.Set("redirect_uri", constant.OneDriveRedirectURI)
|
data.Set("redirect_uri", constant.OneDriveRedirectURI)
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
req, err := http.NewRequest("POST", "https://login.microsoftonline.com/common/oauth2/v2.0/token", strings.NewReader(data.Encode()))
|
req, err := http.NewRequest("POST", "https://login.microsoftonline.com/common/oauth2/v2.0/token", strings.NewReader(data.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("new http post client for access token failed, err: %v", err)
|
return "", "", fmt.Errorf("new http post client for access token failed, err: %v", err)
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("request for access token failed, err: %v", err)
|
return "", "", fmt.Errorf("request for access token failed, err: %v", err)
|
||||||
}
|
}
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("read data from response body failed, err: %v", err)
|
return "", "", fmt.Errorf("read data from response body failed, err: %v", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
tokenMap := map[string]interface{}{}
|
tokenMap := map[string]interface{}{}
|
||||||
if err := json.Unmarshal(respBody, &tokenMap); err != nil {
|
if err := json.Unmarshal(respBody, &tokenMap); err != nil {
|
||||||
return "", fmt.Errorf("unmarshal data from response body failed, err: %v", err)
|
return "", "", fmt.Errorf("unmarshal data from response body failed, err: %v", err)
|
||||||
}
|
}
|
||||||
accessToken, ok := tokenMap["access_token"].(string)
|
accessToken, ok := tokenMap["access_token"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", errors.New("no such access token in response")
|
return "", "", errors.New("no such access token in response")
|
||||||
}
|
}
|
||||||
return accessToken, nil
|
refreshToken, ok := tokenMap["refresh_token"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", "", errors.New("no such access token in response")
|
||||||
|
}
|
||||||
|
return accessToken, refreshToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *oneDriveClient) createFolder(parent string) error {
|
func (o *oneDriveClient) createFolder(parent string) error {
|
||||||
@ -355,3 +293,89 @@ func (o *oneDriveClient) NewSessionFileUploadRequest(absoluteUrl string, grandOf
|
|||||||
|
|
||||||
return req, err
|
return req, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *oneDriveClient) upSmall(ctx context.Context, srcPath, folderID string, fileSize int64) (bool, error) {
|
||||||
|
file, err := os.Open(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
buffer := make([]byte, fileSize)
|
||||||
|
_, _ = file.Read(buffer)
|
||||||
|
fileReader := bytes.NewReader(buffer)
|
||||||
|
apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/content?@microsoft.graph.conflictBehavior=rename", url.PathEscape(folderID), path.Base(srcPath))
|
||||||
|
|
||||||
|
mimeType := files.GetMimeType(srcPath)
|
||||||
|
req, err := o.client.NewFileUploadRequest(apiURL, mimeType, fileReader)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
var response *DriveItem
|
||||||
|
if err := o.client.Do(context.Background(), req, false, &response); err != nil {
|
||||||
|
return false, fmt.Errorf("do request for list failed, err: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println(response)
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *oneDriveClient) upBig(ctx context.Context, srcPath, folderID string, fileSize int64) (bool, error) {
|
||||||
|
file, err := os.Open(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
apiURL := fmt.Sprintf("me/drive/items/%s:/%s:/createUploadSession", url.PathEscape(folderID), path.Base(srcPath))
|
||||||
|
sessionCreationRequestInside := NewUploadSessionCreationRequest{
|
||||||
|
ConflictBehavior: "rename",
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCreationRequest := struct {
|
||||||
|
Item NewUploadSessionCreationRequest `json:"item"`
|
||||||
|
DeferCommit bool `json:"deferCommit"`
|
||||||
|
}{sessionCreationRequestInside, false}
|
||||||
|
|
||||||
|
sessionCreationReq, err := o.client.NewRequest("POST", apiURL, sessionCreationRequest)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionCreationResp *NewUploadSessionCreationResponse
|
||||||
|
err = o.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 := o.NewSessionFileUploadRequest(fileSessionUploadUrl, splitNow*sizePerSplit, fileSize, bytes.NewReader(buffer))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err := o.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
|
||||||
|
}
|
||||||
|
@ -97,6 +97,10 @@ func (s s3Client) Delete(path string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s s3Client) Upload(src, target string) (bool, error) {
|
func (s s3Client) Upload(src, target string) (bool, error) {
|
||||||
|
fileInfo, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
file, err := os.Open(src)
|
file, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -104,6 +108,9 @@ func (s s3Client) Upload(src, target string) (bool, error) {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
uploader := s3manager.NewUploader(&s.Sess)
|
uploader := s3manager.NewUploader(&s.Sess)
|
||||||
|
if fileInfo.Size() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
|
||||||
|
uploader.PartSize = fileInfo.Size() / (s3manager.MaxUploadParts - 1)
|
||||||
|
}
|
||||||
if _, err := uploader.Upload(&s3manager.UploadInput{
|
if _, err := uploader.Upload(&s3manager.UploadInput{
|
||||||
Bucket: aws.String(s.bucket),
|
Bucket: aws.String(s.bucket),
|
||||||
Key: aws.String(target),
|
Key: aws.String(target),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@ -56,33 +56,14 @@ func (s sftpClient) Upload(src, target string) (bool, error) {
|
|||||||
}
|
}
|
||||||
defer srcFile.Close()
|
defer srcFile.Close()
|
||||||
|
|
||||||
targetFilePath := s.bucket + "/" + target
|
dstFile, err := client.Create(path.Join(s.bucket, target))
|
||||||
targetDir, _ := path.Split(targetFilePath)
|
|
||||||
if _, err = client.Stat(targetDir); err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
if err = client.MkdirAll(targetDir); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dstFile, err := client.Create(targetFilePath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer dstFile.Close()
|
defer dstFile.Close()
|
||||||
|
|
||||||
reader := bufio.NewReaderSize(srcFile, 128*1024*1024)
|
if _, err := io.Copy(dstFile, srcFile); err != nil {
|
||||||
for {
|
return false, err
|
||||||
chunk, err := reader.Peek(8 * 1024 * 1024)
|
|
||||||
if len(chunk) != 0 {
|
|
||||||
_, _ = dstFile.Write(chunk)
|
|
||||||
_, _ = reader.Discard(len(chunk))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -103,6 +84,7 @@ func (s sftpClient) Download(src, target string) (bool, error) {
|
|||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|
||||||
srcFile, err := client.Open(s.bucket + "/" + src)
|
srcFile, err := client.Open(s.bucket + "/" + src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -121,7 +103,7 @@ func (s sftpClient) Download(src, target string) (bool, error) {
|
|||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sftpClient) Exist(path string) (bool, error) {
|
func (s sftpClient) Exist(filePath string) (bool, error) {
|
||||||
sshClient, err := ssh.Dial("tcp", s.connInfo, s.config)
|
sshClient, err := ssh.Dial("tcp", s.connInfo, s.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -133,7 +115,7 @@ func (s sftpClient) Exist(path string) (bool, error) {
|
|||||||
defer client.Close()
|
defer client.Close()
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|
||||||
srcFile, err := client.Open(s.bucket + "/" + path)
|
srcFile, err := client.Open(path.Join(s.bucket, filePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
@ -145,7 +127,7 @@ func (s sftpClient) Exist(path string) (bool, error) {
|
|||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sftpClient) Size(path string) (int64, error) {
|
func (s sftpClient) Size(filePath string) (int64, error) {
|
||||||
sshClient, err := ssh.Dial("tcp", s.connInfo, s.config)
|
sshClient, err := ssh.Dial("tcp", s.connInfo, s.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -157,7 +139,7 @@ func (s sftpClient) Size(path string) (int64, error) {
|
|||||||
defer client.Close()
|
defer client.Close()
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|
||||||
files, err := client.Stat(s.bucket + "/" + path)
|
files, err := client.Stat(path.Join(s.bucket, filePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -176,8 +158,7 @@ func (s sftpClient) Delete(filePath string) (bool, error) {
|
|||||||
defer client.Close()
|
defer client.Close()
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|
||||||
targetFilePath := s.bucket + "/" + filePath
|
if err := client.Remove(path.Join(s.bucket, filePath)); err != nil {
|
||||||
if err := client.Remove(targetFilePath); err != nil {
|
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -195,7 +176,7 @@ func (s sftpClient) ListObjects(prefix string) ([]string, error) {
|
|||||||
defer client.Close()
|
defer client.Close()
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|
||||||
files, err := client.ReadDir(s.bucket + "/" + prefix)
|
files, err := client.ReadDir(path.Join(s.bucket, prefix))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,9 @@ export const handleRecover = (params: Backup.Recover) => {
|
|||||||
export const handleRecoverByUpload = (params: Backup.Recover) => {
|
export const handleRecoverByUpload = (params: Backup.Recover) => {
|
||||||
return http.post(`/settings/backup/recover/byupload`, params, TimeoutEnum.T_1D);
|
return http.post(`/settings/backup/recover/byupload`, params, TimeoutEnum.T_1D);
|
||||||
};
|
};
|
||||||
|
export const refreshOneDrive = () => {
|
||||||
|
return http.post(`/settings/backup/refresh/onedrive`, {});
|
||||||
|
};
|
||||||
export const downloadBackupRecord = (params: Backup.RecordDownload) => {
|
export const downloadBackupRecord = (params: Backup.RecordDownload) => {
|
||||||
return http.post<string>(`/settings/backup/record/download`, params, TimeoutEnum.T_10M);
|
return http.post<string>(`/settings/backup/record/download`, params, TimeoutEnum.T_10M);
|
||||||
};
|
};
|
||||||
|
@ -1241,6 +1241,8 @@ const message = {
|
|||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
WebDAV: 'WebDAV',
|
WebDAV: 'WebDAV',
|
||||||
OneDrive: 'Microsoft OneDrive',
|
OneDrive: 'Microsoft OneDrive',
|
||||||
|
refreshTime: 'Token Refresh Time',
|
||||||
|
refreshStatus: 'Token Refresh Status',
|
||||||
backupDir: 'Backup dir',
|
backupDir: 'Backup dir',
|
||||||
codeWarning: 'The current authorization code format is incorrect, please confirm again!',
|
codeWarning: 'The current authorization code format is incorrect, please confirm again!',
|
||||||
isCN: 'Domestic version (not supported at the moment)',
|
isCN: 'Domestic version (not supported at the moment)',
|
||||||
|
@ -1165,6 +1165,8 @@ const message = {
|
|||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
WebDAV: 'WebDAV',
|
WebDAV: 'WebDAV',
|
||||||
OneDrive: '微軟 OneDrive',
|
OneDrive: '微軟 OneDrive',
|
||||||
|
refreshTime: '令牌刷新時間',
|
||||||
|
refreshStatus: '令牌刷新狀態',
|
||||||
codeWarning: '當前授權碼格式錯誤,請重新確認!',
|
codeWarning: '當前授權碼格式錯誤,請重新確認!',
|
||||||
backupDir: '備份路徑',
|
backupDir: '備份路徑',
|
||||||
isCN: '國內版 (暫不支持)',
|
isCN: '國內版 (暫不支持)',
|
||||||
|
@ -1166,6 +1166,8 @@ const message = {
|
|||||||
SFTP: 'SFTP',
|
SFTP: 'SFTP',
|
||||||
WebDAV: 'WebDAV',
|
WebDAV: 'WebDAV',
|
||||||
OneDrive: '微软 OneDrive',
|
OneDrive: '微软 OneDrive',
|
||||||
|
refreshTime: '令牌刷新时间',
|
||||||
|
refreshStatus: '令牌刷新状态',
|
||||||
codeWarning: '当前授权码格式错误,请重新确认!',
|
codeWarning: '当前授权码格式错误,请重新确认!',
|
||||||
backupDir: '备份路径',
|
backupDir: '备份路径',
|
||||||
isCN: '国内版 (暂不支持)',
|
isCN: '国内版 (暂不支持)',
|
||||||
|
@ -212,7 +212,7 @@
|
|||||||
round
|
round
|
||||||
plain
|
plain
|
||||||
:disabled="oneDriveData.id === 0"
|
:disabled="oneDriveData.id === 0"
|
||||||
@click="onOpenDialog('edit', 'SFTP', oneDriveData)"
|
@click="onOpenDialog('edit', 'OneDrive', oneDriveData)"
|
||||||
>
|
>
|
||||||
{{ $t('commons.button.edit') }}
|
{{ $t('commons.button.edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -227,6 +227,26 @@
|
|||||||
<span v-if="oneDriveData.backupPath">{{ oneDriveData.backupPath }}</span>
|
<span v-if="oneDriveData.backupPath">{{ oneDriveData.backupPath }}</span>
|
||||||
<span v-else>{{ $t('setting.unSetting') }}</span>
|
<span v-else>{{ $t('setting.unSetting') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.refreshTime')">
|
||||||
|
<span>{{ oneDriveData.varsJson['refresh_time'] }}</span>
|
||||||
|
<el-button @click="refreshToken" link type="primary" class="ml-2">
|
||||||
|
{{ $t('commons.button.refresh') }}
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.refreshStatus')">
|
||||||
|
<el-tag v-if="oneDriveData.varsJson['refresh_status'] === 'Success'" type="success">
|
||||||
|
{{ $t('commons.status.success') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tooltip
|
||||||
|
v-if="oneDriveData.varsJson['refresh_status'] === 'Failed'"
|
||||||
|
:content="oneDriveData.varsJson['refresh_msg']"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<el-tag type="danger">
|
||||||
|
{{ $t('commons.status.failed') }}
|
||||||
|
</el-tag>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
{{ dateFormat(0, 0, oneDriveData.createdAt) }}
|
{{ dateFormat(0, 0, oneDriveData.createdAt) }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -430,7 +450,7 @@
|
|||||||
import { dateFormat } from '@/utils/util';
|
import { dateFormat } from '@/utils/util';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import OpDialog from '@/components/del-dialog/index.vue';
|
import OpDialog from '@/components/del-dialog/index.vue';
|
||||||
import { getBackupList, deleteBackup } from '@/api/modules/setting';
|
import { getBackupList, deleteBackup, refreshOneDrive } from '@/api/modules/setting';
|
||||||
import localDialog from '@/views/setting/backup-account/local/index.vue';
|
import localDialog from '@/views/setting/backup-account/local/index.vue';
|
||||||
import s3Dialog from '@/views/setting/backup-account/s3/index.vue';
|
import s3Dialog from '@/views/setting/backup-account/s3/index.vue';
|
||||||
import ossDialog from '@/views/setting/backup-account/oss/index.vue';
|
import ossDialog from '@/views/setting/backup-account/oss/index.vue';
|
||||||
@ -536,7 +556,9 @@ const oneDriveData = ref<Backup.BackupInfo>({
|
|||||||
backupPath: '',
|
backupPath: '',
|
||||||
vars: '',
|
vars: '',
|
||||||
varsJson: {
|
varsJson: {
|
||||||
redirectURI: '',
|
refresh_msg: '',
|
||||||
|
refresh_time: '',
|
||||||
|
refresh_status: '',
|
||||||
},
|
},
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
});
|
});
|
||||||
@ -680,6 +702,11 @@ const onOpenDialog = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const refreshToken = async () => {
|
||||||
|
await refreshOneDrive();
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user