github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/commands/utils.go (about)

     1  package commands
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"strings"
     7  
     8  	"golang.org/x/term"
     9  )
    10  
    11  // GetPassword fetches the password using the provided prompt, if any
    12  func (io *IOImpl) GetPassword(
    13  	prompt string,
    14  	insecure bool,
    15  ) (string, error) {
    16  	if prompt != "" {
    17  		// Print out the prompt
    18  		// On stderr, so it isn't part of bash output
    19  		io.ErrPrintln(prompt)
    20  	}
    21  
    22  	if insecure {
    23  		return io.readLine()
    24  	}
    25  
    26  	return readPassword()
    27  }
    28  
    29  // readLine reads a new line from standard input
    30  func (io *IOImpl) readLine() (string, error) {
    31  	input, err := io.inBuf.ReadString('\n')
    32  	if err != nil {
    33  		return "", err
    34  	}
    35  
    36  	return input[:len(input)-1], nil
    37  }
    38  
    39  // readPassword reads the password from a terminal
    40  // without local echo
    41  func readPassword() (string, error) {
    42  	fd := int(os.Stdin.Fd())
    43  
    44  	inputPass, err := term.ReadPassword(fd)
    45  	if err != nil {
    46  		return "", err
    47  	}
    48  
    49  	return string(inputPass), nil
    50  }
    51  
    52  // GetConfirmation will request user give the confirmation from stdin.
    53  // "y", "Y", "yes", "YES", and "Yes" all count as confirmations.
    54  // If the input is not recognized, it returns false and a nil error.
    55  func (io *IOImpl) GetConfirmation(prompt string) (bool, error) {
    56  	// On stderr so it isn't part of bash output.
    57  	io.ErrPrintfln("%s [y/n]:", prompt)
    58  
    59  	response, err := io.readLine()
    60  	if err != nil {
    61  		return false, err
    62  	}
    63  
    64  	response = strings.TrimSpace(response)
    65  	if len(response) == 0 {
    66  		return false, nil
    67  	}
    68  
    69  	response = strings.ToLower(response)
    70  	if response[0] == 'y' {
    71  		return true, nil
    72  	}
    73  
    74  	return false, nil
    75  }
    76  
    77  // GetCheckPassword will prompt for a password twice to verify they
    78  // match (for creating a new password).
    79  // It enforces the password length. Only parses password once if
    80  // input is piped in.
    81  func (io *IOImpl) GetCheckPassword(
    82  	prompts [2]string,
    83  	insecure bool,
    84  ) (string, error) {
    85  	pass, err := io.GetPassword(prompts[0], insecure)
    86  	if err != nil {
    87  		return "", err
    88  	}
    89  
    90  	pass2, err := io.GetPassword(prompts[1], insecure)
    91  	if err != nil {
    92  		return "", err
    93  	}
    94  
    95  	if pass != pass2 {
    96  		return "", errors.New("passphrases don't match")
    97  	}
    98  
    99  	return pass, nil
   100  }
   101  
   102  // GetString simply returns the trimmed string output of a given reader.
   103  func (io *IOImpl) GetString(prompt string) (string, error) {
   104  	if prompt != "" {
   105  		// On stderr so it isn't part of bash output.
   106  		io.ErrPrintln(prompt)
   107  	}
   108  
   109  	out, err := io.readLine()
   110  	if err != nil {
   111  		return "", err
   112  	}
   113  
   114  	return strings.TrimSpace(out), nil
   115  }