code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/api_token_generate.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 "time" 24 25 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli" 26 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags" 27 "code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer" 28 "code.vegaprotocol.io/vega/paths" 29 v2 "code.vegaprotocol.io/vega/wallet/service/v2" 30 "code.vegaprotocol.io/vega/wallet/service/v2/connections" 31 tokenStoreV1 "code.vegaprotocol.io/vega/wallet/service/v2/connections/store/longliving/v1" 32 "code.vegaprotocol.io/vega/wallet/wallets" 33 34 "github.com/spf13/cobra" 35 ) 36 37 var ( 38 generateAPITokenLong = cli.LongDesc(` 39 Generate a long-living API token 40 `) 41 42 generateAPITokenExample = cli.Examples(` 43 # Generate a long-living API token 44 {{.Software}} api-token generate --description DESCRIPTION --wallet-name WALLET 45 `) 46 ) 47 48 type GenerateAPITokenHandler func(f GenerateAPITokenFlags, params connections.GenerateAPITokenParams) (connections.Token, error) 49 50 func NewCmdGenerateAPIToken(w io.Writer, rf *RootFlags) *cobra.Command { 51 h := func(f GenerateAPITokenFlags, params connections.GenerateAPITokenParams) (connections.Token, error) { 52 vegaPaths := paths.New(rf.Home) 53 54 walletStore, err := wallets.InitialiseStoreFromPaths(vegaPaths, false) 55 if err != nil { 56 return "", fmt.Errorf("couldn't initialise wallets store: %w", err) 57 } 58 defer walletStore.Close() 59 60 tokenStore, err := tokenStoreV1.InitialiseStore(vegaPaths, f.passphrase) 61 if err != nil { 62 if errors.Is(err, tokenStoreV1.ErrWrongPassphrase) { 63 return "", fmt.Errorf("could not unlock the token store: %w", err) 64 } 65 return "", fmt.Errorf("couldn't load the token store: %w", err) 66 } 67 defer tokenStore.Close() 68 69 handler := connections.NewGenerateAPITokenHandler(walletStore, tokenStore, v2.NewStdTime()) 70 return handler.Handle(context.Background(), params) 71 } 72 73 return BuildCmdGenerateAPIToken(w, ensureAPITokenStoreIsInit, h, rf) 74 } 75 76 func BuildCmdGenerateAPIToken(w io.Writer, preCheck APITokenPreCheck, handler GenerateAPITokenHandler, rf *RootFlags) *cobra.Command { 77 f := &GenerateAPITokenFlags{} 78 79 cmd := &cobra.Command{ 80 Use: "generate", 81 Short: "Generate a long-living API token", 82 Long: generateAPITokenLong, 83 Example: generateAPITokenExample, 84 RunE: func(_ *cobra.Command, _ []string) error { 85 if err := preCheck(rf); err != nil { 86 return err 87 } 88 89 params, err := f.Validate() 90 if err != nil { 91 return err 92 } 93 94 res, err := handler(*f, params) 95 if err != nil { 96 return err 97 } 98 99 switch rf.Output { 100 case flags.InteractiveOutput: 101 printGeneratedAPIToken(w, params, res) 102 case flags.JSONOutput: 103 return printer.FprintJSON(w, struct { 104 Token connections.Token `json:"token"` 105 }{ 106 Token: res, 107 }) 108 } 109 return nil 110 }, 111 } 112 113 cmd.Flags().StringVar(&f.Description, 114 "description", 115 "", 116 "Description of the token purpose", 117 ) 118 119 cmd.Flags().StringVar(&f.PassphraseFile, 120 "tokens-passphrase-file", 121 "", 122 "Path to the file containing the tokens database passphrase", 123 ) 124 125 cmd.Flags().StringVar(&f.WalletName, 126 "wallet-name", 127 "", 128 "Name of the wallet associated to the token", 129 ) 130 131 cmd.Flags().StringVar(&f.WalletPassphraseFile, 132 "wallet-passphrase-file", 133 "", 134 "Path to the file containing the wallet's passphrase", 135 ) 136 137 cmd.Flags().DurationVar(&f.ExpiresIn, 138 "expires-in", 139 0, 140 "How duration for which the token will be valid", 141 ) 142 143 autoCompleteWallet(cmd, f.WalletName, "wallet-name") 144 145 return cmd 146 } 147 148 type GenerateAPITokenFlags struct { 149 Description string 150 PassphraseFile string 151 WalletName string 152 WalletPassphraseFile string 153 ExpiresIn time.Duration 154 passphrase string 155 } 156 157 func (f *GenerateAPITokenFlags) Validate() (connections.GenerateAPITokenParams, error) { 158 if len(f.WalletName) == 0 { 159 return connections.GenerateAPITokenParams{}, flags.MustBeSpecifiedError("wallet-name") 160 } 161 162 passphrase, err := flags.GetPassphraseWithOptions(flags.PassphraseOptions{Name: "tokens"}, f.PassphraseFile) 163 if err != nil { 164 return connections.GenerateAPITokenParams{}, err 165 } 166 f.passphrase = passphrase 167 168 walletPassphrase, err := flags.GetPassphraseWithOptions(flags.PassphraseOptions{Name: "wallet"}, f.WalletPassphraseFile) 169 if err != nil { 170 return connections.GenerateAPITokenParams{}, err 171 } 172 173 var expiresIn *time.Duration 174 if f.ExpiresIn != 0 { 175 expiresIn = &f.ExpiresIn 176 } 177 178 tokenParams := connections.GenerateAPITokenParams{ 179 Description: f.Description, 180 ExpiresIn: expiresIn, 181 Wallet: connections.GenerateAPITokenWalletParams{ 182 Name: f.WalletName, 183 Passphrase: walletPassphrase, 184 }, 185 } 186 params := tokenParams 187 return params, nil 188 } 189 190 func printGeneratedAPIToken(w io.Writer, params connections.GenerateAPITokenParams, token connections.Token) { 191 p := printer.NewInteractivePrinter(w) 192 193 str := p.String() 194 defer p.Print(str) 195 196 str.CheckMark().Text("The API token has been successfully generated: ").SuccessText(token.String()).NextSection() 197 198 str.RedArrow().DangerText("Important").NextLine() 199 str.DangerText("This token can be used by third-party applications to access the wallet ").DangerBold(params.Wallet.Name).DangerText(" and send transactions from it, automatically, without human intervention!").NextLine() 200 str.DangerBold("Only distribute it to applications you have absolute trust in.").NextLine() 201 }