mirror of
https://github.com/gilbertchen/duplicacy
synced 2025-12-06 00:03:38 +00:00
Merge pull request #632 from sevimo123/custom_odb_creds
CLI support for custom credentials for OneDrive (client_id/client_secret)
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
package duplicacy
|
package duplicacy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -39,6 +40,7 @@ type OneDriveClient struct {
|
|||||||
|
|
||||||
TokenFile string
|
TokenFile string
|
||||||
Token *oauth2.Token
|
Token *oauth2.Token
|
||||||
|
OAConfig *oauth2.Config
|
||||||
TokenLock *sync.Mutex
|
TokenLock *sync.Mutex
|
||||||
|
|
||||||
IsConnected bool
|
IsConnected bool
|
||||||
@@ -49,7 +51,7 @@ type OneDriveClient struct {
|
|||||||
APIURL string
|
APIURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOneDriveClient(tokenFile string, isBusiness bool) (*OneDriveClient, error) {
|
func NewOneDriveClient(tokenFile string, isBusiness bool, client_id string, client_secret string) (*OneDriveClient, error) {
|
||||||
|
|
||||||
description, err := ioutil.ReadFile(tokenFile)
|
description, err := ioutil.ReadFile(tokenFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -65,10 +67,25 @@ func NewOneDriveClient(tokenFile string, isBusiness bool) (*OneDriveClient, erro
|
|||||||
HTTPClient: http.DefaultClient,
|
HTTPClient: http.DefaultClient,
|
||||||
TokenFile: tokenFile,
|
TokenFile: tokenFile,
|
||||||
Token: token,
|
Token: token,
|
||||||
|
OAConfig: nil,
|
||||||
TokenLock: &sync.Mutex{},
|
TokenLock: &sync.Mutex{},
|
||||||
IsBusiness: isBusiness,
|
IsBusiness: isBusiness,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client_id != "") {
|
||||||
|
oneOauthConfig := oauth2.Config{
|
||||||
|
ClientID: client_id,
|
||||||
|
ClientSecret: client_secret,
|
||||||
|
Scopes: []string{"Files.ReadWrite", "offline_access"},
|
||||||
|
Endpoint: oauth2.Endpoint{
|
||||||
|
AuthURL: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
||||||
|
TokenURL: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
client.OAConfig = &oneOauthConfig
|
||||||
|
}
|
||||||
|
|
||||||
if isBusiness {
|
if isBusiness {
|
||||||
client.RefreshTokenURL = "https://duplicacy.com/odb_refresh"
|
client.RefreshTokenURL = "https://duplicacy.com/odb_refresh"
|
||||||
client.APIURL = "https://graph.microsoft.com/v1.0/me"
|
client.APIURL = "https://graph.microsoft.com/v1.0/me"
|
||||||
@@ -218,15 +235,25 @@ func (client *OneDriveClient) RefreshToken(force bool) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
readCloser, _, err := client.call(client.RefreshTokenURL, "POST", client.Token, "")
|
if (client.OAConfig == nil) {
|
||||||
if err != nil {
|
readCloser, _, err := client.call(client.RefreshTokenURL, "POST", client.Token, "")
|
||||||
return fmt.Errorf("failed to refresh the access token: %v", err)
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("failed to refresh the access token: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
defer readCloser.Close()
|
defer readCloser.Close()
|
||||||
|
|
||||||
if err = json.NewDecoder(readCloser).Decode(client.Token); err != nil {
|
if err = json.NewDecoder(readCloser).Decode(client.Token); err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx := context.Background()
|
||||||
|
tokenSource := client.OAConfig.TokenSource(ctx, client.Token)
|
||||||
|
token, err := tokenSource.Token()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to refresh the access token: %v", err)
|
||||||
|
}
|
||||||
|
client.Token = token
|
||||||
}
|
}
|
||||||
|
|
||||||
description, err := json.Marshal(client.Token)
|
description, err := json.Marshal(client.Token)
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ type OneDriveStorage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateOneDriveStorage creates an OneDrive storage object.
|
// CreateOneDriveStorage creates an OneDrive storage object.
|
||||||
func CreateOneDriveStorage(tokenFile string, isBusiness bool, storagePath string, threads int) (storage *OneDriveStorage, err error) {
|
func CreateOneDriveStorage(tokenFile string, isBusiness bool, storagePath string, threads int, client_id string, client_secret string) (storage *OneDriveStorage, err error) {
|
||||||
|
|
||||||
for len(storagePath) > 0 && storagePath[len(storagePath)-1] == '/' {
|
for len(storagePath) > 0 && storagePath[len(storagePath)-1] == '/' {
|
||||||
storagePath = storagePath[:len(storagePath)-1]
|
storagePath = storagePath[:len(storagePath)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := NewOneDriveClient(tokenFile, isBusiness)
|
client, err := NewOneDriveClient(tokenFile, isBusiness, client_id, client_secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -647,12 +647,28 @@ func CreateStorage(preference Preference, resetPassword bool, threads int) (stor
|
|||||||
storagePath := matched[3] + matched[4]
|
storagePath := matched[3] + matched[4]
|
||||||
prompt := fmt.Sprintf("Enter the path of the OneDrive token file (downloadable from https://duplicacy.com/one_start):")
|
prompt := fmt.Sprintf("Enter the path of the OneDrive token file (downloadable from https://duplicacy.com/one_start):")
|
||||||
tokenFile := GetPassword(preference, matched[1] + "_token", prompt, true, resetPassword)
|
tokenFile := GetPassword(preference, matched[1] + "_token", prompt, true, resetPassword)
|
||||||
oneDriveStorage, err := CreateOneDriveStorage(tokenFile, matched[1] == "odb", storagePath, threads)
|
|
||||||
|
// client_id, just like tokenFile, can be stored in preferences
|
||||||
|
//prompt = fmt.Sprintf("Enter client_id for custom Azure app (if empty will use duplicacy.com one):")
|
||||||
|
client_id := GetPasswordFromPreference(preference, matched[1] + "_client_id")
|
||||||
|
client_secret := ""
|
||||||
|
|
||||||
|
if client_id != "" {
|
||||||
|
// client_secret should go into keyring
|
||||||
|
prompt = fmt.Sprintf("Enter client_secret for custom Azure app (if empty will use duplicacy.com one):")
|
||||||
|
client_secret = GetPassword(preference, matched[1] + "_client_secret", prompt, true, resetPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
oneDriveStorage, err := CreateOneDriveStorage(tokenFile, matched[1] == "odb", storagePath, threads, client_id, client_secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LOG_ERROR("STORAGE_CREATE", "Failed to load the OneDrive storage at %s: %v", storageURL, err)
|
LOG_ERROR("STORAGE_CREATE", "Failed to load the OneDrive storage at %s: %v", storageURL, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
SavePassword(preference, matched[1] + "_token", tokenFile)
|
SavePassword(preference, matched[1] + "_token", tokenFile)
|
||||||
|
if client_id != "" {
|
||||||
|
SavePassword(preference, matched[1] + "_client_secret", client_secret)
|
||||||
|
}
|
||||||
return oneDriveStorage
|
return oneDriveStorage
|
||||||
} else if matched[1] == "hubic" {
|
} else if matched[1] == "hubic" {
|
||||||
storagePath := matched[3] + matched[4]
|
storagePath := matched[3] + matched[4]
|
||||||
|
|||||||
Reference in New Issue
Block a user