mirror of
https://github.com/rclone/rclone.git
synced 2024-11-29 03:48:27 +08:00
pcloud: fix oauth on European region "eapi.pcloud.com"
Pcloud appears to have opened up a new region and they are returning the hostname in the oauth callback, thus GET /?code=XXX&locationid=1&hostname=api.pcloud.com&state=XXX HTTP/1.1 GET /?code=XXX&locationid=2&hostname=eapi.pcloud.com&state=XXX HTTP/1.1 This isn't documented yet, however pCloud have confirmed that this is the correct interpretation. Rclone now reads the "hostname" parameter in the oauth callback and stores it in the config file. It uses it for all subequent API calls.
This commit is contained in:
parent
e6fdc3a932
commit
d4b2709fb0
|
@ -42,7 +42,7 @@ const (
|
||||||
minSleep = 10 * time.Millisecond
|
minSleep = 10 * time.Millisecond
|
||||||
maxSleep = 2 * time.Second
|
maxSleep = 2 * time.Second
|
||||||
decayConstant = 2 // bigger for slower decay, exponential
|
decayConstant = 2 // bigger for slower decay, exponential
|
||||||
rootURL = "https://api.pcloud.com"
|
defaultHostname = "api.pcloud.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
|
@ -51,8 +51,8 @@ var (
|
||||||
oauthConfig = &oauth2.Config{
|
oauthConfig = &oauth2.Config{
|
||||||
Scopes: nil,
|
Scopes: nil,
|
||||||
Endpoint: oauth2.Endpoint{
|
Endpoint: oauth2.Endpoint{
|
||||||
AuthURL: "https://my.pcloud.com/oauth2/authorize",
|
AuthURL: "https://my.pcloud.com/oauth2/authorize",
|
||||||
TokenURL: "https://api.pcloud.com/oauth2_token",
|
// TokenURL: "https://api.pcloud.com/oauth2_token", set by updateTokenURL
|
||||||
},
|
},
|
||||||
ClientID: rcloneClientID,
|
ClientID: rcloneClientID,
|
||||||
ClientSecret: obscure.MustReveal(rcloneEncryptedClientSecret),
|
ClientSecret: obscure.MustReveal(rcloneEncryptedClientSecret),
|
||||||
|
@ -60,17 +60,45 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Update the TokenURL with the actual hostname
|
||||||
|
func updateTokenURL(oauthConfig *oauth2.Config, hostname string) {
|
||||||
|
oauthConfig.Endpoint.TokenURL = "https://" + hostname + "/oauth2_token"
|
||||||
|
}
|
||||||
|
|
||||||
// Register with Fs
|
// Register with Fs
|
||||||
func init() {
|
func init() {
|
||||||
|
updateTokenURL(oauthConfig, defaultHostname)
|
||||||
fs.Register(&fs.RegInfo{
|
fs.Register(&fs.RegInfo{
|
||||||
Name: "pcloud",
|
Name: "pcloud",
|
||||||
Description: "Pcloud",
|
Description: "Pcloud",
|
||||||
NewFs: NewFs,
|
NewFs: NewFs,
|
||||||
Config: func(name string, m configmap.Mapper) {
|
Config: func(name string, m configmap.Mapper) {
|
||||||
|
optc := new(Options)
|
||||||
|
err := configstruct.Set(m, optc)
|
||||||
|
if err != nil {
|
||||||
|
fs.Errorf(nil, "Failed to read config: %v", err)
|
||||||
|
}
|
||||||
|
updateTokenURL(oauthConfig, optc.Hostname)
|
||||||
|
checkAuth := func(oauthConfig *oauth2.Config, auth *oauthutil.AuthResult) error {
|
||||||
|
if auth == nil || auth.Form == nil {
|
||||||
|
return errors.New("form not found in response")
|
||||||
|
}
|
||||||
|
hostname := auth.Form.Get("hostname")
|
||||||
|
if hostname == "" {
|
||||||
|
hostname = defaultHostname
|
||||||
|
}
|
||||||
|
// Save the hostname in the config
|
||||||
|
m.Set("hostname", hostname)
|
||||||
|
// Update the token URL
|
||||||
|
updateTokenURL(oauthConfig, hostname)
|
||||||
|
fs.Debugf(nil, "pcloud: got hostname %q", hostname)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
opt := oauthutil.Options{
|
opt := oauthutil.Options{
|
||||||
|
CheckAuth: checkAuth,
|
||||||
StateBlankOK: true, // pCloud seems to drop the state parameter now - see #4210
|
StateBlankOK: true, // pCloud seems to drop the state parameter now - see #4210
|
||||||
}
|
}
|
||||||
err := oauthutil.Config("pcloud", name, m, oauthConfig, &opt)
|
err = oauthutil.Config("pcloud", name, m, oauthConfig, &opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to configure token: %v", err)
|
log.Fatalf("Failed to configure token: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -96,6 +124,13 @@ func init() {
|
||||||
Help: "Fill in for rclone to use a non root folder as its starting point.",
|
Help: "Fill in for rclone to use a non root folder as its starting point.",
|
||||||
Default: "d0",
|
Default: "d0",
|
||||||
Advanced: true,
|
Advanced: true,
|
||||||
|
}, {
|
||||||
|
Name: "hostname",
|
||||||
|
Help: `Hostname to connect to.
|
||||||
|
|
||||||
|
This is normally set when rclone initially does the oauth connection.`,
|
||||||
|
Default: defaultHostname,
|
||||||
|
Advanced: true,
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -104,6 +139,7 @@ func init() {
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Enc encoder.MultiEncoder `config:"encoding"`
|
Enc encoder.MultiEncoder `config:"encoding"`
|
||||||
RootFolderID string `config:"root_folder_id"`
|
RootFolderID string `config:"root_folder_id"`
|
||||||
|
Hostname string `config:"hostname"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fs represents a remote pcloud
|
// Fs represents a remote pcloud
|
||||||
|
@ -253,12 +289,13 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to configure Pcloud")
|
return nil, errors.Wrap(err, "failed to configure Pcloud")
|
||||||
}
|
}
|
||||||
|
updateTokenURL(oauthConfig, opt.Hostname)
|
||||||
|
|
||||||
f := &Fs{
|
f := &Fs{
|
||||||
name: name,
|
name: name,
|
||||||
root: root,
|
root: root,
|
||||||
opt: *opt,
|
opt: *opt,
|
||||||
srv: rest.NewClient(oAuthClient).SetRoot(rootURL),
|
srv: rest.NewClient(oAuthClient).SetRoot("https://" + opt.Hostname),
|
||||||
pacer: fs.NewPacer(pacer.NewDefault(pacer.MinSleep(minSleep), pacer.MaxSleep(maxSleep), pacer.DecayConstant(decayConstant))),
|
pacer: fs.NewPacer(pacer.NewDefault(pacer.MinSleep(minSleep), pacer.MaxSleep(maxSleep), pacer.DecayConstant(decayConstant))),
|
||||||
}
|
}
|
||||||
f.features = (&fs.Features{
|
f.features = (&fs.Features{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user