Skip to content

Commit

Permalink
adding confirmation code into login flow
Browse files Browse the repository at this point in the history
  • Loading branch information
rusq committed Jan 7, 2024
1 parent 571df1f commit cde920c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 7 deletions.
6 changes: 6 additions & 0 deletions auth/auth_ui/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,9 @@ func prompt(w io.Writer, prompt string, readlnFn func(*os.File) (string, error))
fmt.Fprintln(w, "input cannot be empty")
}
}

func (*CLI) ConfirmationCode(email string) (code int, err error) {
fmt.Printf("Enter confirmation code sent to %s: ", email)
_, err = fmt.Fscanf(os.Stdin, "%d", &code)
return
}
29 changes: 29 additions & 0 deletions auth/auth_ui/huh.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"io"
"regexp"
"strconv"

"github.com/charmbracelet/huh"
)
Expand Down Expand Up @@ -102,3 +104,30 @@ func valSepEaster() func(v int) error {
return nil
}
}

func (*Huh) ConfirmationCode(email string) (int, error) {
var strCode string
q := huh.NewInput().
CharLimit(6).
Title(fmt.Sprintf("Enter confirmation code sent to %s", email)).
Description("Slack did not recognise the browser, and sent a confirmation code. Please enter the confirmation code below.").
Value(&strCode).
Validate(valSixDigits)
if err := q.Run(); err != nil {
return 0, err
}
code, err := strconv.Atoi(strCode)
if err != nil {
return 0, err
}
return code, nil
}

var numChlgRE = regexp.MustCompile(`^\d{6}$`)

func valSixDigits(s string) error {
if numChlgRE.MatchString(s) {
return nil
}
return errors.New("confirmation code must be a sequence of six digits")
}
47 changes: 47 additions & 0 deletions auth/auth_ui/huh_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package auth_ui

import "testing"

func Test_valSixDigits(t *testing.T) {
type args struct {
s string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
"empty",
args{""},
true,
},
{
"too short",
args{"12345"},
true,
},
{
"too long",
args{"1234567"},
true,
},
{
"not a number",
args{"123456a"},
true,
},
{
"valid",
args{"123456"},
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := valSixDigits(tt.args.s); (err != nil) != tt.wantErr {
t.Errorf("valSixDigits() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
18 changes: 11 additions & 7 deletions auth/rod.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"os"
"time"

"github.com/charmbracelet/huh/spinner"
"github.com/rusq/slackauth"
"github.com/rusq/slackdump/v2/auth/auth_ui"
)
Expand All @@ -29,6 +28,7 @@ type browserAuthUIExt interface {
BrowserAuthUI
RequestLoginType(w io.Writer) (int, error)
RequestCreds(w io.Writer, workspace string) (email string, passwd string, err error)
ConfirmationCode(email string) (code int, err error)
}

const expectedLoginDuration = 16 * time.Second
Expand Down Expand Up @@ -84,16 +84,20 @@ func NewRODAuth(ctx context.Context, opts ...Option) (RodAuth, error) {
if password == "" {
return r, fmt.Errorf("password cannot be empty")
}
fmt.Println("Logging in to Slack, depending on your connection speed, it usually takes 10-20 seconds...")

var loginErr error
spin := spinner.New().Title("Logging in...").Action(func() {
sp.Token, sp.Cookie, loginErr = slackauth.Headless(ctx, r.opts.workspace, username, password)
})
if err := spin.Run(); err != nil {
return r, err
}
sp.Token, sp.Cookie, loginErr = slackauth.Headless(
ctx,
r.opts.workspace,
username,
password,
slackauth.WithChallengeFunc(r.opts.ui.ConfirmationCode),
)
if loginErr != nil {
return r, loginErr
}

fmt.Fprintln(os.Stderr, "authenticated.")
case auth_ui.LoginCancel:
return r, ErrCancelled
Expand Down

0 comments on commit cde920c

Please sign in to comment.