Skip to content

Commit 668f874

Browse files
committed
chore: refactor PromptForInput
Signed-off-by: Alano Terblanche <[email protected]>
1 parent dd22e09 commit 668f874

2 files changed

Lines changed: 24 additions & 34 deletions

File tree

cli/command/registry.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,13 @@ func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, auth
142142
return errors.Errorf("Error: Non-null Username Required")
143143
}
144144
if flPassword == "" {
145-
var err error
146-
flPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ", WithHideUserInput(true))
145+
restoreInput, err := DisableInputEcho(cli.In())
146+
if err != nil {
147+
return err
148+
}
149+
defer restoreInput()
150+
151+
flPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ")
147152
if err != nil {
148153
return err
149154
}

cli/command/utils.go

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,20 @@ func PrettyPrint(i any) string {
7777

7878
var ErrPromptTerminated = errdefs.Cancelled(errors.New("prompt terminated"))
7979

80-
type promptOptions struct {
81-
disableEcho bool
82-
}
83-
84-
type PromptOptions func(*promptOptions)
85-
86-
func WithHideUserInput(t bool) PromptOptions {
87-
return func(p *promptOptions) {
88-
p.disableEcho = t
80+
// DisableInputEcho disables input echo on the provided io.ReadCloser.
81+
// This is useful when the user provides sensitive information like passwords.
82+
// The function returns a restore function that should be called to restore the
83+
// terminal state.
84+
func DisableInputEcho(in io.ReadCloser) (restore func() error, err error) {
85+
ins := streams.NewIn(in)
86+
oldState, err := term.SaveState(ins.FD())
87+
if err != nil {
88+
return nil, err
89+
}
90+
restore = func() error {
91+
return term.RestoreTerminal(ins.FD(), oldState)
8992
}
93+
return restore, term.DisableEcho(ins.FD(), oldState)
9094
}
9195

9296
// PromptForInput requests input from the user.
@@ -96,29 +100,10 @@ func WithHideUserInput(t bool) PromptOptions {
96100
// When the prompt returns an error, the caller should propagate the error up
97101
// the stack and close the io.Reader used for the prompt which will prevent the
98102
// background goroutine from blocking indefinitely.
99-
func PromptForInput(ctx context.Context, ins *streams.In, outs *streams.Out, message string, opts ...PromptOptions) (string, error) {
100-
options := promptOptions{}
101-
for _, o := range opts {
102-
o(&options)
103-
}
103+
func PromptForInput(ctx context.Context, in io.ReadCloser, out io.Writer, message string) (string, error) {
104+
_, _ = fmt.Fprint(out, message)
104105

105-
_, _ = fmt.Fprint(outs, message)
106-
107-
if options.disableEcho {
108-
oldState, err := term.SaveState(ins.FD())
109-
if err != nil {
110-
return "", err
111-
}
112-
_ = term.DisableEcho(ins.FD(), oldState)
113-
defer func() {
114-
_ = term.RestoreTerminal(ins.FD(), oldState)
115-
}()
116-
}
117-
118-
// On Windows, force the use of the regular OS stdin stream.
119-
if runtime.GOOS == "windows" {
120-
ins = streams.NewIn(os.Stdin)
121-
}
106+
ins := streams.NewIn(in)
122107

123108
result := make(chan string)
124109

@@ -131,7 +116,7 @@ func PromptForInput(ctx context.Context, ins *streams.In, outs *streams.Out, mes
131116

132117
select {
133118
case <-ctx.Done():
134-
_, _ = fmt.Fprintln(outs, "")
119+
_, _ = fmt.Fprintln(out, "")
135120
return "", ErrPromptTerminated
136121
case r := <-result:
137122
return r, nil

0 commit comments

Comments
 (0)