-
Notifications
You must be signed in to change notification settings - Fork 265
/
login.go
127 lines (107 loc) · 3.05 KB
/
login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package cmd
import (
"bufio"
"context"
"fmt"
"log"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/turbot/steampipe/pkg/cloud"
"github.com/turbot/steampipe/pkg/cmdconfig"
"github.com/turbot/steampipe/pkg/constants"
"github.com/turbot/steampipe/pkg/error_helpers"
"github.com/turbot/steampipe/sperr"
)
func loginCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "login",
TraverseChildren: true,
Args: cobra.NoArgs,
Run: runLoginCmd,
Short: "Login to Steampipe Cloud",
Long: `Login to Steampipe Cloud.`,
}
cmdconfig.OnCmd(cmd).
AddBoolFlag(constants.ArgHelp, false, "Help for dashboard", cmdconfig.FlagOptions.WithShortHand("h"))
return cmd
}
func runLoginCmd(cmd *cobra.Command, _ []string) {
ctx := cmd.Context()
log.Printf("[TRACE] login, cloud host %s", viper.Get(constants.ArgCloudHost))
log.Printf("[TRACE] opening login web page")
// start login flow - this will open a web page prompting user to login, and will give the user a code to enter
var id, err = cloud.WebLogin(ctx)
if err != nil {
error_helpers.ShowError(ctx, err)
exitCode = constants.ExitCodeLoginCloudConnectionFailed
return
}
token, err := getToken(ctx, id)
if err != nil {
error_helpers.ShowError(ctx, err)
exitCode = constants.ExitCodeLoginCloudConnectionFailed
return
}
// save token
err = cloud.SaveToken(token)
if err != nil {
error_helpers.ShowError(ctx, err)
exitCode = constants.ExitCodeLoginCloudConnectionFailed
return
}
displayLoginMessage(ctx, token)
}
func getToken(ctx context.Context, id string) (loginToken string, err error) {
log.Printf("[TRACE] prompt for verification code")
fmt.Println()
retries := 0
for {
var code string
code, err = promptUserForString("Enter verification code: ")
error_helpers.FailOnError(err)
if code != "" {
log.Printf("[TRACE] get login token")
// use this code to get a login token and store it
loginToken, err = cloud.GetLoginToken(ctx, id, code)
if err == nil {
return loginToken, nil
}
}
if err != nil {
// a code was entered but it failed - inc retry count
log.Printf("[TRACE] GetLoginToken failed with %s", err.Error())
}
retries++
// if we have used our retries, break out before displaying wanring - we will display an error
if retries == 3 {
return "", sperr.New("Too many attempts.")
}
if err != nil {
error_helpers.ShowWarning(err.Error())
}
log.Printf("[TRACE] Retrying")
}
}
func displayLoginMessage(ctx context.Context, token string) {
userName, err := cloud.GetUserName(ctx, token)
error_helpers.FailOnError(sperr.WrapWithMessage(err, "failed to read user name"))
fmt.Println()
fmt.Printf("Logged in as: %s\n", constants.Bold(userName))
fmt.Println()
}
func promptUserForString(prompt string) (string, error) {
fmt.Print(prompt)
scanner := bufio.NewScanner(os.Stdin)
if !scanner.Scan() {
// handle ctrl+d
fmt.Println()
os.Exit(0)
}
err := scanner.Err()
if err != nil {
return "", sperr.Wrap(err)
}
code := scanner.Text()
return code, nil
}