From 8033b90695ccfeb1123a3f773d8610c3b64c980a Mon Sep 17 00:00:00 2001 From: kevin olson Date: Thu, 14 Mar 2024 21:08:22 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20authentication=20prgoress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 + pkg/cmd/auth/auth.go | 2 + pkg/cmd/auth/login/login.go | 11 +++++- pkg/cmd/auth/status/status.go | 17 ++++++-- pkg/config/config.go | 11 ++++++ pkg/ui/spinner.go | 12 +++--- pkg/ui/token.go | 74 +++++++++++++++++++++++++++++++++++ pkg/ui/ui.go | 12 +++++- 9 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 pkg/ui/token.go diff --git a/go.mod b/go.mod index a55ed9e..7051dc7 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( ) require ( + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/bubbles v0.18.0 // indirect github.com/charmbracelet/bubbletea v0.25.0 // indirect diff --git a/go.sum b/go.sum index b7e0785..9c21cfb 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= diff --git a/pkg/cmd/auth/auth.go b/pkg/cmd/auth/auth.go index 1f3da24..75a9ab4 100644 --- a/pkg/cmd/auth/auth.go +++ b/pkg/cmd/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( "github.com/spf13/cobra" "github.com/vulncheck-oss/cli/pkg/cmd/auth/login" + "github.com/vulncheck-oss/cli/pkg/cmd/auth/status" "github.com/vulncheck-oss/cli/pkg/session" ) @@ -16,6 +17,7 @@ func Command() *cobra.Command { session.DisableAuthCheck(cmd) cmd.AddCommand(login.Command()) + cmd.AddCommand(status.Command()) return cmd } diff --git a/pkg/cmd/auth/login/login.go b/pkg/cmd/auth/login/login.go index 9825df0..a8af58f 100644 --- a/pkg/cmd/auth/login/login.go +++ b/pkg/cmd/auth/login/login.go @@ -3,6 +3,7 @@ package login import ( "fmt" "github.com/MakeNowJust/heredoc/v2" + "github.com/octoper/go-ray" "github.com/spf13/cobra" "github.com/vulncheck-oss/cli/pkg/config" "github.com/vulncheck-oss/cli/pkg/session" @@ -48,9 +49,15 @@ func Command() *cobra.Command { Use: "token", Short: "Connect a VulnCheck account using a token", RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return util.FlagErrorf("No token specified") + if len(args) < 1 { + token, err := ui.TokenPrompt() + + if err != nil { + return util.FlagErrorf("Failed to read token: %v", err) + } + args = []string{token} } + ray.Ray(args[0]) if !ValidToken(args[0]) { return util.FlagErrorf("Invalid token specified") } diff --git a/pkg/cmd/auth/status/status.go b/pkg/cmd/auth/status/status.go index a082ab8..0badc33 100644 --- a/pkg/cmd/auth/status/status.go +++ b/pkg/cmd/auth/status/status.go @@ -1,16 +1,27 @@ package status -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" + "github.com/vulncheck-oss/cli/pkg/config" + "github.com/vulncheck-oss/cli/pkg/session" + "github.com/vulncheck-oss/cli/pkg/ui" +) func Command() *cobra.Command { cmd := &cobra.Command{ Use: "status", Short: "Check authentication status", - Long: "Check if you're currently authenticated and if so, display the account information". + Long: "Check if you're currently authenticated and if so, display the account information", RunE: func(cmd *cobra.Command, args []string) error { config.Init() + + if !config.HasConfig() { + ui.Danger("No configuration found. Please run `vc auth login` to authenticate.") + } + + return nil }, } - + session.DisableAuthCheck(cmd) return cmd } diff --git a/pkg/config/config.go b/pkg/config/config.go index 22bceb5..571cfe1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -59,6 +59,17 @@ func configDir() (string, error) { return dir, nil } +func HasConfig() bool { + + _, err := loadConfig() + + if err != nil { + return false + } + + return true +} + func SaveToken(token string) (string, error) { dir, err := configDir() if err != nil { diff --git a/pkg/ui/spinner.go b/pkg/ui/spinner.go index 7c69d3b..e8e4366 100644 --- a/pkg/ui/spinner.go +++ b/pkg/ui/spinner.go @@ -8,29 +8,29 @@ import ( "os" ) -type model struct { +type spinnerModel struct { spinner spinner.Model quitting bool err error copy string } -func (m *model) Init() tea.Cmd { +func (m *spinnerModel) Init() tea.Cmd { return m.spinner.Tick } -func (m *model) Quit() tea.Msg { +func (m *spinnerModel) Quit() tea.Msg { m.quitting = true return tea.Quit } -func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +func (m *spinnerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd m.spinner, cmd = m.spinner.Update(msg) return m, cmd } -func (m *model) View() string { +func (m *spinnerModel) View() string { return fmt.Sprintf("[ %s] %s", m.spinner.View(), m.copy) } @@ -38,7 +38,7 @@ func Spinner(copy string) *tea.Program { s := spinner.New() s.Spinner = spinner.Dot s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("#6667ab")) - program := tea.NewProgram(&model{spinner: s, copy: copy}) + program := tea.NewProgram(&spinnerModel{spinner: s, copy: copy}) go func() { if _, err := program.Run(); err != nil { fmt.Println(err) diff --git a/pkg/ui/token.go b/pkg/ui/token.go new file mode 100644 index 0000000..9929dff --- /dev/null +++ b/pkg/ui/token.go @@ -0,0 +1,74 @@ +package ui + +import ( + "fmt" + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" + "log" +) + +type tokenModel struct { + TextInput textinput.Model + err error +} + +type ( + errMsg error +) + +func initialModel() tokenModel { + ti := textinput.New() + ti.Placeholder = "vulncheck_***********" + ti.Focus() + ti.CharLimit = 74 + ti.Width = 74 + ti.EchoMode = textinput.EchoPassword + + return tokenModel{ + TextInput: ti, + err: nil, + } +} + +func (m tokenModel) Init() tea.Cmd { + return textinput.Blink +} + +func (m tokenModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var cmd tea.Cmd + + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.Type { + case tea.KeyEnter, tea.KeyCtrlC, tea.KeyEsc: + return m, tea.Quit + } + + // We handle errors just like any other message + case errMsg: + m.err = msg + return m, nil + } + + m.TextInput, cmd = m.TextInput.Update(msg) + return m, cmd +} + +func (m tokenModel) View() string { + return fmt.Sprintf( + "Paste your authentication token\n\n%s\n\n%s", + m.TextInput.View(), + "(esc to equit)", + ) + "\n" + +} + +func TokenPrompt() (string, error) { + p := tea.NewProgram(initialModel()) + result, err := p.Run() + if err != nil { + log.Fatal(err) + return "", err + } + return result.(tokenModel).TextInput.Value(), nil +} diff --git a/pkg/ui/ui.go b/pkg/ui/ui.go index 9140bf3..ed4f50a 100644 --- a/pkg/ui/ui.go +++ b/pkg/ui/ui.go @@ -5,10 +5,20 @@ import ( "github.com/charmbracelet/lipgloss" ) +var format = "[ %s ] %s\n" + func Success(str string) { fmt.Printf( - "[ %s ] %s\n", + format, lipgloss.NewStyle().Foreground(lipgloss.Color("#00ff00")).Render("✓"), lipgloss.NewStyle().Foreground(lipgloss.Color("#ffffff")).Render(str), ) } + +func Danger(sr string) error { + return fmt.Errorf( + format, + lipgloss.NewStyle().Foreground(lipgloss.Color("#ff0000")).Render("✗"), + lipgloss.NewStyle().Foreground(lipgloss.Color("#ffffff")).Render(sr), + ) +}