chore: refactor password code for StdIO (#139)
This commit is contained in:
parent
f80b91730d
commit
a3408e031a
@ -1 +1 @@
|
||||
Subproject commit d9aa0f1136d17956f45ebb63717220214933d477
|
||||
Subproject commit 8a47036bed515857a28d7fba103c3b1b13ac64fd
|
@ -8,8 +8,6 @@ import (
|
||||
"github.com/influxdata/influx-cli/v2/pkg/stdio"
|
||||
)
|
||||
|
||||
const MinPasswordLen = 8
|
||||
|
||||
// CLI is a container for common functionality used to execute commands.
|
||||
type CLI struct {
|
||||
StdIO stdio.StdIO
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/influxdata/influx-cli/v2/clients/bucket"
|
||||
"github.com/influxdata/influx-cli/v2/config"
|
||||
"github.com/influxdata/influx-cli/v2/internal/duration"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/stdio"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -121,7 +122,7 @@ func (c Client) validateNoNameCollision(configName string) error {
|
||||
// Unless the 'force' parameter is set, the user will be prompted to enter any missing information
|
||||
// and to confirm the final request parameters.
|
||||
func (c Client) onboardingRequest(params *Params) (req api.OnboardingRequest, err error) {
|
||||
if (params.Force || params.Password != "") && len(params.Password) < clients.MinPasswordLen {
|
||||
if (params.Force || params.Password != "") && len(params.Password) < stdio.MinPasswordLen {
|
||||
return req, clients.ErrPasswordIsTooShort
|
||||
}
|
||||
|
||||
@ -164,24 +165,11 @@ func (c Client) onboardingRequest(params *Params) (req api.OnboardingRequest, er
|
||||
}
|
||||
}
|
||||
if params.Password == "" {
|
||||
for {
|
||||
pass1, err := c.StdIO.GetSecret("Please type your password", clients.MinPasswordLen)
|
||||
if err != nil {
|
||||
return req, err
|
||||
}
|
||||
// Don't bother with the length check the 2nd time, since we check equality to pass1.
|
||||
pass2, err := c.StdIO.GetSecret("Please type your password again", 0)
|
||||
if err != nil {
|
||||
return req, err
|
||||
}
|
||||
if pass1 == pass2 {
|
||||
req.Password = &pass1
|
||||
break
|
||||
}
|
||||
if err := c.StdIO.Error("Passwords do not match"); err != nil {
|
||||
return req, err
|
||||
}
|
||||
pass, err := c.StdIO.GetPassword("Please type your password")
|
||||
if err != nil {
|
||||
return req, err
|
||||
}
|
||||
req.Password = &pass
|
||||
}
|
||||
if params.Org == "" {
|
||||
req.Org, err = c.StdIO.GetStringInput("Please type your primary organization name", "")
|
||||
|
@ -215,8 +215,7 @@ func Test_SetupSuccessInteractive(t *testing.T) {
|
||||
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(bytesWritten.Write).AnyTimes()
|
||||
stdio.EXPECT().Banner(gomock.Any())
|
||||
stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary username"), gomock.Any()).Return(username, nil)
|
||||
stdio.EXPECT().GetSecret(gomock.Eq("Please type your password"), gomock.Any()).Return(password, nil)
|
||||
stdio.EXPECT().GetSecret(gomock.Eq("Please type your password again"), gomock.Any()).Return(password, nil)
|
||||
stdio.EXPECT().GetPassword(gomock.Eq("Please type your password")).Return(password, nil)
|
||||
stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary organization name"), gomock.Any()).Return(org, nil)
|
||||
stdio.EXPECT().GetStringInput("Please type your primary bucket name", gomock.Any()).Return(bucket, nil)
|
||||
stdio.EXPECT().GetStringInput("Please type your retention period in hours, or 0 for infinite", gomock.Any()).Return(strconv.Itoa(retentionHrs), nil)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/influxdata/influx-cli/v2/api"
|
||||
"github.com/influxdata/influx-cli/v2/clients"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/influxid"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/stdio"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
@ -49,7 +50,7 @@ func getOrgID(ctx context.Context, params *clients.OrgParams, c clients.CLI, org
|
||||
}
|
||||
|
||||
func (c Client) Create(ctx context.Context, params *CreateParams) error {
|
||||
if params.Password != "" && len(params.Password) < clients.MinPasswordLen {
|
||||
if params.Password != "" && len(params.Password) < stdio.MinPasswordLen {
|
||||
return clients.ErrPasswordIsTooShort
|
||||
}
|
||||
|
||||
@ -159,31 +160,16 @@ func (c Client) SetPassword(ctx context.Context, params *SetPasswordParams) erro
|
||||
id = (*users.Users)[0].GetId()
|
||||
}
|
||||
|
||||
var password string
|
||||
for {
|
||||
pass1, err := c.StdIO.GetSecret(fmt.Sprintf("Please type new password for %q", displayName), clients.MinPasswordLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Don't bother with the length check the 2nd time, since we check equality to pass1.
|
||||
pass2, err := c.StdIO.GetSecret("Please type new password again", 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pass1 == pass2 {
|
||||
password = pass1
|
||||
break
|
||||
}
|
||||
if err := c.StdIO.Error("Passwords do not match"); err != nil {
|
||||
return err
|
||||
}
|
||||
password, err := c.StdIO.GetPassword(fmt.Sprintf("Please type new password for %q", displayName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
body := api.PasswordResetBody{Password: password}
|
||||
if err := c.PostUsersIDPassword(ctx, id).PasswordResetBody(body).Execute(); err != nil {
|
||||
return fmt.Errorf("failed to set password for user %q: %w", params.Id.String(), err)
|
||||
}
|
||||
_, err := c.StdIO.Write([]byte(fmt.Sprintf("Successfully updated password for user %q\n", displayName)))
|
||||
_, err = c.StdIO.Write([]byte(fmt.Sprintf("Successfully updated password for user %q\n", displayName)))
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ func TestClient_SetPassword(t *testing.T) {
|
||||
stdio := mock.NewMockStdIO(ctrl)
|
||||
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes()
|
||||
if !tc.noExpectAsk {
|
||||
stdio.EXPECT().GetSecret(gomock.Any(), gomock.Any()).Return("mypassword", nil).Times(2)
|
||||
stdio.EXPECT().GetPassword(gomock.Any()).Return("mypassword", nil)
|
||||
}
|
||||
|
||||
cli := user.Client{CLI: clients.CLI{StdIO: stdio}, UsersApi: userApi}
|
||||
|
@ -75,6 +75,21 @@ func (mr *MockStdIOMockRecorder) GetConfirm(arg0 interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfirm", reflect.TypeOf((*MockStdIO)(nil).GetConfirm), arg0)
|
||||
}
|
||||
|
||||
// GetPassword mocks base method.
|
||||
func (m *MockStdIO) GetPassword(arg0 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPassword", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetPassword indicates an expected call of GetPassword.
|
||||
func (mr *MockStdIOMockRecorder) GetPassword(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPassword", reflect.TypeOf((*MockStdIO)(nil).GetPassword), arg0)
|
||||
}
|
||||
|
||||
// GetSecret mocks base method.
|
||||
func (m *MockStdIO) GetSecret(arg0 string, arg1 int) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -67,7 +67,7 @@ func (t *terminalStdio) GetStringInput(prompt, defaultValue string) (input strin
|
||||
return
|
||||
}
|
||||
|
||||
// GetSecret prompts the user for a password.
|
||||
// GetSecret prompts the user for a secret.
|
||||
func (t *terminalStdio) GetSecret(prompt string, minLen int) (password string, err error) {
|
||||
question := survey.Password{Message: prompt}
|
||||
opts := []survey.AskOpt{survey.WithStdio(t.Stdin, t.Stdout, t.Stderr)}
|
||||
@ -79,6 +79,24 @@ func (t *terminalStdio) GetSecret(prompt string, minLen int) (password string, e
|
||||
return
|
||||
}
|
||||
|
||||
// GetPassword prompts the user for a secret twice, and inputs must match.
|
||||
// Uses stdio.MinPasswordLen as the minimum input length
|
||||
func (t *terminalStdio) GetPassword(prompt string) (string, error) {
|
||||
pass1, err := t.GetSecret(prompt, MinPasswordLen)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Don't bother with the length check the 2nd time, since we check equality to pass1.
|
||||
pass2, err := t.GetSecret(prompt+" again", 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if pass1 == pass2 {
|
||||
return pass1, nil
|
||||
}
|
||||
return "", t.Error("Passwords do not match")
|
||||
}
|
||||
|
||||
// GetConfirm asks the user for a y/n answer to a prompt.
|
||||
func (t *terminalStdio) GetConfirm(prompt string) (answer bool) {
|
||||
question := survey.Confirm{
|
||||
|
@ -2,6 +2,8 @@ package stdio
|
||||
|
||||
import "io"
|
||||
|
||||
const MinPasswordLen = 8
|
||||
|
||||
type StdIO interface {
|
||||
io.Writer
|
||||
WriteErr(p []byte) (n int, err error)
|
||||
@ -9,5 +11,6 @@ type StdIO interface {
|
||||
Error(message string) error
|
||||
GetStringInput(prompt, defaultValue string) (string, error)
|
||||
GetSecret(prompt string, minLen int) (string, error)
|
||||
GetPassword(prompt string) (string, error)
|
||||
GetConfirm(prompt string) bool
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user