forked from TrueCloudLab/rclone
Add easier headless configuration.
This will allow setting up a remote with copy&paste of values to a headless machine. It will allow copy+pasting a token into the configuration. This requires rclone to be on a machine with a proper browser. Custom client id and secrets are supported. To test token generation, use `rclone auth "fs type"`.
This commit is contained in:
parent
c245183101
commit
bcbd30bb8a
9 changed files with 120 additions and 13 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
|
@ -25,6 +26,9 @@ const (
|
|||
// ConfigClientSecret is the config key used to store the client secret
|
||||
ConfigClientSecret = "client_secret"
|
||||
|
||||
// ConfigAutomatic indicates that we want non-interactive configuration
|
||||
ConfigAutomatic = "config_automatic"
|
||||
|
||||
// TitleBarRedirectURL is the OAuth2 redirect URL to use when the authorization
|
||||
// code should be returned in the title bar of the browser, with the page text
|
||||
// prompting the user to copy the code and paste it in the application.
|
||||
|
@ -147,16 +151,21 @@ func Context() context.Context {
|
|||
}
|
||||
|
||||
// overrideCredentials sets the ClientID and ClientSecret from the
|
||||
// config file if they are not blank
|
||||
func overrideCredentials(name string, config *oauth2.Config) {
|
||||
// config file if they are not blank.
|
||||
// If any value is overridden, true is returned.
|
||||
func overrideCredentials(name string, config *oauth2.Config) bool {
|
||||
changed := false
|
||||
ClientID := fs.ConfigFile.MustValue(name, ConfigClientID)
|
||||
if ClientID != "" {
|
||||
config.ClientID = ClientID
|
||||
changed = true
|
||||
}
|
||||
ClientSecret := fs.ConfigFile.MustValue(name, ConfigClientSecret)
|
||||
if ClientSecret != "" {
|
||||
config.ClientSecret = ClientSecret
|
||||
changed = true
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
// NewClient gets a token from the config file and configures a Client
|
||||
|
@ -185,8 +194,10 @@ func NewClient(name string, config *oauth2.Config) (*http.Client, error) {
|
|||
// Config does the initial creation of the token
|
||||
//
|
||||
// It may run an internal webserver to receive the results
|
||||
func Config(name string, config *oauth2.Config) error {
|
||||
overrideCredentials(name, config)
|
||||
func Config(id, name string, config *oauth2.Config) error {
|
||||
changed := overrideCredentials(name, config)
|
||||
automatic := fs.ConfigFile.MustValue(name, ConfigAutomatic) != ""
|
||||
|
||||
// See if already have a token
|
||||
tokenString := fs.ConfigFile.MustValue(name, "token")
|
||||
if tokenString != "" {
|
||||
|
@ -201,11 +212,42 @@ func Config(name string, config *oauth2.Config) error {
|
|||
switch config.RedirectURL {
|
||||
case RedirectURL, RedirectPublicURL, RedirectLocalhostURL:
|
||||
useWebServer = true
|
||||
case TitleBarRedirectURL:
|
||||
if automatic {
|
||||
break
|
||||
}
|
||||
fmt.Printf("Use auto config?\n")
|
||||
fmt.Printf(" * Say Y if not sure\n")
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n")
|
||||
useWebServer = fs.Confirm()
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine\n")
|
||||
auto := fs.Confirm()
|
||||
if !auto {
|
||||
fmt.Printf("For this to work, you will need rclone available on a machine that has a web browser available.\n")
|
||||
fmt.Printf("Execute the following on your machine:\n")
|
||||
if changed {
|
||||
fmt.Printf("\trclone authorize %q %q %q\n", id, config.ClientID, config.ClientSecret)
|
||||
} else {
|
||||
fmt.Printf("\trclone authorize %q\n", id)
|
||||
}
|
||||
fmt.Println("Then paste the result below:")
|
||||
code := ""
|
||||
for code == "" {
|
||||
fmt.Printf("result> ")
|
||||
code = strings.TrimSpace(fs.ReadLine())
|
||||
}
|
||||
token := &oauth2.Token{}
|
||||
err := json.Unmarshal([]byte(code), token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return putToken(name, token)
|
||||
}
|
||||
case TitleBarRedirectURL:
|
||||
useWebServer = automatic
|
||||
if !automatic {
|
||||
fmt.Printf("Use auto config?\n")
|
||||
fmt.Printf(" * Say Y if not sure\n")
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n")
|
||||
useWebServer = fs.Confirm()
|
||||
}
|
||||
if useWebServer {
|
||||
// copy the config and set to use the internal webserver
|
||||
configCopy := *config
|
||||
|
@ -260,6 +302,15 @@ func Config(name string, config *oauth2.Config) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("Failed to get token: %v", err)
|
||||
}
|
||||
|
||||
// Print code if we do automatic retrieval
|
||||
if automatic {
|
||||
result, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to marshal token: %v", err)
|
||||
}
|
||||
fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste", result)
|
||||
}
|
||||
return putToken(name, token)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue