code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/key_annotate.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 cmd 17 18 import ( 19 "context" 20 "errors" 21 "fmt" 22 "io" 23 24 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli" 25 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags" 26 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer" 27 "code.vegaprotocol.io/vega/wallet/api" 28 "code.vegaprotocol.io/vega/wallet/wallets" 29 30 "github.com/spf13/cobra" 31 ) 32 33 var ( 34 annotateKeyLong = cli.LongDesc(` 35 Add metadata to a key pair. All existing metadata is removed and replaced 36 by the specified new metadata. 37 38 The metadata is a list of key-value pairs. A key-value is colon-separated, 39 and the key-values are comma-separated. 40 41 It is possible to give a name to a key pair, that is recognised by user 42 interfaces, by setting the metadata "name". 43 `) 44 45 annotateKeyExample = cli.Examples(` 46 Given the following metadata to be added: 47 - name: my-wallet 48 - type: validation 49 50 # Annotate a key pair 51 {{.Software}} key annotate --wallet WALLET --pubkey PUBKEY --meta "name:my-wallet,type:validation" 52 53 # Remove all metadata from a key pair 54 {{.Software}} key annotate --wallet WALLET --pubkey PUBKEY --clear 55 `) 56 ) 57 58 type AnnotateKeyHandler func(api.AdminAnnotateKeyParams, string) (api.AdminAnnotateKeyResult, error) 59 60 func NewCmdAnnotateKey(w io.Writer, rf *RootFlags) *cobra.Command { 61 h := func(params api.AdminAnnotateKeyParams, passphrase string) (api.AdminAnnotateKeyResult, error) { 62 ctx := context.Background() 63 64 walletStore, err := wallets.InitialiseStore(rf.Home, false) 65 if err != nil { 66 return api.AdminAnnotateKeyResult{}, fmt.Errorf("couldn't initialise wallets store: %w", err) 67 } 68 defer walletStore.Close() 69 70 if _, errDetails := api.NewAdminUnlockWallet(walletStore).Handle(ctx, api.AdminUnlockWalletParams{ 71 Wallet: params.Wallet, 72 Passphrase: passphrase, 73 }); errDetails != nil { 74 return api.AdminAnnotateKeyResult{}, errors.New(errDetails.Data) 75 } 76 77 rawResult, errDetails := api.NewAdminAnnotateKey(walletStore).Handle(ctx, params) 78 if errDetails != nil { 79 return api.AdminAnnotateKeyResult{}, errors.New(errDetails.Data) 80 } 81 return rawResult.(api.AdminAnnotateKeyResult), nil 82 } 83 84 return BuildCmdAnnotateKey(w, h, rf) 85 } 86 87 func BuildCmdAnnotateKey(w io.Writer, handler AnnotateKeyHandler, rf *RootFlags) *cobra.Command { 88 f := AnnotateKeyFlags{} 89 90 cmd := &cobra.Command{ 91 Use: "annotate", 92 Short: "Add metadata to a key pair", 93 Long: annotateKeyLong, 94 Example: annotateKeyExample, 95 RunE: func(_ *cobra.Command, _ []string) error { 96 req, pass, err := f.Validate() 97 if err != nil { 98 return err 99 } 100 101 resp, err := handler(req, pass) 102 if err != nil { 103 return err 104 } 105 106 switch rf.Output { 107 case flags.InteractiveOutput: 108 PrintAnnotateKeyResponse(w, f, resp) 109 case flags.JSONOutput: 110 return printer.FprintJSON(w, resp) 111 } 112 113 return nil 114 }, 115 } 116 117 cmd.Flags().StringVarP(&f.Wallet, 118 "wallet", "w", 119 "", 120 "Wallet holding the public key", 121 ) 122 cmd.Flags().StringVarP(&f.PassphraseFile, 123 "passphrase-file", "p", 124 "", 125 "Path to the file containing the wallet's passphrase", 126 ) 127 cmd.Flags().StringVarP(&f.PubKey, 128 "pubkey", "k", 129 "", 130 "Public key to annotate (hex-encoded)", 131 ) 132 cmd.Flags().StringSliceVarP(&f.RawMetadata, 133 "meta", "m", 134 []string{}, 135 `A list of metadata e.g: "my-key1:my-value1,my-key2:my-value2"`, 136 ) 137 cmd.Flags().BoolVar(&f.Clear, 138 "clear", 139 false, 140 "Clear the metadata", 141 ) 142 143 autoCompleteWallet(cmd, rf.Home, "wallet") 144 145 return cmd 146 } 147 148 type AnnotateKeyFlags struct { 149 Wallet string 150 PubKey string 151 PassphraseFile string 152 Clear bool 153 RawMetadata []string 154 } 155 156 func (f *AnnotateKeyFlags) Validate() (api.AdminAnnotateKeyParams, string, error) { 157 if len(f.Wallet) == 0 { 158 return api.AdminAnnotateKeyParams{}, "", flags.MustBeSpecifiedError("wallet") 159 } 160 161 if len(f.PubKey) == 0 { 162 return api.AdminAnnotateKeyParams{}, "", flags.MustBeSpecifiedError("pubkey") 163 } 164 165 if len(f.RawMetadata) == 0 && !f.Clear { 166 return api.AdminAnnotateKeyParams{}, "", flags.OneOfFlagsMustBeSpecifiedError("meta", "clear") 167 } 168 if len(f.RawMetadata) != 0 && f.Clear { 169 return api.AdminAnnotateKeyParams{}, "", flags.MutuallyExclusiveError("meta", "clear") 170 } 171 172 metadata, err := cli.ParseMetadata(f.RawMetadata) 173 if err != nil { 174 return api.AdminAnnotateKeyParams{}, "", err 175 } 176 177 passphrase, err := flags.GetPassphrase(f.PassphraseFile) 178 if err != nil { 179 return api.AdminAnnotateKeyParams{}, "", err 180 } 181 182 return api.AdminAnnotateKeyParams{ 183 Wallet: f.Wallet, 184 PublicKey: f.PubKey, 185 Metadata: metadata, 186 }, passphrase, nil 187 } 188 189 func PrintAnnotateKeyResponse(w io.Writer, f AnnotateKeyFlags, res api.AdminAnnotateKeyResult) { 190 p := printer.NewInteractivePrinter(w) 191 str := p.String() 192 defer p.Print(str) 193 if f.Clear { 194 str.CheckMark().SuccessText("Annotation cleared").NextLine() 195 } else { 196 str.CheckMark().SuccessText("Annotation succeeded").NextSection() 197 } 198 str.Text("New metadata:").NextLine() 199 printMeta(str, res.Metadata) 200 }