1
0
mirror of https://github.com/rclone/rclone.git synced 2025-12-06 00:03:32 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
a9adc7007e build(deps): bump DavidAnson/markdownlint-cli2-action from 20 to 21
Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 20 to 21.
- [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases)
- [Commits](https://github.com/davidanson/markdownlint-cli2-action/compare/v20...v21)

---
updated-dependencies:
- dependency-name: DavidAnson/markdownlint-cli2-action
  dependency-version: '21'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-17 22:07:50 +00:00
9 changed files with 31 additions and 80 deletions

View File

@@ -283,7 +283,7 @@ jobs:
run: govulncheck ./... run: govulncheck ./...
- name: Check Markdown format - name: Check Markdown format
uses: DavidAnson/markdownlint-cli2-action@v20 uses: DavidAnson/markdownlint-cli2-action@v21
with: with:
globs: | globs: |
CONTRIBUTING.md CONTRIBUTING.md

View File

@@ -87,11 +87,13 @@ func init() {
Description: "Box", Description: "Box",
NewFs: NewFs, NewFs: NewFs,
Config: func(ctx context.Context, name string, m configmap.Mapper, config fs.ConfigIn) (*fs.ConfigOut, error) { Config: func(ctx context.Context, name string, m configmap.Mapper, config fs.ConfigIn) (*fs.ConfigOut, error) {
jsonFile, ok := m.Get("box_config_file")
boxSubType, boxSubTypeOk := m.Get("box_sub_type")
boxAccessToken, boxAccessTokenOk := m.Get("access_token") boxAccessToken, boxAccessTokenOk := m.Get("access_token")
var err error var err error
// If using box config.json, use JWT auth // If using box config.json, use JWT auth
if usesJWTAuth(m) { if ok && boxSubTypeOk && jsonFile != "" && boxSubType != "" {
err = refreshJWTToken(ctx, name, m) err = refreshJWTToken(ctx, jsonFile, boxSubType, name, m)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to configure token with jwt authentication: %w", err) return nil, fmt.Errorf("failed to configure token with jwt authentication: %w", err)
} }
@@ -112,11 +114,6 @@ func init() {
}, { }, {
Name: "box_config_file", Name: "box_config_file",
Help: "Box App config.json location\n\nLeave blank normally." + env.ShellExpandHelp, Help: "Box App config.json location\n\nLeave blank normally." + env.ShellExpandHelp,
}, {
Name: "config_credentials",
Help: "Box App config.json contents.\n\nLeave blank normally.",
Hide: fs.OptionHideBoth,
Sensitive: true,
}, { }, {
Name: "access_token", Name: "access_token",
Help: "Box App Primary Access Token\n\nLeave blank normally.", Help: "Box App Primary Access Token\n\nLeave blank normally.",
@@ -187,17 +184,9 @@ See: https://developer.box.com/guides/authentication/jwt/as-user/
}) })
} }
func usesJWTAuth(m configmap.Mapper) bool { func refreshJWTToken(ctx context.Context, jsonFile string, boxSubType string, name string, m configmap.Mapper) error {
jsonFile, okFile := m.Get("box_config_file") jsonFile = env.ShellExpand(jsonFile)
jsonFileCredentials, okCredentials := m.Get("config_credentials") boxConfig, err := getBoxConfig(jsonFile)
boxSubType, boxSubTypeOk := m.Get("box_sub_type")
return (okFile || okCredentials) && boxSubTypeOk && (jsonFile != "" || jsonFileCredentials != "") && boxSubType != ""
}
func refreshJWTToken(ctx context.Context, name string, m configmap.Mapper) error {
boxSubType, _ := m.Get("box_sub_type")
boxConfig, err := getBoxConfig(m)
if err != nil { if err != nil {
return fmt.Errorf("get box config: %w", err) return fmt.Errorf("get box config: %w", err)
} }
@@ -216,19 +205,12 @@ func refreshJWTToken(ctx context.Context, name string, m configmap.Mapper) error
return err return err
} }
func getBoxConfig(m configmap.Mapper) (boxConfig *api.ConfigJSON, err error) { func getBoxConfig(configFile string) (boxConfig *api.ConfigJSON, err error) {
configFileCredentials, _ := m.Get("config_credentials") file, err := os.ReadFile(configFile)
configFileBytes := []byte(configFileCredentials)
if configFileCredentials == "" {
configFile, _ := m.Get("box_config_file")
configFileBytes, err = os.ReadFile(configFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("box: failed to read Box config: %w", err) return nil, fmt.Errorf("box: failed to read Box config: %w", err)
} }
} err = json.Unmarshal(file, &boxConfig)
err = json.Unmarshal(configFileBytes, &boxConfig)
if err != nil { if err != nil {
return nil, fmt.Errorf("box: failed to parse Box config: %w", err) return nil, fmt.Errorf("box: failed to parse Box config: %w", err)
} }
@@ -503,12 +485,15 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
f.srv.SetHeader("as-user", f.opt.Impersonate) f.srv.SetHeader("as-user", f.opt.Impersonate)
} }
jsonFile, ok := m.Get("box_config_file")
boxSubType, boxSubTypeOk := m.Get("box_sub_type")
if ts != nil { if ts != nil {
// If using box config.json and JWT, renewing should just refresh the token and // If using box config.json and JWT, renewing should just refresh the token and
// should do so whether there are uploads pending or not. // should do so whether there are uploads pending or not.
if usesJWTAuth(m) { if ok && boxSubTypeOk && jsonFile != "" && boxSubType != "" {
f.tokenRenewer = oauthutil.NewRenew(f.String(), ts, func() error { f.tokenRenewer = oauthutil.NewRenew(f.String(), ts, func() error {
err := refreshJWTToken(ctx, name, m) err := refreshJWTToken(ctx, jsonFile, boxSubType, name, m)
return err return err
}) })
f.tokenRenewer.Start() f.tokenRenewer.Start()

View File

@@ -1648,14 +1648,11 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
newRoot, leaf := path.Split(oldRoot) newRoot, leaf := path.Split(oldRoot)
f.setRoot(newRoot) f.setRoot(newRoot)
_, err := f.NewObject(ctx, leaf) _, err := f.NewObject(ctx, leaf)
if errors.Is(err, fs.ErrorObjectNotFound) { if err != nil {
// File doesn't exist or is a directory so return old f // File doesn't exist or is a directory so return old f
f.setRoot(oldRoot) f.setRoot(oldRoot)
return f, nil return f, nil
} }
if err != nil {
return nil, err
}
// 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
} }

View File

@@ -1045,5 +1045,3 @@ put them back in again. -->
- n4n5 <its.just.n4n5@gmail.com> - n4n5 <its.just.n4n5@gmail.com>
- aliaj1 <ali19961@gmail.com> - aliaj1 <ali19961@gmail.com>
- Sean Turner <30396892+seanturner026@users.noreply.github.com> - Sean Turner <30396892+seanturner026@users.noreply.github.com>
- jijamik <30904953+jijamik@users.noreply.github.com>
- Dominik Sander <git@dsander.de>

View File

@@ -221,18 +221,6 @@ client credentials flow. In particular the "onedrive" option does not
work. You can use the "sharepoint" option or if that does not find the work. You can use the "sharepoint" option or if that does not find the
correct drive ID type it in manually with the "driveid" option. correct drive ID type it in manually with the "driveid" option.
To back up any user's data using this flow, grant your Azure AD
application the necessary Microsoft Graph *Application permissions*
(such as `Files.Read.All`, `Sites.Read.All` and/or `Sites.Selected`).
With these permissions, rclone can access drives across the tenant,
but it needs to know *which user or drive* you want. Supply a specific
`drive_id` corresponding to that user's OneDrive, or a SharePoint site
ID for SharePoint libraries. You can obtain a user's drive ID using
Microsoft Graph (e.g. `/users/{userUPN}/drive`) and then configure it
in rclone. Once the correct drive ID is provided, rclone will back up
that user's data using the app-only token without requiring their
credentials.
**NOTE** Assigning permissions directly to the application means that **NOTE** Assigning permissions directly to the application means that
anyone with the *Client ID* and *Client Secret* can access your anyone with the *Client ID* and *Client Secret* can access your
OneDrive files. Take care to safeguard these credentials. OneDrive files. Take care to safeguard these credentials.

View File

@@ -20,7 +20,7 @@ Unlocks the config file if it is locked.
Parameters: Parameters:
- 'configPassword' - password to unlock the config file - 'config_password' - password to unlock the config file
A good idea is to disable AskPassword before making this call A good idea is to disable AskPassword before making this call
`, `,
@@ -30,14 +30,10 @@ A good idea is to disable AskPassword before making this call
// Unlock the config file // Unlock the config file
// A good idea is to disable AskPassword before making this call // A good idea is to disable AskPassword before making this call
func rcConfigPassword(ctx context.Context, in rc.Params) (out rc.Params, err error) { func rcConfigPassword(ctx context.Context, in rc.Params) (out rc.Params, err error) {
configPass, err := in.GetString("configPassword") configPass, err := in.GetString("config_password")
if err != nil { if err != nil {
var err2 error
configPass, err2 = in.GetString("config_password") // backwards compat
if err2 != nil {
return nil, err return nil, err
} }
}
if SetConfigPassword(configPass) != nil { if SetConfigPassword(configPass) != nil {
return nil, errors.New("failed to set config password") return nil, errors.New("failed to set config password")
} }

View File

@@ -215,26 +215,13 @@ func TestRcPaths(t *testing.T) {
func TestRcConfigUnlock(t *testing.T) { func TestRcConfigUnlock(t *testing.T) {
call := rc.Calls.Get("config/unlock") call := rc.Calls.Get("config/unlock")
assert.NotNil(t, call) assert.NotNil(t, call)
in := rc.Params{ in := rc.Params{
"configPassword": "test", "config_password": "test",
} }
out, err := call.Fn(context.Background(), in) out, err := call.Fn(context.Background(), in)
require.NoError(t, err) require.NoError(t, err)
assert.Nil(t, err)
assert.Nil(t, out) assert.Nil(t, out)
in = rc.Params{
"config_password": "test",
}
out, err = call.Fn(context.Background(), in)
require.NoError(t, err)
assert.Nil(t, out)
in = rc.Params{
"bad_config_password": "test",
}
out, err = call.Fn(context.Background(), in)
require.Error(t, err)
assert.ErrorContains(t, err, `Didn't find key "configPassword" in input`)
assert.Nil(t, out)
} }

View File

@@ -425,8 +425,8 @@ Results:
- executeId - string id of rclone executing (change after restart) - executeId - string id of rclone executing (change after restart)
- jobids - array of integer job ids (starting at 1 on each restart) - jobids - array of integer job ids (starting at 1 on each restart)
- runningIds - array of integer job ids that are running - running_ids - array of integer job ids that are running
- finishedIds - array of integer job ids that are finished - finished_ids - array of integer job ids that are finished
`, `,
}) })
} }
@@ -436,8 +436,8 @@ func rcJobList(ctx context.Context, in rc.Params) (out rc.Params, err error) {
out = make(rc.Params) out = make(rc.Params)
out["jobids"] = running.IDs() out["jobids"] = running.IDs()
runningIDs, finishedIDs := running.Stats() runningIDs, finishedIDs := running.Stats()
out["runningIds"] = runningIDs out["running_ids"] = runningIDs
out["finishedIds"] = finishedIDs out["finished_ids"] = finishedIDs
out["executeId"] = executeID out["executeId"] = executeID
return out, nil return out, nil
} }

View File

@@ -378,8 +378,8 @@ func TestRcJobList(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, out1) require.NotNil(t, out1)
assert.Equal(t, []int64{1}, out1["jobids"], "should have job listed") assert.Equal(t, []int64{1}, out1["jobids"], "should have job listed")
assert.Equal(t, []int64{1}, out1["runningIds"], "should have running job") assert.Equal(t, []int64{1}, out1["running_ids"], "should have running job")
assert.Equal(t, []int64{}, out1["finishedIds"], "should not have finished job") assert.Equal(t, []int64{}, out1["finished_ids"], "should not have finished job")
_, _, err = NewJob(ctx, longFn, rc.Params{"_async": true}) _, _, err = NewJob(ctx, longFn, rc.Params{"_async": true})
assert.NoError(t, err) assert.NoError(t, err)