Skip to content

Commit

Permalink
Merge pull request #404 from gphotosuploader/issue-402
Browse files Browse the repository at this point in the history
Add a parameter to the  command to set the redirect URL after auth
  • Loading branch information
pacoorozco authored Nov 1, 2023
2 parents 877b7fc + 7635aee commit f93d7c4
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/) and this project adheres to [Semantic Versioning](https://semver.org/).

## 4.2.0
### Added
- New parameter `--redirect-url-hostname` to the `auth` command in order to set the URL to use after the Google Photos authentication ([#402][i402])

[i402]: https://github.com/gphotosuploader/gphotos-uploader-cli/issues/402

## 4.1.1
### Fixed
- Uploads are showing the data of upload instead of the filename in the Google Photos UI. Thanks [@mikebilly](https://github.com/mikebilly) ([#398][i398])
Expand Down
23 changes: 18 additions & 5 deletions internal/app/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,30 @@ func (app *App) AuthenticateFromToken(ctx context.Context) (*http.Client, error)
return oauth.Client(ctx, cfg, token)
}

type AuthenticationOptions struct {
// Hostname of the redirect URL.
// You can set this if your provider does not accept localhost.
// Default to localhost.
RedirectURLHostname string

// Hostname and port which the local server binds to.
// You can set port number to 0 to allocate a free port.
// If nil or an empty slice is given, it defaults to "127.0.0.1:0" i.e., a free port.
LocalServerBindAddress string
}

// AuthenticateFromWeb returns an HTTP client authenticated in Google Photos.
// AuthenticateFromWeb will create a new token after completing the OAuth 2.0 flow.
func (app *App) AuthenticateFromWeb(ctx context.Context, port int) (*http.Client, error) {
func (app *App) AuthenticateFromWeb(ctx context.Context, authOptions AuthenticationOptions) (*http.Client, error) {
account := app.Config.Account
app.Logger.Infof("Getting authentication token for '%s'", account)

cfg := &oauth.Config{
ClientID: app.Config.APIAppCredentials.ClientID,
ClientSecret: app.Config.APIAppCredentials.ClientSecret,
Logf: app.Logger.Debugf,
Port: port,
ClientID: app.Config.APIAppCredentials.ClientID,
ClientSecret: app.Config.APIAppCredentials.ClientSecret,
Logf: app.Logger.Debugf,
LocalServerBindAddress: []string{authOptions.LocalServerBindAddress},
RedirectURLHostname: authOptions.RedirectURLHostname,
}

token, err := oauth.GetToken(ctx, cfg)
Expand Down
18 changes: 15 additions & 3 deletions internal/cli/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package auth

import (
"context"
"fmt"

"github.com/spf13/cobra"

Expand All @@ -14,7 +15,8 @@ type AuthCmd struct {
*flags.GlobalFlags

// command flags
Port int
Port int
RedirectURLHostname string
}

func NewCommand(globalFlags *flags.GlobalFlags) *cobra.Command {
Expand All @@ -28,7 +30,8 @@ func NewCommand(globalFlags *flags.GlobalFlags) *cobra.Command {
RunE: cmd.Run,
}

authCmd.Flags().IntVarP(&cmd.Port, "port", "p", 0, "port on which the auth server will listen (default 0)")
authCmd.Flags().IntVar(&cmd.Port, "port", 0, "port on which the auth server will listen (default 0)")
authCmd.Flags().StringVar(&cmd.RedirectURLHostname, "redirect-url-hostname", "", "hostname of the redirect URL (default localhost)")

return authCmd
}
Expand All @@ -43,7 +46,16 @@ func (cmd *AuthCmd) Run(cobraCmd *cobra.Command, args []string) error {
_ = cli.Stop()
}()

_, err = cli.AuthenticateFromWeb(ctx, cmd.Port)
// customize authentication options based on the command line parameters
authOptions := app.AuthenticationOptions{}
if cmd.Port != 0 {
authOptions.LocalServerBindAddress = fmt.Sprintf("127.0.0.1:%d", cmd.Port)
}
if cmd.RedirectURLHostname != "" {
authOptions.RedirectURLHostname = cmd.RedirectURLHostname
}

_, err = cli.AuthenticateFromWeb(ctx, authOptions)
if err == nil {
cli.Logger.Donef("Successful authentication for account '%s'", cli.Config.Account)
}
Expand Down
21 changes: 13 additions & 8 deletions internal/oauth/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ type Config struct {
// Logger function for debug.
Logf func(format string, args ...interface{})

// Port to bind the local authenticator
Port int
// Candidates of hostname and port which the local server binds to.
// You can set port number to 0 to allocate a free port.
// If multiple addresses are given, it will try the ports in order.
// If nil or an empty slice is given, it defaults to "127.0.0.1:0" i.e., a free port.
LocalServerBindAddress []string

// Hostname of the redirect URL.
// You can set this if your provider does not accept localhost.
// Default to localhost.
RedirectURLHostname string

oAuth2Config *oauth2.Config
}
Expand Down Expand Up @@ -69,10 +77,6 @@ func (c *Config) validateAndSetDefaults() error {
return fmt.Errorf("both ClientID and ClientSecret must be set")
}

if c.Port < 0 || c.Port > 65535 {
return fmt.Errorf("invalid port, must be in the range [0-65535]")
}

if c.Logf == nil {
c.Logf = func(string, ...interface{}) {}
}
Expand All @@ -82,6 +86,7 @@ func (c *Config) validateAndSetDefaults() error {
ClientSecret: c.ClientSecret,
Scopes: []string{PhotosLibraryScope},
Endpoint: GoogleAuthEndpoint,
RedirectURL: c.RedirectURLHostname,
}

return nil
Expand All @@ -91,12 +96,12 @@ func (c *Config) validateAndSetDefaults() error {
// flow, blocks until the user completes authorization and is redirected back, and returns the access token.
func (c *Config) getTokenFromWeb(ctx context.Context) (*oauth2.Token, error) {
ready := make(chan string, 1)
localServerBindAddress := fmt.Sprintf("127.0.0.1:%d", c.Port)
cfg := oauth2cli.Config{
OAuth2Config: *c.oAuth2Config,
LocalServerReadyChan: ready,
Logf: c.Logf,
LocalServerBindAddress: []string{localServerBindAddress},
LocalServerBindAddress: c.LocalServerBindAddress,
RedirectURLHostname: c.RedirectURLHostname,
}

var token *oauth2.Token
Expand Down

0 comments on commit f93d7c4

Please sign in to comment.