code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/api_token_list.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  	"errors"
    20  	"fmt"
    21  	"io"
    22  	"time"
    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/paths"
    28  	"code.vegaprotocol.io/vega/wallet/service/v2/connections"
    29  	tokenStoreV1 "code.vegaprotocol.io/vega/wallet/service/v2/connections/store/longliving/v1"
    30  
    31  	"github.com/spf13/cobra"
    32  )
    33  
    34  var (
    35  	listAPITokensLong = cli.LongDesc(`
    36  		List all the registered long-living API tokens
    37  	`)
    38  
    39  	listAPITokensExample = cli.Examples(`
    40  		# List the long-living API tokens
    41  		{{.Software}} api-token list
    42  	`)
    43  )
    44  
    45  type ListAPITokensHandler func(f ListAPITokensFlags) (connections.ListAPITokensResult, error)
    46  
    47  func NewCmdListAPITokens(w io.Writer, rf *RootFlags) *cobra.Command {
    48  	h := func(f ListAPITokensFlags) (connections.ListAPITokensResult, error) {
    49  		vegaPaths := paths.New(rf.Home)
    50  
    51  		tokenStore, err := tokenStoreV1.InitialiseStore(vegaPaths, f.passphrase)
    52  		if err != nil {
    53  			if errors.Is(err, tokenStoreV1.ErrWrongPassphrase) {
    54  				return connections.ListAPITokensResult{}, fmt.Errorf("could not unlock the token store: %w", err)
    55  			}
    56  			return connections.ListAPITokensResult{}, fmt.Errorf("couldn't load the token store: %w", err)
    57  		}
    58  		defer tokenStore.Close()
    59  
    60  		return connections.ListAPITokens(tokenStore)
    61  	}
    62  
    63  	return BuildCmdListAPITokens(w, ensureAPITokenStoreIsInit, h, rf)
    64  }
    65  
    66  func BuildCmdListAPITokens(w io.Writer, preCheck APITokenPreCheck, handler ListAPITokensHandler, rf *RootFlags) *cobra.Command {
    67  	f := &ListAPITokensFlags{}
    68  
    69  	cmd := &cobra.Command{
    70  		Use:     "list",
    71  		Short:   "List all the registered long-living API tokens",
    72  		Long:    listAPITokensLong,
    73  		Example: listAPITokensExample,
    74  		RunE: func(_ *cobra.Command, _ []string) error {
    75  			if err := preCheck(rf); err != nil {
    76  				return err
    77  			}
    78  
    79  			if err := f.Validate(); err != nil {
    80  				return err
    81  			}
    82  
    83  			res, err := handler(*f)
    84  			if err != nil {
    85  				return err
    86  			}
    87  
    88  			switch rf.Output {
    89  			case flags.InteractiveOutput:
    90  				printListAPITokens(w, res)
    91  			case flags.JSONOutput:
    92  				return printer.FprintJSON(w, res)
    93  			}
    94  			return nil
    95  		},
    96  	}
    97  
    98  	cmd.Flags().StringVar(&f.PassphraseFile,
    99  		"passphrase-file",
   100  		"",
   101  		"Path to the file containing the tokens database passphrase",
   102  	)
   103  
   104  	return cmd
   105  }
   106  
   107  type ListAPITokensFlags struct {
   108  	PassphraseFile string
   109  	passphrase     string
   110  }
   111  
   112  func (f *ListAPITokensFlags) Validate() error {
   113  	passphrase, err := flags.GetPassphrase(f.PassphraseFile)
   114  	if err != nil {
   115  		return err
   116  	}
   117  	f.passphrase = passphrase
   118  	return nil
   119  }
   120  
   121  func printListAPITokens(w io.Writer, resp connections.ListAPITokensResult) {
   122  	p := printer.NewInteractivePrinter(w)
   123  
   124  	str := p.String()
   125  	defer p.Print(str)
   126  
   127  	if len(resp.Tokens) == 0 {
   128  		str.InfoText("No tokens registered.").NextLine()
   129  		return
   130  	}
   131  
   132  	for i, token := range resp.Tokens {
   133  		str.Text("- ").WarningText(token.Token.String()).NextLine()
   134  		if token.Description != "" {
   135  			str.Text("  ").Text(token.Description).NextLine()
   136  		}
   137  		str.Pad().Text("Created at: ").Text(token.CreationDate.String())
   138  		if token.ExpirationDate != nil {
   139  			str.NextLine().Pad().Text("Expiration date: ").Text(token.ExpirationDate.String())
   140  			if !token.ExpirationDate.After(time.Now()) {
   141  				str.Text(" (expired)")
   142  			}
   143  		}
   144  
   145  		if i == len(resp.Tokens)-1 {
   146  			str.NextLine()
   147  		} else {
   148  			str.NextSection()
   149  		}
   150  	}
   151  }