From 83f69ad1206730e9012f8453ef673720438cde9b Mon Sep 17 00:00:00 2001 From: Shantanu Date: Thu, 22 Aug 2024 11:29:36 -0700 Subject: [PATCH] login: extract login into its own pkg for reuse --- cmd/login.go | 100 ++--------------------------------------------- login/login.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 97 deletions(-) create mode 100644 login/login.go diff --git a/cmd/login.go b/cmd/login.go index dcf57cb..76a7c12 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -3,14 +3,9 @@ package cmd import ( "fmt" "os" - "strings" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/getsavvyinc/savvy-cli/client" - "github.com/getsavvyinc/savvy-cli/cmd/browser" - "github.com/getsavvyinc/savvy-cli/config" "github.com/getsavvyinc/savvy-cli/display" + "github.com/getsavvyinc/savvy-cli/login" "github.com/spf13/cobra" ) @@ -21,53 +16,6 @@ var loginCmd = &cobra.Command{ Run: runLoginCmd, } -var savvyLoginURL string = config.DashboardHost() + "/cli_login" - -type loginModel struct { - textInput textinput.Model - err error -} - -func initialModel() loginModel { - ti := textinput.New() - ti.Placeholder = "Paste your login token here" - ti.Prompt = "🔑 " - ti.Focus() - ti.CharLimit = 256 - ti.Width = 50 - ti.EchoCharacter = '*' - ti.EchoMode = textinput.EchoPassword - - return loginModel{textInput: ti} -} - -func (m loginModel) Init() tea.Cmd { - return textinput.Blink -} - -func (lm loginModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.Type { - case tea.KeyEnter: - return lm, tea.Quit - case tea.KeyCtrlC, tea.KeyEsc: - return lm, tea.Quit - } - } - - var cmd tea.Cmd - lm.textInput, cmd = lm.textInput.Update(msg) - return lm, cmd -} - -func (lm loginModel) View() string { - return fmt.Sprintf( - "Paste login token:\n%s\n\nPress Enter when done, Esc to quit.", - lm.textInput.View(), - ) -} - func runLoginCmd(cmd *cobra.Command, args []string) { force, err := cmd.Flags().GetBool(forceLoginFlag) if err != nil { @@ -75,55 +23,13 @@ func runLoginCmd(cmd *cobra.Command, args []string) { os.Exit(1) } - if err := verifyLogin(); err == nil && !force { + if err := login.Verify(); err == nil && !force { display.Info("You are already logged in!") display.Info("Run `savvy login --force` to get a new token") return } - runLogin() -} - -func runLogin() { - browser.Open(savvyLoginURL) - - p := tea.NewProgram(initialModel()) - - m, err := p.Run() - if err != nil { - display.ErrorWithSupportCTA(fmt.Errorf("login error: %w\n", err)) - os.Exit(1) - } else { - model := m.(loginModel) - if model.err != nil { - display.ErrorWithSupportCTA(fmt.Errorf("login failed: %w", model.err)) - os.Exit(1) - } - // Handle the token here (e.g., store it) - tok := model.textInput.Value() - // Remove quotes and braces and spaces from token - tok = strings.Trim(tok, "\"{} ") - - defer func() { - if err := verifyLogin(); err != nil { - display.ErrorWithSupportCTA(fmt.Errorf("login failed: %w", err)) - os.Exit(1) - } - display.Success("Login successful!") - }() - - cfg := config.Config{Token: tok} - if err := cfg.Save(); err != nil { - err = fmt.Errorf("error saving config: %w", err) - display.ErrorWithSupportCTA(err) - os.Exit(1) - } - } -} - -func verifyLogin() error { - _, err := client.New() - return err + login.Run() } const forceLoginFlag = "force" diff --git a/login/login.go b/login/login.go new file mode 100644 index 0000000..bb10d4b --- /dev/null +++ b/login/login.go @@ -0,0 +1,103 @@ +package login + +import ( + "fmt" + "os" + "strings" + + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" + "github.com/getsavvyinc/savvy-cli/client" + "github.com/getsavvyinc/savvy-cli/cmd/browser" + "github.com/getsavvyinc/savvy-cli/config" + "github.com/getsavvyinc/savvy-cli/display" +) + +type loginModel struct { + textInput textinput.Model + err error +} + +func initialModel() loginModel { + ti := textinput.New() + ti.Placeholder = "Paste your login token here" + ti.Prompt = "🔑 " + ti.Focus() + ti.CharLimit = 256 + ti.Width = 50 + ti.EchoCharacter = '*' + ti.EchoMode = textinput.EchoPassword + + return loginModel{textInput: ti} +} + +func (m loginModel) Init() tea.Cmd { + return textinput.Blink +} + +func (lm loginModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.Type { + case tea.KeyEnter: + return lm, tea.Quit + case tea.KeyCtrlC, tea.KeyEsc: + return lm, tea.Quit + } + } + + var cmd tea.Cmd + lm.textInput, cmd = lm.textInput.Update(msg) + return lm, cmd +} + +func (lm loginModel) View() string { + return fmt.Sprintf( + "Paste login token:\n%s\n\nPress Enter when done, Esc to quit.", + lm.textInput.View(), + ) +} + +var savvyLoginURL string = config.DashboardHost() + "/cli_login" + +func Run() { + browser.Open(savvyLoginURL) + + p := tea.NewProgram(initialModel()) + + m, err := p.Run() + if err != nil { + display.ErrorWithSupportCTA(fmt.Errorf("login error: %w\n", err)) + os.Exit(1) + } else { + model := m.(loginModel) + if model.err != nil { + display.ErrorWithSupportCTA(fmt.Errorf("login failed: %w", model.err)) + os.Exit(1) + } + // Handle the token here (e.g., store it) + tok := model.textInput.Value() + // Remove quotes and braces and spaces from token + tok = strings.Trim(tok, "\"{} ") + + defer func() { + if err := Verify(); err != nil { + display.ErrorWithSupportCTA(fmt.Errorf("login failed: %w", err)) + os.Exit(1) + } + display.Success("Login successful!") + }() + + cfg := config.Config{Token: tok} + if err := cfg.Save(); err != nil { + err = fmt.Errorf("error saving config: %w", err) + display.ErrorWithSupportCTA(err) + os.Exit(1) + } + } +} + +func Verify() error { + _, err := client.New() + return err +}