mirror of
https://github.com/rclone/rclone.git
synced 2025-01-11 08:49:37 +01:00
jottacloud: Use token auth for all API requests
Don't store password anymore
This commit is contained in:
parent
92fa30a787
commit
88592a1779
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/ncw/rclone/backend/jottacloud/api"
|
"github.com/ncw/rclone/backend/jottacloud/api"
|
||||||
"github.com/ncw/rclone/fs"
|
"github.com/ncw/rclone/fs"
|
||||||
"github.com/ncw/rclone/fs/accounting"
|
"github.com/ncw/rclone/fs/accounting"
|
||||||
|
"github.com/ncw/rclone/fs/config"
|
||||||
"github.com/ncw/rclone/fs/config/configmap"
|
"github.com/ncw/rclone/fs/config/configmap"
|
||||||
"github.com/ncw/rclone/fs/config/configstruct"
|
"github.com/ncw/rclone/fs/config/configstruct"
|
||||||
"github.com/ncw/rclone/fs/config/obscure"
|
"github.com/ncw/rclone/fs/config/obscure"
|
||||||
@ -47,7 +48,6 @@ const (
|
|||||||
rcloneClientID = "nibfk8biu12ju7hpqomr8b1e40"
|
rcloneClientID = "nibfk8biu12ju7hpqomr8b1e40"
|
||||||
rcloneEncryptedClientSecret = "Vp8eAv7eVElMnQwN-kgU9cbhgApNDaMqWdlDi5qFydlQoji4JBxrGMF2"
|
rcloneEncryptedClientSecret = "Vp8eAv7eVElMnQwN-kgU9cbhgApNDaMqWdlDi5qFydlQoji4JBxrGMF2"
|
||||||
configUsername = "user"
|
configUsername = "user"
|
||||||
configPassword = "pass"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -70,23 +70,31 @@ func init() {
|
|||||||
Description: "JottaCloud",
|
Description: "JottaCloud",
|
||||||
NewFs: NewFs,
|
NewFs: NewFs,
|
||||||
Config: func(name string, m configmap.Mapper) {
|
Config: func(name string, m configmap.Mapper) {
|
||||||
|
tokenString, ok := m.Get("token")
|
||||||
|
if ok && tokenString != "" {
|
||||||
|
fmt.Printf("Already have a token - refresh?\n")
|
||||||
|
if !config.Confirm() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
username, ok := m.Get(configUsername)
|
username, ok := m.Get(configUsername)
|
||||||
if !ok {
|
if !ok {
|
||||||
fs.Errorf(nil, "No username defined")
|
fs.Errorf(nil, "No username defined")
|
||||||
}
|
}
|
||||||
password, ok := m.Get(configPassword)
|
// Password
|
||||||
if !ok {
|
password := config.GetPassword("Your Jottacloud password is only required during config and will not be stored.")
|
||||||
fs.Errorf(nil, "No username defined")
|
if password == "" {
|
||||||
|
fs.Errorf(nil, "Password must not be empty!")
|
||||||
}
|
}
|
||||||
password = obscure.MustReveal(password)
|
|
||||||
srv := rest.NewClient(fshttp.NewClient(fs.Config))
|
|
||||||
|
|
||||||
|
srv := rest.NewClient(fshttp.NewClient(fs.Config))
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("grant_type", "PASSWORD")
|
values.Set("grant_type", "PASSWORD")
|
||||||
values.Set("password", password)
|
values.Set("password", password)
|
||||||
values.Set("username", username)
|
values.Set("username", username)
|
||||||
values.Set("client_id", rcloneClientID)
|
values.Set("client_id", oauthConfig.ClientID)
|
||||||
values.Set("client_secret", obscure.MustReveal(rcloneEncryptedClientSecret))
|
values.Set("client_secret", oauthConfig.ClientSecret)
|
||||||
opts := rest.Opts{
|
opts := rest.Opts{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
RootURL: oauthConfig.Endpoint.AuthURL,
|
RootURL: oauthConfig.Endpoint.AuthURL,
|
||||||
@ -119,11 +127,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
Options: []fs.Option{{
|
Options: []fs.Option{{
|
||||||
Name: configUsername,
|
Name: configUsername,
|
||||||
Help: "User Name",
|
Help: "User Name:",
|
||||||
}, {
|
|
||||||
Name: configPassword,
|
|
||||||
Help: "Password.",
|
|
||||||
IsPassword: true,
|
|
||||||
}, {
|
}, {
|
||||||
Name: "mountpoint",
|
Name: "mountpoint",
|
||||||
Help: "The mountpoint to use.",
|
Help: "The mountpoint to use.",
|
||||||
@ -162,7 +166,6 @@ func init() {
|
|||||||
// Options defines the configuration for this backend
|
// Options defines the configuration for this backend
|
||||||
type Options struct {
|
type Options struct {
|
||||||
User string `config:"user"`
|
User string `config:"user"`
|
||||||
Pass string `config:"pass"`
|
|
||||||
Mountpoint string `config:"mountpoint"`
|
Mountpoint string `config:"mountpoint"`
|
||||||
MD5MemoryThreshold fs.SizeSuffix `config:"md5_memory_limit"`
|
MD5MemoryThreshold fs.SizeSuffix `config:"md5_memory_limit"`
|
||||||
HardDelete bool `config:"hard_delete"`
|
HardDelete bool `config:"hard_delete"`
|
||||||
@ -336,15 +339,6 @@ func (o *Object) filePath() string {
|
|||||||
return o.fs.filePath(o.remote)
|
return o.fs.filePath(o.remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummyClose is required for the grantTypeFilter below
|
|
||||||
// because http.Request.Body needs to be a io.ReadCloser
|
|
||||||
// and bytes.NewReader is only a io.Reader
|
|
||||||
type dummyCloser struct {
|
|
||||||
io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dummyCloser) Close() error { return nil }
|
|
||||||
|
|
||||||
// Jottacloud requires the grant_type 'refresh_token' string
|
// Jottacloud requires the grant_type 'refresh_token' string
|
||||||
// to be uppercase and throws a 400 Bad Request if we use the
|
// to be uppercase and throws a 400 Bad Request if we use the
|
||||||
// lower case used by the oauth2 module
|
// lower case used by the oauth2 module
|
||||||
@ -364,7 +358,7 @@ func grantTypeFilter(req *http.Request) {
|
|||||||
refreshBody = []byte(strings.Replace(string(refreshBody), "grant_type=refresh_token", "grant_type=REFRESH_TOKEN", 1))
|
refreshBody = []byte(strings.Replace(string(refreshBody), "grant_type=refresh_token", "grant_type=REFRESH_TOKEN", 1))
|
||||||
|
|
||||||
// set the new ReadCloser (with a dummy Close())
|
// set the new ReadCloser (with a dummy Close())
|
||||||
req.Body = &dummyCloser{bytes.NewReader(refreshBody)}
|
req.Body = ioutil.NopCloser(bytes.NewReader(refreshBody))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,14 +374,6 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
|||||||
rootIsDir := strings.HasSuffix(root, "/")
|
rootIsDir := strings.HasSuffix(root, "/")
|
||||||
root = parsePath(root)
|
root = parsePath(root)
|
||||||
|
|
||||||
if opt.Pass != "" {
|
|
||||||
var err error
|
|
||||||
opt.Pass, err = obscure.Reveal(opt.Pass)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "couldn't decrypt password")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the oauth client for the api servers needs
|
// the oauth client for the api servers needs
|
||||||
// a filter to fix the grant_type issues (see above)
|
// a filter to fix the grant_type issues (see above)
|
||||||
baseClient := fshttp.NewClient(fs.Config)
|
baseClient := fshttp.NewClient(fs.Config)
|
||||||
@ -451,7 +437,6 @@ func NewFs(name, root string, m configmap.Mapper) (fs.Fs, error) {
|
|||||||
// return an error with an fs which points to the parent
|
// return an error with an fs which points to the parent
|
||||||
return f, fs.ErrorIsFile
|
return f, fs.ErrorIsFile
|
||||||
}
|
}
|
||||||
|
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1226,7 +1211,7 @@ func (o *Object) Update(in io.Reader, src fs.ObjectInfo, options ...fs.OpenOptio
|
|||||||
o.modTime = time.Unix(result.Modified/1000, 0)
|
o.modTime = time.Unix(result.Modified/1000, 0)
|
||||||
} else {
|
} else {
|
||||||
// If the file state is COMPLETE we don't need to upload it because the file was allready found but we still ned to update our metadata
|
// If the file state is COMPLETE we don't need to upload it because the file was allready found but we still ned to update our metadata
|
||||||
o.readMetaData(true)
|
return o.readMetaData(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user