From 3dbcddc310d77029c90b2393cd52b5f2e2b59316 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 6 May 2022 15:47:38 +0300 Subject: [PATCH] fix: Confirm password in cli create first user step (#1220) Fixes #1182 --- cli/login.go | 13 +++++++++++++ cli/login_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/cli/login.go b/cli/login.go index 49729a605c..7ef42a6e4e 100644 --- a/cli/login.go +++ b/cli/login.go @@ -117,6 +117,19 @@ func login() *cobra.Command { if err != nil { return xerrors.Errorf("specify password prompt: %w", err) } + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: "Confirm " + cliui.Styles.Field.Render("password") + ":", + Secret: true, + Validate: func(s string) error { + if s != password { + return xerrors.Errorf("Passwords do not match") + } + return nil + }, + }) + if err != nil { + return xerrors.Errorf("confirm password prompt: %w", err) + } _, err = client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{ Email: email, diff --git a/cli/login_test.go b/cli/login_test.go index 32e9fcae55..a9cd31b6b7 100644 --- a/cli/login_test.go +++ b/cli/login_test.go @@ -43,6 +43,7 @@ func TestLogin(t *testing.T) { "username", "testuser", "email", "user@coder.com", "password", "password", + "password", "password", // Confirm. } for i := 0; i < len(matches); i += 2 { match := matches[i] @@ -54,6 +55,44 @@ func TestLogin(t *testing.T) { <-doneChan }) + t.Run("InitialUserTTYConfirmPasswordFailAndReprompt", func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + client := coderdtest.New(t, nil) + // The --force-tty flag is required on Windows, because the `isatty` library does not + // accurately detect Windows ptys when they are not attached to a process: + // https://github.com/mattn/go-isatty/issues/59 + doneChan := make(chan struct{}) + root, _ := clitest.New(t, "login", "--force-tty", client.URL.String()) + pty := ptytest.New(t) + root.SetIn(pty.Input()) + root.SetOut(pty.Output()) + go func() { + defer close(doneChan) + err := root.ExecuteContext(ctx) + require.ErrorIs(t, err, context.Canceled) + }() + + matches := []string{ + "first user?", "yes", + "username", "testuser", + "email", "user@coder.com", + "password", "mypass", + "password", "wrongpass", // Confirm. + } + for i := 0; i < len(matches); i += 2 { + match := matches[i] + value := matches[i+1] + pty.ExpectMatch(match) + pty.WriteLine(value) + } + pty.ExpectMatch("Passwords do not match") + pty.ExpectMatch("password") // Re-prompt password. + cancel() + <-doneChan + }) + t.Run("ExistingUserValidTokenTTY", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil)