code.vegaprotocol.io/vega@v0.79.0/core/config/flags.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package config 17 18 import ( 19 "errors" 20 "fmt" 21 "io/ioutil" 22 "os" 23 "strings" 24 25 vgos "code.vegaprotocol.io/vega/libs/os" 26 27 "golang.org/x/crypto/ssh/terminal" 28 ) 29 30 // Empty is used when a command or sub-command receives no argument and has no execution. 31 type Empty struct{} 32 33 var ( 34 ErrPassphraseDoNotMatch = errors.New("passphrase do not match") 35 36 supportedOutputs = []string{ 37 "json", 38 "human", 39 } 40 ) 41 42 type OutputFlag struct { 43 Output Output `default:"human" description:"Specify the output format: json,human" long:"output" required:"true"` 44 } 45 46 func (f OutputFlag) GetOutput() (Output, error) { 47 outputStr := string(f.Output) 48 if !isSupportedOutput(outputStr) { 49 return "", fmt.Errorf("unsupported output \"%s\"", outputStr) 50 } 51 if f.Output == "human" && vgos.HasNoTTY() { 52 return "", errors.New("output \"human\" is not script-friendly, use \"json\" instead") 53 } 54 return f.Output, nil 55 } 56 57 func isSupportedOutput(output string) bool { 58 for _, o := range supportedOutputs { 59 if output == o { 60 return true 61 } 62 } 63 return false 64 } 65 66 type Output string 67 68 func (o Output) IsHuman() bool { 69 return string(o) == "human" 70 } 71 72 func (o Output) IsJSON() bool { 73 return string(o) == "json" 74 } 75 76 type VegaHomeFlag struct { 77 VegaHome string `description:"Path to the custom home for vega" long:"home"` 78 } 79 80 type PassphraseFlag struct { 81 PassphraseFile Passphrase `description:"A file containing the passphrase for the wallet, if empty will prompt for input" long:"passphrase-file" short:"p"` 82 } 83 84 type Passphrase string 85 86 func (p Passphrase) Get(prompt string, withConfirmation bool) (string, error) { 87 if len(p) == 0 { 88 if vgos.HasNoTTY() { 89 return "", errors.New("passphrase-file flag required without TTY") 90 } 91 return p.getFromUser(prompt, withConfirmation) 92 } 93 94 return p.getFromFile(string(p)) 95 } 96 97 func (p Passphrase) getFromUser(prompt string, withConfirmation bool) (string, error) { 98 passphrase, err := promptForPassphrase(fmt.Sprintf("Enter %s passphrase:", prompt)) 99 if err != nil { 100 return "", err 101 } 102 103 if withConfirmation { 104 passphraseConfirmation, err := promptForPassphrase(fmt.Sprintf("Confirm %s passphrase:", prompt)) 105 if err != nil { 106 return "", err 107 } 108 109 if passphrase != passphraseConfirmation { 110 return "", ErrPassphraseDoNotMatch 111 } 112 } 113 114 return passphrase, nil 115 } 116 117 func promptForPassphrase(msg string) (string, error) { 118 fmt.Print(msg) 119 password, err := terminal.ReadPassword(int(os.Stdin.Fd())) 120 if err != nil { 121 return "", fmt.Errorf("failed to read passphrase input: %w", err) 122 } 123 fmt.Println() 124 125 return string(password), nil 126 } 127 128 func (p Passphrase) getFromFile(path string) (string, error) { 129 buf, err := ioutil.ReadFile(path) 130 if err != nil { 131 return "", err 132 } 133 134 return strings.TrimRight(string(buf), "\n"), nil 135 } 136 137 type PromptString string 138 139 // Get returns a string if set or prompts user otherwise. 140 func (p PromptString) Get(prompt, name string) (string, error) { 141 if len(p) == 0 { 142 if vgos.HasNoTTY() { 143 return "", fmt.Errorf("%s flag required without TTY", name) 144 } 145 return p.getFromUser(prompt) 146 } 147 148 return string(p), nil 149 } 150 151 func (p PromptString) getFromUser(prompt string) (string, error) { 152 var s string 153 fmt.Printf("Enter %s:", prompt) 154 defer func() { fmt.Printf("\n") }() 155 if _, err := fmt.Scanf("%s", &s); err != nil { 156 return "", fmt.Errorf("failed read the input: %w", err) 157 } 158 159 return s, nil 160 }