# HG changeset patch # User Mikael Berthe # Date 1494418273 -7200 # Node ID 2e411da68fd3bb9220bf4ed939d7fe826aa02fce # Parent 58d30ab47543f6ecc8d811e5d82bca6e6401ef1a Add oauth2 command Allows OAuth 2.0 authentication interactively or non-interactively. % madonctl oauth2 or % madonctl oauth2 > conffile.yaml Non-interactively: % madonctl oauth2 get-url % madonctl oauth2 code OAUTHCODE (--output/--template can be used as well to customize the output.) diff -r 58d30ab47543 -r 2e411da68fd3 cmd/accounts.go --- a/cmd/accounts.go Tue May 09 20:14:28 2017 +0200 +++ b/cmd/accounts.go Wed May 10 14:11:13 2017 +0200 @@ -86,7 +86,6 @@ Aliases: []string{"account"}, Short: "Account-related functions", //Long: `TBW...`, // TODO - //PersistentPreRunE: func(cmd *cobra.Command, args []string) error {}, } // Note: Some account subcommands are not defined in this file. diff -r 58d30ab47543 -r 2e411da68fd3 cmd/config.go --- a/cmd/config.go Tue May 09 20:14:28 2017 +0200 +++ b/cmd/config.go Wed May 10 14:11:13 2017 +0200 @@ -90,7 +90,8 @@ cfile = defaultConfigFile } errPrint("You can copy the following lines into a configuration file.") - errPrint("E.g. %s -i INSTANCE -L USERNAME -P PASS config dump > %s\n", AppName, cfile) + errPrint("E.g. %s -i INSTANCE -L USERNAME -P PASS config dump > %s", AppName, cfile) + errPrint(" or %s -i INSTANCE oauth2 > %s\n", AppName, cfile) pOptions := printer.Options{"template": configurationTemplate} p, err = printer.NewPrinterTemplate(pOptions) } else { diff -r 58d30ab47543 -r 2e411da68fd3 cmd/oauth2.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/oauth2.go Wed May 10 14:11:13 2017 +0200 @@ -0,0 +1,116 @@ +// Copyright © 2017 Mikael Berthe +// +// Licensed under the MIT license. +// Please see the LICENSE file is this directory. + +package cmd + +import ( + "fmt" + "os" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + //"github.com/McKael/madonctl/printer" +) + +var oauth2Cmd = &cobra.Command{ + Use: "oauth2", + Short: "OAuth2 authentication/authorization", + Example: ` madonctl oauth2 # Interactive OAuth2 login + madonctl oauth2 get-url # Display OAuth2 auhtorization URL + madonctl oauth2 code CODE # Enter OAuth2 code`, + RunE: func(cmd *cobra.Command, args []string) error { + return oAuth2Interactive(args) + }, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Initialize application; do not log in yet + return madonInit(false) + }, +} + +func init() { + RootCmd.AddCommand(oauth2Cmd) + + // Subcommands + oauth2Cmd.AddCommand(oauth2Subcommands...) +} + +var oauth2Subcommands = []*cobra.Command{ + &cobra.Command{ + Use: "get-url", + Short: "Get OAuth2 URL", + RunE: func(cmd *cobra.Command, args []string) error { + return oAuth2GetURL() + }, + }, + &cobra.Command{ + Use: "code", + Short: "Log in with OAuth2 code", + RunE: func(cmd *cobra.Command, args []string) error { + return oAuth2ExchangeCode(args) + }, + }, +} + +func oAuth2GetURL() error { + // (gClient != nil thanks to PreRun) + + url, err := gClient.LoginOAuth2("", scopes) + if err != nil { + return errors.Wrap(err, "OAuth2 authentication failed") + } + + fmt.Printf("%s\n", url) + return nil +} + +func oAuth2ExchangeCode(args []string) error { + // (gClient != nil thanks to PreRun) + + if len(args) != 1 { + return errors.New("wrong usage: code needs 1 argument") + } + + code := args[0] + + if code == "" { + return errors.New("no code entered") + } + + // The code has been set; proceed with token exchange + _, err := gClient.LoginOAuth2(code, scopes) + if err != nil { + return err + } + + if gClient.UserToken != nil { + errPrint("Login successful.\n") + configDump() + } + return nil +} + +// oAuth2Interactive is the default behaviour +func oAuth2Interactive(args []string) error { + // (gClient != nil thanks to PreRun) + + url, err := gClient.LoginOAuth2("", scopes) + if err != nil { + return errors.Wrap(err, "OAuth2 authentication failed") + } + + fmt.Fprintf(os.Stderr, "Visit the URL for the auth dialog:\n%s\n", url) + fmt.Fprintf(os.Stderr, "Enter code: ") + var code string + if _, err := fmt.Scan(&code); err != nil { + return err + } + + if code == "" { + return errors.New("no code entered") + } + + // The code has been set; proceed with token exchange + return oAuth2ExchangeCode([]string{code}) +} diff -r 58d30ab47543 -r 2e411da68fd3 cmd/status.go --- a/cmd/status.go Tue May 09 20:14:28 2017 +0200 +++ b/cmd/status.go Wed May 10 14:11:13 2017 +0200 @@ -82,10 +82,7 @@ if statusOpts.statusID < 1 && cmd.Name() != "post" { return errors.New("missing status ID") } - if err := madonInit(true); err != nil { - return err - } - return nil + return madonInit(true) }, }