code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/api_token_describe.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  	describeAPITokenLong = cli.LongDesc(`
    36  		Describe a long-living API tokens and its configuration
    37  	`)
    38  
    39  	describeAPITokenExample = cli.Examples(`
    40  		# Describe a long-living API tokens
    41  		{{.Software}} api-token describe --token TOKEN
    42  	`)
    43  )
    44  
    45  type DescribeAPITokenHandler func(f DescribeAPITokenFlags) (connections.TokenDescription, error)
    46  
    47  func NewCmdDescribeAPIToken(w io.Writer, rf *RootFlags) *cobra.Command {
    48  	h := func(f DescribeAPITokenFlags) (connections.TokenDescription, 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.TokenDescription{}, fmt.Errorf("could not unlock the token store: %w", err)
    55  			}
    56  			return connections.TokenDescription{}, fmt.Errorf("couldn't load the token store: %w", err)
    57  		}
    58  		defer tokenStore.Close()
    59  
    60  		return connections.DescribeAPIToken(tokenStore, f.Token)
    61  	}
    62  
    63  	return BuildCmdDescribeAPIToken(w, ensureAPITokenStoreIsInit, h, rf)
    64  }
    65  
    66  func BuildCmdDescribeAPIToken(w io.Writer, preCheck APITokenPreCheck, handler DescribeAPITokenHandler, rf *RootFlags) *cobra.Command {
    67  	f := &DescribeAPITokenFlags{}
    68  
    69  	cmd := &cobra.Command{
    70  		Use:     "describe",
    71  		Short:   "Describe the token and its configuration",
    72  		Long:    describeAPITokenLong,
    73  		Example: describeAPITokenExample,
    74  		RunE: func(_ *cobra.Command, _ []string) error {
    75  			if err := preCheck(rf); err != nil {
    76  				return err
    77  			}
    78  
    79  			err := f.Validate()
    80  			if err != nil {
    81  				return err
    82  			}
    83  
    84  			res, err := handler(*f)
    85  			if err != nil {
    86  				return err
    87  			}
    88  
    89  			switch rf.Output {
    90  			case flags.InteractiveOutput:
    91  				printDescribeAPIToken(w, res)
    92  			case flags.JSONOutput:
    93  				return printer.FprintJSON(w, res)
    94  			}
    95  			return nil
    96  		},
    97  	}
    98  
    99  	cmd.Flags().StringVar(&f.Token,
   100  		"token",
   101  		"",
   102  		"Token to describe",
   103  	)
   104  	cmd.Flags().StringVar(&f.PassphraseFile,
   105  		"passphrase-file",
   106  		"",
   107  		"Path to the file containing the tokens database passphrase",
   108  	)
   109  
   110  	return cmd
   111  }
   112  
   113  type DescribeAPITokenFlags struct {
   114  	PassphraseFile string
   115  	Token          string
   116  	passphrase     string
   117  }
   118  
   119  func (f *DescribeAPITokenFlags) Validate() error {
   120  	if len(f.Token) == 0 {
   121  		return flags.MustBeSpecifiedError("token")
   122  	}
   123  
   124  	passphrase, err := flags.GetPassphrase(f.PassphraseFile)
   125  	if err != nil {
   126  		return err
   127  	}
   128  	f.passphrase = passphrase
   129  
   130  	return nil
   131  }
   132  
   133  func printDescribeAPIToken(w io.Writer, resp connections.TokenDescription) {
   134  	p := printer.NewInteractivePrinter(w)
   135  
   136  	str := p.String()
   137  	defer p.Print(str)
   138  
   139  	str.Text("Token:").NextLine()
   140  	str.WarningText(resp.Token.String()).NextSection()
   141  
   142  	if len(resp.Description) != 0 {
   143  		str.Text("Description:").NextLine()
   144  		str.WarningText(resp.Description).NextSection()
   145  	}
   146  	str.Text("Creation date:").NextLine()
   147  	str.WarningText(resp.CreationDate.String()).NextSection()
   148  
   149  	if resp.ExpirationDate != nil {
   150  		str.Text("Expiration date:").NextLine()
   151  		str.WarningText(resp.ExpirationDate.String())
   152  		if !resp.ExpirationDate.After(time.Now()) {
   153  			str.DangerBold(" (expired)")
   154  		}
   155  		str.NextSection()
   156  	}
   157  
   158  	str.Text("This token is linked to the wallet ").WarningText(resp.Wallet.Name).Text(".").NextLine()
   159  }