From e1e649537e1d9bc5903521e671e92d5c1d64bb72 Mon Sep 17 00:00:00 2001 From: bravo68web Date: Thu, 8 Aug 2024 20:00:48 +0000 Subject: [PATCH 1/3] feat: added feature to show warning to user if they are already logged in --- cli/login.go | 9 ++++++--- cli/login_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ cli/root.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/cli/login.go b/cli/login.go index 834ba73ce38a0..dd11d4e22b883 100644 --- a/cli/login.go +++ b/cli/login.go @@ -151,9 +151,12 @@ func (r *RootCmd) login() *serpent.Command { useTokenForSession bool ) cmd := &serpent.Command{ - Use: "login []", - Short: "Authenticate with Coder deployment", - Middleware: serpent.RequireRangeArgs(0, 1), + Use: "login []", + Short: "Authenticate with Coder deployment", + Middleware: serpent.Chain( + serpent.RequireRangeArgs(0, 1), + r.CheckExistingUserSession(), + ), Handler: func(inv *serpent.Invocation) error { ctx := inv.Context() rawURL := "" diff --git a/cli/login_test.go b/cli/login_test.go index 0428c332d02b0..834e2463bc4e0 100644 --- a/cli/login_test.go +++ b/cli/login_test.go @@ -442,4 +442,48 @@ func TestLogin(t *testing.T) { require.NoError(t, err) require.Equal(t, selected, first.OrganizationID.String()) }) + + t.Run("ExistingUserValidTokenTTYWarnReloggin", func(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, nil) + coderdtest.CreateFirstUser(t, client) + + doneChan := make(chan struct{}) + root, _ := clitest.New(t, "login", "--force-tty", client.URL.String(), "--no-open") + pty := ptytest.New(t).Attach(root) + go func() { + defer close(doneChan) + err := root.Run() + assert.NoError(t, err) + }() + + pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with argument URL: '%s'", client.URL.String())) + pty.ExpectMatch("Paste your token here:") + pty.WriteLine(client.SessionToken()) + if runtime.GOOS != "windows" { + // For some reason, the match does not show up on Windows. + pty.ExpectMatch(client.SessionToken()) + } + pty.ExpectMatch("Welcome to Coder") + <-doneChan + + doneChan = make(chan struct{}) + root, _ = clitest.New(t, "login", "--force-tty", client.URL.String(), "--no-open") + pty = ptytest.New(t).Attach(root) + go func() { + defer close(doneChan) + err := root.Run() + assert.NoError(t, err) + }() + pty.ExpectMatch(fmt.Sprintf(" Already Logged In to '%s'!", client.URL.String())) + pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with argument URL: '%s'", client.URL.String())) + pty.ExpectMatch("Paste your token here:") + pty.WriteLine(client.SessionToken()) + if runtime.GOOS != "windows" { + // For some reason, the match does not show up on Windows. + pty.ExpectMatch(client.SessionToken()) + } + pty.ExpectMatch("Welcome to Coder") + <-doneChan + }) } diff --git a/cli/root.go b/cli/root.go index 22d153c00f7f1..219378340c507 100644 --- a/cli/root.go +++ b/cli/root.go @@ -546,6 +546,50 @@ func (r *RootCmd) InitClient(client *codersdk.Client) serpent.MiddlewareFunc { } } +func (r *RootCmd) CheckExistingUserSession() serpent.MiddlewareFunc { + return func(next serpent.HandlerFunc) serpent.HandlerFunc { + return func(inv *serpent.Invocation) error { + conf := r.createConfig() + var err error + // Read the client URL stored on disk. + if r.clientURL == nil || r.clientURL.String() == "" { + rawURL, err := conf.URL().Read() + // If the configuration files are absent, the user is logged out + if os.IsNotExist(err) { + return next(inv) + } + if err != nil { + return err + } + + r.clientURL, err = url.Parse(strings.TrimSpace(rawURL)) + if err != nil { + return err + } + } + // Read the token stored on disk. + if r.token == "" { + r.token, err = conf.Session().Read() + // Even if there isn't a token, we don't care. + if err != nil && !os.IsNotExist(err) { + return next(inv) + } + } + + // IF r.token and r.clientUR, exists then print warning "ALready loggedIn" + if r.token != "" && r.clientURL.String() != "" { + _, _ = fmt.Fprintf(inv.Stdout, Caret+"%s!\n", pretty.Sprint(cliui.DefaultStyles.Warn, "Already Logged In to "+r.clientURL.String())) + } + + // We remove the token and clientURL from the RootCmd, so the user can still go ahead and login + r.clientURL = nil + r.token = "" + + return next(inv) + } + } +} + // HeaderTransport creates a new transport that executes `--header-command` // if it is set to add headers for all outbound requests. func (r *RootCmd) HeaderTransport(ctx context.Context, serverURL *url.URL) (*codersdk.HeaderTransport, error) { From f9270a9b8c0da09098a9ab11f47151ef9fbae01b Mon Sep 17 00:00:00 2001 From: bravo68web Date: Fri, 9 Aug 2024 14:18:02 +0000 Subject: [PATCH 2/3] fix: added requested changes --- cli/login_test.go | 2 +- cli/root.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/login_test.go b/cli/login_test.go index 834e2463bc4e0..ba6d56232f0c5 100644 --- a/cli/login_test.go +++ b/cli/login_test.go @@ -475,7 +475,7 @@ func TestLogin(t *testing.T) { err := root.Run() assert.NoError(t, err) }() - pty.ExpectMatch(fmt.Sprintf(" Already Logged In to '%s'!", client.URL.String())) + pty.ExpectMatch(fmt.Sprintf("You are already logged in to '%s'!", client.URL.String())) pty.ExpectMatch(fmt.Sprintf("Attempting to authenticate with argument URL: '%s'", client.URL.String())) pty.ExpectMatch("Paste your token here:") pty.WriteLine(client.SessionToken()) diff --git a/cli/root.go b/cli/root.go index 219378340c507..412068c0391bf 100644 --- a/cli/root.go +++ b/cli/root.go @@ -576,9 +576,9 @@ func (r *RootCmd) CheckExistingUserSession() serpent.MiddlewareFunc { } } - // IF r.token and r.clientUR, exists then print warning "ALready loggedIn" + // IF r.token and r.clientUR, exists then print warning "You are already logged in to $" if r.token != "" && r.clientURL.String() != "" { - _, _ = fmt.Fprintf(inv.Stdout, Caret+"%s!\n", pretty.Sprint(cliui.DefaultStyles.Warn, "Already Logged In to "+r.clientURL.String())) + _, _ = fmt.Fprintf(inv.Stdout, Caret+"%s!\n", pretty.Sprint(cliui.DefaultStyles.Warn, "You are already logged in to "+r.clientURL.String())) } // We remove the token and clientURL from the RootCmd, so the user can still go ahead and login From ac950066e475c012fdd55573cde8475fc9d26380 Mon Sep 17 00:00:00 2001 From: bravo68web Date: Wed, 28 Aug 2024 15:50:40 +0000 Subject: [PATCH 3/3] chore: minor changes --- cli/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/root.go b/cli/root.go index 412068c0391bf..02f5715a2251d 100644 --- a/cli/root.go +++ b/cli/root.go @@ -578,7 +578,7 @@ func (r *RootCmd) CheckExistingUserSession() serpent.MiddlewareFunc { // IF r.token and r.clientUR, exists then print warning "You are already logged in to $" if r.token != "" && r.clientURL.String() != "" { - _, _ = fmt.Fprintf(inv.Stdout, Caret+"%s!\n", pretty.Sprint(cliui.DefaultStyles.Warn, "You are already logged in to "+r.clientURL.String())) + _, _ = fmt.Fprintf(inv.Stderr, Caret+"%s!\n", pretty.Sprint(cliui.DefaultStyles.Warn, "You are already logged in to "+r.clientURL.String()+"!")) } // We remove the token and clientURL from the RootCmd, so the user can still go ahead and login