Skip to content

Commit

Permalink
Added support for token login.
Browse files Browse the repository at this point in the history
  • Loading branch information
BogdanHabic committed Feb 10, 2019
1 parent 6026190 commit 6ffc1c8
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 59 deletions.
13 changes: 12 additions & 1 deletion commands/commonMessages.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,24 @@ func WriteGlobalConfig() {
err := config.WriteGlobalConfig()
if err != nil {
userError.LogErrorf(
"login call: write global config: %s",
"write global config: %s",
userError.NewUserError(err, "Couldn't write global config file"),
)
os.Exit(1)
}
}

func WriteProjectConfig() {
err := config.WriteProjectConfig()
if err != nil {
userError.LogErrorf(
"write project config: %s",
userError.NewUserError(err, "Couldn't write project config file"),
)
os.Exit(1)
}
}

func DetectedProjectMessage(
printLoginSuccess bool,
action string,
Expand Down
2 changes: 1 addition & 1 deletion commands/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var initCmd = &cobra.Command{

config.SetProjectConfig(config.ProjectSlug, project.Slug)
config.SetProjectConfig(config.AccountID, config.GetString(config.AccountID))
config.WriteProjectConfig()
WriteProjectConfig()

logrus.Info(aurora.Sprintf("Project successfully initialized. "+
"You can change the project information by editing the %s file or by rerunning %s with the %s flag.",
Expand Down
197 changes: 148 additions & 49 deletions commands/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package commands

import (
"errors"
"fmt"
"github.com/logrusorgru/aurora"
"github.com/sirupsen/logrus"
"github.com/tenderly/tenderly-cli/rest"
"github.com/tenderly/tenderly-cli/rest/payloads"
"github.com/tenderly/tenderly-cli/userError"
"os"
Expand All @@ -18,13 +20,17 @@ const (
numberOfTries = 3
)

var providedUsername string
var providedEmail string
var providedPassword string
var providedToken string
var providedAuthenticationMethod string
var forceLogin bool

func init() {
loginCmd.PersistentFlags().StringVar(&providedUsername, "username", "", "The username used for logging in.")
loginCmd.PersistentFlags().StringVar(&providedEmail, "email", "", "The email used for logging in.")
loginCmd.PersistentFlags().StringVar(&providedPassword, "password", "", "The password used for logging in.")
loginCmd.PersistentFlags().StringVar(&providedToken, "token", "", "The token used for logging in.")
loginCmd.PersistentFlags().StringVar(&providedAuthenticationMethod, "authentication-method", "", "Pick the authentication method. Possible values are email or token")
loginCmd.PersistentFlags().BoolVar(&forceLogin, "force", false, "Don't check if you are already logged in.")
rootCmd.AddCommand(loginCmd)
}
Expand All @@ -50,56 +56,28 @@ var loginCmd = &cobra.Command{
os.Exit(0)
}

if len(providedAuthenticationMethod) == 0 {
promptAuthenticationMethod()
}

rest := newRest()
var token string

for i := 0; i < numberOfTries; i++ {
var email string
var password string
var err error

if providedUsername == "" {
email, err = promptEmail()
if err != nil {
userError.LogErrorf("prompt email failed: %s", err)
os.Exit(1)
}
} else {
email = providedUsername
}

if providedPassword == "" {
password, err = promptPassword()
if err != nil {
userError.LogErrorf("prompt password failed: %s", err)
os.Exit(1)
}
} else {
password = providedPassword
}

tokenResponse, err := rest.Auth.Login(payloads.LoginRequest{
Email: email,
Password: password,
})

if err != nil {
userError.LogErrorf("login call: %s", userError.NewUserError(
err,
"Couldn't make the login request. Please try again.",
))
continue
}
if tokenResponse.Error != nil {
userError.LogErrorf("login call: %s", tokenResponse.Error)
if providedUsername != "" && providedPassword != "" {
break
}
continue
}

token = tokenResponse.Token
break
if providedAuthenticationMethod == "email" {
token = emailLogin(rest)
} else if providedAuthenticationMethod == "token" {
token = tokenLogin()
} else {
userError.LogErrorf("unsupported authentication method: %s", userError.NewUserError(
fmt.Errorf("non-supported authentication method: %s", providedAuthenticationMethod),
aurora.Sprintf(
"The %s can either be %s or %s",
aurora.Bold(aurora.Green("--authentication-method")),
aurora.Bold(aurora.Green("email")),
aurora.Bold(aurora.Green("token")),
),
))
os.Exit(1)
}

if token == "" {
Expand All @@ -110,6 +88,14 @@ var loginCmd = &cobra.Command{

user, err := rest.User.User()
if err != nil {
if providedAuthenticationMethod == "token" {
userError.LogErrorf("cannot fetch user info: %s", userError.NewUserError(
err,
"Couldn't fetch user information. This can happen if your authentication token is not valid. Please try again.",
))
os.Exit(1)
}

userError.LogErrorf("cannot fetch user info: %s", userError.NewUserError(
err,
"Couldn't fetch user information. Please try again.",
Expand All @@ -131,6 +117,99 @@ var loginCmd = &cobra.Command{
},
}

func promptAuthenticationMethod() {
promptLoginWith := promptui.Select{
Label: "Select authentication method",
Items: []string{
"Email",
aurora.Sprintf(
"Authentication token (can be found under %s)",
aurora.Bold(aurora.Green("https://dashboard.tenderly.app/settings")),
),
},
}

index, _, err := promptLoginWith.Run()
if err != nil {
userError.LogErrorf("prompt authentication method failed: %s", err)
os.Exit(1)
}

providedAuthenticationMethod = "email"

if index == 1 {
providedAuthenticationMethod = "token"
}
}

func emailLogin(rest *rest.Rest) string {
var token string

for i := 0; i < numberOfTries; i++ {
var email string
var password string
var err error

if providedEmail == "" {
email, err = promptEmail()
if err != nil {
userError.LogErrorf("prompt email failed: %s", err)
os.Exit(1)
}
} else {
email = providedEmail
}

if providedPassword == "" {
password, err = promptPassword()
if err != nil {
userError.LogErrorf("prompt password failed: %s", err)
os.Exit(1)
}
} else {
password = providedPassword
}

tokenResponse, err := rest.Auth.Login(payloads.LoginRequest{
Email: email,
Password: password,
})

if err != nil {
userError.LogErrorf("login call: %s", userError.NewUserError(
err,
"Couldn't make the login request. Please try again.",
))
continue
}
if tokenResponse.Error != nil {
userError.LogErrorf("login call: %s", tokenResponse.Error)
if providedEmail != "" && providedPassword != "" {
break
}
continue
}

token = tokenResponse.Token
break
}

return token
}

func tokenLogin() string {
if len(providedToken) != 0 {
return providedToken
}

result, err := promptToken()
if err != nil {
return ""
}

return result
}

func promptEmail() (string, error) {
promptEmail := promptui.Prompt{
Label: "Enter your email",
Expand Down Expand Up @@ -171,3 +250,23 @@ func promptPassword() (string, error) {

return result, nil
}

func promptToken() (string, error) {
prompt := promptui.Prompt{
Label: "Authentication token",
Validate: func(input string) error {
if len(input) == 0 {
return errors.New("Please enter your authenticaiton token")
}
return nil
},
}

result, err := prompt.Run()

if err != nil {
return "", err
}

return result, nil
}
18 changes: 13 additions & 5 deletions commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package commands
import (
"flag"
"fmt"
"github.com/tenderly/tenderly-cli/userError"
"os"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -34,20 +35,29 @@ func init() {

func Execute() {
if err := rootCmd.Execute(); err != nil {
//@TODO: Print some common failure text here.
logrus.Errorf("Command failed with error: %s", err)
initLog()
userError.LogErrorf("command failed with error: %s", userError.NewUserError(
err,
"Command failed",
))
os.Exit(1)
}
}

var rootCmd = &cobra.Command{
Use: "tenderly",
Short: "Tenderly CLI is a suite of development tools for smart contracts.",
Long: "Tenderly CLI is a suite of development tools for smart contracts which allows your to monitor and debugMode them on any network.\n\n" +
Long: "Tenderly CLI is a suite of development tools for smart contracts which allows your to monitor and debug them on any network.\n\n" +
"To report a bug or give feedback send us an email at [email protected] or join our Discord channel at https://discord.gg/eCWjuvt\n",
}

func initConfig() {
initLog()

config.Init()
}

func initLog() {
logrus.SetFormatter(&logrus.TextFormatter{
DisableLevelTruncation: true,
})
Expand All @@ -58,8 +68,6 @@ func initConfig() {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetReportCaller(true)
}

config.Init()
}

func printHelp() {
Expand Down
6 changes: 3 additions & 3 deletions commands/whoami.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ var whoamiCmd = &cobra.Command{
os.Exit(0)
}

logrus.Infof("ID: %s", aurora.Green(user.ID))
logrus.Infof("Email: %s", aurora.Green(user.Email))
logrus.Infof("ID: %s", aurora.Bold(aurora.Green(user.ID)))
logrus.Infof("Email: %s", aurora.Bold(aurora.Green(user.Email)))
if len(user.Username) != 0 {
logrus.Infof("Username: %s", aurora.Green(user.Username))
logrus.Infof("Username: %s", aurora.Bold(aurora.Green(user.Username)))
}
},
}

0 comments on commit 6ffc1c8

Please sign in to comment.