From 181267e20e0d8fb7fa467160647aee33d9043940 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 3 Nov 2018 12:40:50 +0000 Subject: [PATCH] cmd/rc: add --user and --pass flags and interpret --rc-user, --rc-pass, --rc-addr --- cmd/rc/rc.go | 74 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/cmd/rc/rc.go b/cmd/rc/rc.go index 25e4f8b0b..0f89f00a8 100644 --- a/cmd/rc/rc.go +++ b/cmd/rc/rc.go @@ -22,6 +22,8 @@ var ( noOutput = false url = "http://localhost:5572/" jsonInput = "" + authUser = "" + authPass = "" ) func init() { @@ -29,14 +31,24 @@ func init() { commandDefintion.Flags().BoolVarP(&noOutput, "no-output", "", noOutput, "If set don't output the JSON result.") commandDefintion.Flags().StringVarP(&url, "url", "", url, "URL to connect to rclone remote control.") commandDefintion.Flags().StringVarP(&jsonInput, "json", "", jsonInput, "Input JSON - use instead of key=value args.") + commandDefintion.Flags().StringVarP(&authUser, "user", "", "", "Username to use to rclone remote control.") + commandDefintion.Flags().StringVarP(&authPass, "pass", "", "", "Password to use to connect to rclone remote control.") } var commandDefintion = &cobra.Command{ Use: "rc commands parameter", Short: `Run a command against a running rclone.`, Long: ` -This runs a command against a running rclone. By default it will use -that specified in the --rc-addr command. + +This runs a command against a running rclone. Use the --url flag to +specify an non default URL to connect on. This can be either a +":port" which is taken to mean "http://localhost:port" or a +"host:port" which is taken to mean "http://host:port" + +A username and password can be passed in with --user and --pass. + +Note that --rc-addr, --rc-user, --rc-pass will be read also for --url, +--user, --pass. Arguments should be passed in as parameter=value. @@ -50,6 +62,7 @@ Use "rclone rc" to see a list of all possible commands.`, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(0, 1E9, command, args) cmd.Run(false, false, command, func() error { + parseFlags() if len(args) == 0 { return list() } @@ -58,30 +71,56 @@ Use "rclone rc" to see a list of all possible commands.`, }, } +// Parse the flags +func parseFlags() { + // set alternates from alternate flags + setAlternateFlag("rc-addr", &url) + setAlternateFlag("rc-user", &authUser) + setAlternateFlag("rc-pass", &authPass) + // If url is just :port then fix it up + if strings.HasPrefix(url, ":") { + url = "localhost" + url + } + // if url is just host:port add http:// + if !strings.HasPrefix(url, "http:") && !strings.HasPrefix(url, "https:") { + url = "http://" + url + } + // if url doesn't end with / add it + if !strings.HasSuffix(url, "/") { + url += "/" + } +} + +// If the user set flagName set the output to its value +func setAlternateFlag(flagName string, output *string) { + if rcFlag := pflag.Lookup(flagName); rcFlag != nil && rcFlag.Changed { + *output = rcFlag.Value.String() + } +} + // do a call from (path, in) to (out, err). // // if err is set, out may be a valid error return or it may be nil func doCall(path string, in rc.Params) (out rc.Params, err error) { // Do HTTP request client := fshttp.NewClient(fs.Config) - url := url - // set the user use --rc-addr as well as --url - if rcAddrFlag := pflag.Lookup("rc-addr"); rcAddrFlag != nil && rcAddrFlag.Changed { - url = rcAddrFlag.Value.String() - if strings.HasPrefix(url, ":") { - url = "localhost" + url - } - url = "http://" + url + "/" - } - if !strings.HasSuffix(url, "/") { - url += "/" - } url += path data, err := json.Marshal(in) if err != nil { return nil, errors.Wrap(err, "failed to encode JSON") } - resp, err := client.Post(url, "application/json", bytes.NewBuffer(data)) + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) + if err != nil { + return nil, errors.Wrap(err, "failed to make request") + } + + req.Header.Set("Content-Type", "application/json") + if authUser != "" || authPass != "" { + req.SetBasicAuth(authUser, authPass) + } + + resp, err := client.Do(req) if err != nil { return nil, errors.Wrap(err, "connection failed") } @@ -172,6 +211,11 @@ func list() error { } fmt.Printf("### %s: %s\n\n", info["Path"], info["Title"]) fmt.Printf("%s\n\n", info["Help"]) + if authRequired := info["AuthRequired"]; authRequired != nil { + if authRequired.(bool) { + fmt.Printf("Authentication is required for this call.\n\n") + } + } } return nil }