Skip to content

Commit

Permalink
browser selection, rename auth menu items
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Nov 2, 2024
1 parent 6349576 commit 55fe074
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 22 deletions.
4 changes: 2 additions & 2 deletions auth/auth_ui/auth_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const (
LInteractive LoginType = iota
// LHeadless is the email/password login type.
LHeadless
// LGoogleAuth is the google auth option
LGoogleAuth
// LUserBrowser is the google auth option
LUserBrowser
// LCancel should be returned if the user cancels the login intent.
LCancel
)
Expand Down
2 changes: 1 addition & 1 deletion auth/auth_ui/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (cl *CLI) RequestLoginType(w io.Writer) (LoginType, error) {
value LoginType
}{
{"Email", LHeadless},
{"Google", LGoogleAuth},
{"Google", LUserBrowser},
{"Apple", LInteractive},
{"Login with Single-Sign-On (SSO)", LInteractive},
{"Other/Manual", LInteractive},
Expand Down
98 changes: 85 additions & 13 deletions auth/auth_ui/huh.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"

"github.com/charmbracelet/huh"
"github.com/rusq/slackauth"
)

// Huh is the Auth UI that uses the huh library to provide a terminal UI.
Expand Down Expand Up @@ -48,20 +49,52 @@ func (*Huh) RequestCreds(w io.Writer, workspace string) (email string, passwd st
return
}

func (*Huh) RequestLoginType(w io.Writer) (LoginType, error) {
type methodMenuItem struct {
MenuItem string
ShortDesc string
Type LoginType
}

func (m methodMenuItem) String() string {
return fmt.Sprintf("%-20s - %s", m.MenuItem, m.ShortDesc)
}

var methods = []methodMenuItem{
{
"Manual",
"Works with most authentication schemes, except Google.",
LInteractive,
},
{
"Automatic",
"Only suitable for email/password auth",
LHeadless,
},
{
"User's Browser",
"Loads your user profile, works with Google Auth",
LUserBrowser,
},
}

type LoginOpts struct {
Type LoginType
BrowserPath string
}

func (*Huh) RequestLoginType(w io.Writer) (LoginOpts, error) {
var opts = make([]huh.Option[LoginType], 0, len(methods))
for _, m := range methods {
opts = append(opts, huh.NewOption(m.String(), m.Type))
}
opts = append(opts,
huh.NewOption("------", LoginType(-1)),
huh.NewOption("Cancel", LCancel),
)
var loginType LoginType
err := huh.NewForm(huh.NewGroup(
huh.NewSelect[LoginType]().Title("Select login type").
Options(
huh.NewOption("Email (manual)", LInteractive),
huh.NewOption("Email (automatic)", LHeadless),
huh.NewOption("Google", LGoogleAuth),
huh.NewOption("Apple", LInteractive),
huh.NewOption("Login with Single-Sign-On (SSO)", LInteractive),
huh.NewOption("Other/Manual", LInteractive),
huh.NewOption("", LoginType(-1)),
huh.NewOption("Cancel", LCancel),
).
Options(opts...).
Value(&loginType).
Validate(valSepEaster()).
DescriptionFunc(func() string {
Expand All @@ -70,7 +103,7 @@ func (*Huh) RequestLoginType(w io.Writer) (LoginType, error) {
return "Clean browser will open on a Slack Login page."
case LHeadless:
return "You will be prompted to enter your email and password, login is automated."
case LGoogleAuth:
case LUserBrowser:
return "System browser will open on a Slack Login page."
case LCancel:
return "Cancel the login process."
Expand All @@ -79,7 +112,46 @@ func (*Huh) RequestLoginType(w io.Writer) (LoginType, error) {
}
}, &loginType),
)).Run()
return loginType, err
if err != nil {
return LoginOpts{Type: LCancel}, err
}
if loginType == LUserBrowser {
path, err := chooseBrowser()
if err != nil {
return LoginOpts{Type: LCancel}, err
}
return LoginOpts{
Type: LUserBrowser,
BrowserPath: path,
}, err
}
return LoginOpts{Type: loginType}, nil
}

func chooseBrowser() (string, error) {
browsers, err := slackauth.ListBrowsers()
if err != nil {
return "", err
}
var opts = make([]huh.Option[int], 0, len(browsers))
for i, b := range browsers {
opts = append(opts, huh.NewOption(b.Name, i))
}

var selection int
err = huh.NewForm(huh.NewGroup(
huh.NewSelect[int]().
Title("Detected browsers on your system").
Options(opts...).
Value(&selection).
DescriptionFunc(func() string {
return browsers[selection].Path
}, &selection),
)).Run()
if err != nil {
return "", err
}
return browsers[selection].Path, nil
}

// ConfirmationCode asks the user to input the confirmation code, does some
Expand Down
10 changes: 5 additions & 5 deletions auth/rod.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type browserAuthUIExt interface {
// RequestLoginType should request the login type from the user and return
// one of the [auth_ui.LoginType] constants. The implementation should
// provide a way to cancel the login flow, returning [auth_ui.LoginCancel].
RequestLoginType(w io.Writer) (auth_ui.LoginType, error)
RequestLoginType(w io.Writer) (auth_ui.LoginOpts, error)
// RequestCreds should request the user's email and password and return
// them.
RequestCreds(w io.Writer, workspace string) (email string, passwd string, err error)
Expand Down Expand Up @@ -110,10 +110,10 @@ func NewRODAuth(ctx context.Context, opts ...Option) (RodAuth, error) {
return r, err
}
sopts := r.opts.slackauthOpts()
if resp == auth_ui.LGoogleAuth {
if resp.Type == auth_ui.LUserBrowser {
// it doesn't need to know that this browser is just a puppet in the
// masterful hands.
sopts = append(sopts, slackauth.WithForceUser())
sopts = append(sopts, slackauth.WithForceUser(), slackauth.WithLocalBrowser(resp.BrowserPath))
}

cl, err := slackauth.New(
Expand All @@ -128,8 +128,8 @@ func NewRODAuth(ctx context.Context, opts ...Option) (RodAuth, error) {
lg := logger.FromContext(ctx)
t := time.Now()
var sp simpleProvider
switch resp {
case auth_ui.LInteractive, auth_ui.LGoogleAuth:
switch resp.Type {
case auth_ui.LInteractive, auth_ui.LUserBrowser:
lg.Printf("ℹ️ Initialising browser, once the browser appears, login as usual")
var err error
sp.Token, sp.Cookie, err = cl.Manual(ctx)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
github.com/rusq/osenv/v2 v2.0.1
github.com/rusq/rbubbles v0.0.2
github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99
github.com/rusq/slackauth v0.4.0
github.com/rusq/slackauth v0.5.0
github.com/rusq/tracer v1.0.1
github.com/schollz/progressbar/v3 v3.13.0
github.com/stretchr/testify v1.9.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99 h1:dqEcNs9hMc2PiMwhw8
github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99/go.mod h1:9O0zQAFN6W47z4KpTQbe6vOHOzBO76vMg1+gthPwaTI=
github.com/rusq/slackauth v0.4.0 h1:hNOEWw6Tji24MRJ8rsepgb4w47v0wPGxjhGpvkQJQJU=
github.com/rusq/slackauth v0.4.0/go.mod h1:wAtNCbeKH0pnaZnqJjG5RKY3e5BF9F2L/YTzhOjBIb0=
github.com/rusq/slackauth v0.5.0 h1:CvEuGTfH6/vF+yh1hlfsPVao97fL30X2ZJmHPu181C4=
github.com/rusq/slackauth v0.5.0/go.mod h1:wAtNCbeKH0pnaZnqJjG5RKY3e5BF9F2L/YTzhOjBIb0=
github.com/rusq/tracer v1.0.1 h1:5u4PCV8NGO97VuAINQA4gOVRkPoqHimLE2jpezRVNMU=
github.com/rusq/tracer v1.0.1/go.mod h1:Rqu48C3/K8bA5NPmF20Hft73v431MQIdM+Co+113pME=
github.com/schollz/progressbar/v3 v3.13.0 h1:9TeeWRcjW2qd05I8Kf9knPkW4vLM/hYoa6z9ABvxje8=
Expand Down

0 comments on commit 55fe074

Please sign in to comment.