Merge 50b490a050ab270def7ff3ed5a74e5f2050c15ea into 4d38424e6cbb32d07c74d3b4d760af7afb35742d

This commit is contained in:
Costin Anghel 2025-03-19 07:37:19 -04:00 committed by GitHub
commit cf65cc45e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 113 additions and 65 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ __pycache__
.DS_Store
resource_windows_*.syso
.devcontainer
.vscode

View File

@ -658,6 +658,12 @@ However, a suffix of `B` for Byte, `K` for KiB, `M` for MiB,
`G` for GiB, `T` for TiB and `P` for PiB may be used. These are
the binary units, e.g. 1, 2\*\*10, 2\*\*20, 2\*\*30 respectively.
### --auth-addr=ADDR:PORT
Specify the address and port to be used for binding the oauth callback
listener. By default rclone will use localhost:53682. In Docker, for
example, you would want to use 0.0.0.0:53682
### --backup-dir=DIR ###
When using `sync`, `copy` or `move` any files which would have been
@ -2033,6 +2039,13 @@ to the terminal title.
This flag will limit rclone's output to error messages only.
### --redirect=URL
The `--redirect` flag allows to specify a custom redirect URL used for
OAuth 2.0 calls in the case that rclone is running in an environment
with a reverse proxy configured to route authentication calls back to
rclone.
### --refresh-times ###
The `--refresh-times` flag can be used to update modification times of

108
fs/config.go Normal file → Executable file
View File

@ -543,59 +543,61 @@ var ConfigOptionsInfo = Options{{
// ConfigInfo is filesystem config options
type ConfigInfo struct {
LogLevel LogLevel `config:"log_level"`
StatsLogLevel LogLevel `config:"stats_log_level"`
UseJSONLog bool `config:"use_json_log"`
DryRun bool `config:"dry_run"`
Interactive bool `config:"interactive"`
Links bool `config:"links"`
CheckSum bool `config:"checksum"`
SizeOnly bool `config:"size_only"`
IgnoreTimes bool `config:"ignore_times"`
IgnoreExisting bool `config:"ignore_existing"`
IgnoreErrors bool `config:"ignore_errors"`
ModifyWindow time.Duration `config:"modify_window"`
Checkers int `config:"checkers"`
Transfers int `config:"transfers"`
ConnectTimeout time.Duration `config:"contimeout"` // Connect timeout
Timeout time.Duration `config:"timeout"` // Data channel timeout
ExpectContinueTimeout time.Duration `config:"expect_continue_timeout"`
Dump DumpFlags `config:"dump"`
InsecureSkipVerify bool `config:"no_check_certificate"` // Skip server certificate verification
DeleteMode DeleteMode `config:"delete_mode"`
MaxDelete int64 `config:"max_delete"`
MaxDeleteSize SizeSuffix `config:"max_delete_size"`
TrackRenames bool `config:"track_renames"` // Track file renames.
TrackRenamesStrategy string `config:"track_renames_strategy"` // Comma separated list of strategies used to track renames
Retries int `config:"retries"` // High-level retries
RetriesInterval time.Duration `config:"retries_sleep"`
LowLevelRetries int `config:"low_level_retries"`
UpdateOlder bool `config:"update"` // Skip files that are newer on the destination
NoGzip bool `config:"no_gzip_encoding"` // Disable compression
MaxDepth int `config:"max_depth"`
IgnoreSize bool `config:"ignore_size"`
IgnoreChecksum bool `config:"ignore_checksum"`
IgnoreCaseSync bool `config:"ignore_case_sync"`
FixCase bool `config:"fix_case"`
NoTraverse bool `config:"no_traverse"`
CheckFirst bool `config:"check_first"`
NoCheckDest bool `config:"no_check_dest"`
NoUnicodeNormalization bool `config:"no_unicode_normalization"`
NoUpdateModTime bool `config:"no_update_modtime"`
NoUpdateDirModTime bool `config:"no_update_dir_modtime"`
DataRateUnit string `config:"stats_unit"`
CompareDest []string `config:"compare_dest"`
CopyDest []string `config:"copy_dest"`
BackupDir string `config:"backup_dir"`
Suffix string `config:"suffix"`
SuffixKeepExtension bool `config:"suffix_keep_extension"`
UseListR bool `config:"fast_list"`
BufferSize SizeSuffix `config:"buffer_size"`
BwLimit BwTimetable `config:"bwlimit"`
BwLimitFile BwTimetable `config:"bwlimit_file"`
TPSLimit float64 `config:"tpslimit"`
TPSLimitBurst int `config:"tpslimit_burst"`
BindAddr net.IP `config:"bind_addr"`
LogLevel LogLevel `config:"log_level"`
StatsLogLevel LogLevel `config:"stats_log_level"`
UseJSONLog bool `config:"use_json_log"`
DryRun bool `config:"dry_run"`
Interactive bool `config:"interactive"`
Links bool `config:"links"`
CheckSum bool `config:"checksum"`
SizeOnly bool `config:"size_only"`
IgnoreTimes bool `config:"ignore_times"`
IgnoreExisting bool `config:"ignore_existing"`
IgnoreErrors bool `config:"ignore_errors"`
ModifyWindow time.Duration `config:"modify_window"`
Checkers int `config:"checkers"`
Transfers int `config:"transfers"`
ConnectTimeout time.Duration `config:"contimeout"` // Connect timeout
Timeout time.Duration `config:"timeout"` // Data channel timeout
ExpectContinueTimeout time.Duration `config:"expect_continue_timeout"`
Dump DumpFlags `config:"dump"`
InsecureSkipVerify bool `config:"no_check_certificate"` // Skip server certificate verification
DeleteMode DeleteMode `config:"delete_mode"`
MaxDelete int64 `config:"max_delete"`
MaxDeleteSize SizeSuffix `config:"max_delete_size"`
TrackRenames bool `config:"track_renames"` // Track file renames.
TrackRenamesStrategy string `config:"track_renames_strategy"` // Comma separated list of strategies used to track renames
Retries int `config:"retries"` // High-level retries
RetriesInterval time.Duration `config:"retries_sleep"`
LowLevelRetries int `config:"low_level_retries"`
UpdateOlder bool `config:"update"` // Skip files that are newer on the destination
NoGzip bool `config:"no_gzip_encoding"` // Disable compression
MaxDepth int `config:"max_depth"`
IgnoreSize bool `config:"ignore_size"`
IgnoreChecksum bool `config:"ignore_checksum"`
IgnoreCaseSync bool `config:"ignore_case_sync"`
FixCase bool `config:"fix_case"`
NoTraverse bool `config:"no_traverse"`
CheckFirst bool `config:"check_first"`
NoCheckDest bool `config:"no_check_dest"`
NoUnicodeNormalization bool `config:"no_unicode_normalization"`
NoUpdateModTime bool `config:"no_update_modtime"`
NoUpdateDirModTime bool `config:"no_update_dir_modtime"`
DataRateUnit string `config:"stats_unit"`
CompareDest []string `config:"compare_dest"`
CopyDest []string `config:"copy_dest"`
BackupDir string `config:"backup_dir"`
Suffix string `config:"suffix"`
SuffixKeepExtension bool `config:"suffix_keep_extension"`
UseListR bool `config:"fast_list"`
BufferSize SizeSuffix `config:"buffer_size"`
BwLimit BwTimetable `config:"bwlimit"`
BwLimitFile BwTimetable `config:"bwlimit_file"`
TPSLimit float64 `config:"tpslimit"`
TPSLimitBurst int `config:"tpslimit_burst"`
BindAddr net.IP `config:"bind_addr"`
AuthAddr string
RedirectURL string
DisableFeatures []string `config:"disable"`
UserAgent string `config:"user_agent"`
Immutable bool `config:"immutable"`

2
fs/config/configflags/configflags.go Normal file → Executable file
View File

@ -53,6 +53,8 @@ func AddFlags(ci *fs.ConfigInfo, flagSet *pflag.FlagSet) {
flags.BoolVarP(flagSet, &deleteDuring, "delete-during", "", false, "When synchronizing, delete files during transfer", "Sync")
flags.BoolVarP(flagSet, &deleteAfter, "delete-after", "", false, "When synchronizing, delete files on destination after transferring (default)", "Sync")
flags.StringVarP(flagSet, &bindAddr, "bind", "", "", "Local address to bind to for outgoing connections, IPv4, IPv6 or name", "Networking")
flags.StringVarP(flagSet, &ci.AuthAddr, "auth-addr", "", ci.AuthAddr, "Local address to bind to for OAuth 2.0 callback, IPv4, IPv6 or name", "Networking")
flags.StringVarP(flagSet, &ci.RedirectURL, "redirect", "", ci.RedirectURL, "Redirect URL for OAuth2.0", "Networking")
flags.StringVarP(flagSet, &disableFeatures, "disable", "", "", "Disable a comma separated list of features (use --disable help to see a list)", "Config")
flags.StringArrayVarP(flagSet, &uploadHeaders, "header-upload", "", nil, "Set HTTP header for upload transactions", "Networking")
flags.StringArrayVarP(flagSet, &downloadHeaders, "header-download", "", nil, "Set HTTP header for download transactions", "Networking")

View File

@ -30,13 +30,6 @@ import (
var (
// templateString is the template used in the authorization webserver
templateString string
)
const (
// 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.
TitleBarRedirectURL = "urn:ietf:wg:oauth:2.0:oob"
// bindPort is the port that we bind the local webserver to
bindPort = "53682"
@ -56,6 +49,13 @@ const (
// RedirectPublicSecureURL is a public https URL which
// redirects to the local webserver
RedirectPublicSecureURL = "https://oauth.rclone.org/"
)
const (
// 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.
TitleBarRedirectURL = "urn:ietf:wg:oauth:2.0:oob"
// DefaultAuthResponseTemplate is the default template used in the authorization webserver
DefaultAuthResponseTemplate = `<!DOCTYPE html>
@ -473,12 +473,40 @@ func OverrideCredentials(name string, m configmap.Mapper, origConfig *Config) (n
return newConfig, changed
}
// overrideAuthServer sets the package level variables for the
// authentication server as well as overriding the redirect
// URL of the remote.
// the origConfig is copied
func overrideAuthServer(ctx context.Context, name string, m configmap.Mapper, origConfig *oauth2.Config) (newConfig *oauth2.Config, changed bool) {
newConfig = new(oauth2.Config)
*newConfig = *origConfig
changed = false
bindOverride := fs.GetConfig(ctx).AuthAddr
if bindOverride != "" {
bindAddress = bindOverride
changed = true
}
redirectOverride := fs.GetConfig(ctx).RedirectURL
if redirectOverride != "" {
RedirectPublicURL = redirectOverride + "/"
RedirectLocalhostURL = redirectOverride + "/"
RedirectPublicSecureURL = redirectOverride + "/"
newConfig.RedirectURL = redirectOverride
changed = true
}
return newConfig, changed
}
// NewClientWithBaseClient gets a token from the config file and
// configures a Client with it. It returns the client and a
// TokenSource which Invalidate may need to be called on. It uses the
// httpClient passed in as the base client.
func NewClientWithBaseClient(ctx context.Context, name string, m configmap.Mapper, config *Config, baseClient *http.Client) (*http.Client, *TokenSource, error) {
config, _ = OverrideCredentials(name, m, config)
config, _ = overrideAuthServer(ctx, name, m, config)
token, err := GetToken(name, m)
if err != nil && !config.ClientCredentialFlow {
return nil, nil, err
@ -731,7 +759,8 @@ version recommended):
if err != nil {
return nil, err
}
oauthConfig, changed := OverrideCredentials(name, m, opt.OAuth2Config)
oauthConfigTemp, _ := OverrideCredentials(name, m, opt.OAuth2Config)
oauthConfig, changed := overrideAuthServer(ctx, name, m, oauthConfigTemp)
if changed {
fs.Logf(nil, "Make sure your Redirect URL is set to %q in your custom config.\n", oauthConfig.RedirectURL)
}
@ -853,18 +882,19 @@ func configSetup(ctx context.Context, id, name string, m configmap.Mapper, oauth
}
go server.Serve()
defer server.Stop()
authURL = "http://" + bindAddress + "/auth?state=" + state
authRedirectURL := "http://" + oauthConfig.RedirectURL + "/auth?state=" + state
if !authorizeNoAutoBrowser {
// Open the URL for the user to visit
err := OpenURL(authURL)
err := OpenURL(authRedirectURL)
if err != nil {
fs.Errorf(nil, "Failed to open browser automatically (%v) - please go to the following link: %s\n", err, authURL)
} else {
fs.Logf(nil, "If your browser doesn't open automatically go to the following link: %s\n", authURL)
fs.Logf(nil, "If your browser doesn't open automatically go to the following link: %s\n", authRedirectURL)
}
} else {
fs.Logf(nil, "Please go to the following link: %s\n", authURL)
fs.Logf(nil, "Please go to the following link: %s\n", authRedirectURL)
}
fs.Logf(nil, "Log in and authorize rclone for access\n")