github.com/kbehouse/nsc@v0.0.6/cmd/list.go (about)

     1  /*
     2   * Copyright 2018-2020 The NATS Authors
     3   * Licensed under the Apache License, Version 2.0 (the "License");
     4   * you may not use this file except in compliance with the License.
     5   * You may obtain a copy of the License at
     6   *
     7   * http://www.apache.org/licenses/LICENSE-2.0
     8   *
     9   * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15  
    16  package cmd
    17  
    18  import (
    19  	"errors"
    20  	"fmt"
    21  	"sort"
    22  
    23  	"github.com/kbehouse/nsc/cmd/store"
    24  	cli "github.com/nats-io/cliprompts/v2"
    25  	"github.com/nats-io/jwt/v2"
    26  	"github.com/spf13/cobra"
    27  	"github.com/xlab/tablewriter"
    28  )
    29  
    30  // addCmd represents the add command
    31  var listCmd = &cobra.Command{
    32  	Use:   "list",
    33  	Short: "List assets such as accounts, imports, users",
    34  }
    35  
    36  func init() {
    37  	GetRootCmd().AddCommand(listCmd)
    38  	listCmd.AddCommand(createListOperatorsCmd())
    39  	listCmd.AddCommand(createListAccountsCmd())
    40  	listCmd.AddCommand(CreateListUsersCmd())
    41  }
    42  
    43  type EntryInfo struct {
    44  	Name   string
    45  	Claims jwt.Claims
    46  	Err    error
    47  }
    48  
    49  func createListOperatorsCmd() *cobra.Command {
    50  	cmd := &cobra.Command{
    51  		Use:   "operators",
    52  		Short: "List operators",
    53  		Args:  MaxArgs(0),
    54  		RunE: func(cmd *cobra.Command, args []string) error {
    55  			config := GetConfig()
    56  			if config.StoreRoot == "" {
    57  				return errors.New("no store set - `env --store <dir>`")
    58  			}
    59  			operators := config.ListOperators()
    60  			if len(operators) == 0 {
    61  				fmt.Println("no operators defined - init an environment")
    62  			} else {
    63  				sort.Strings(operators)
    64  				var infos []*EntryInfo
    65  				for _, v := range operators {
    66  					var i EntryInfo
    67  					infos = append(infos, &i)
    68  					i.Name = v
    69  					s, err := config.LoadStore(v)
    70  					if err != nil {
    71  						i.Err = err
    72  						continue
    73  					}
    74  					c, err := s.LoadRootClaim()
    75  					if err != nil {
    76  						i.Err = err
    77  						continue
    78  					}
    79  					if c == nil {
    80  						i.Err = fmt.Errorf("%q jwt not found", v)
    81  						continue
    82  					}
    83  					i.Claims = c
    84  				}
    85  				cmd.Println(listEntities("Operators", infos, config.Operator))
    86  			}
    87  
    88  			return nil
    89  		},
    90  	}
    91  	return cmd
    92  }
    93  
    94  func ListAccounts(s *store.Store) ([]*EntryInfo, error) {
    95  	accounts, err := s.ListSubContainers(store.Accounts)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	sort.Strings(accounts)
   100  
   101  	var infos []*EntryInfo
   102  	for _, v := range accounts {
   103  		var i EntryInfo
   104  		i.Name = v
   105  		infos = append(infos, &i)
   106  		ac, err := s.ReadAccountClaim(v)
   107  		if err != nil {
   108  			i.Err = err
   109  			continue
   110  		}
   111  		i.Claims = ac
   112  	}
   113  	return infos, nil
   114  }
   115  
   116  func createListAccountsCmd() *cobra.Command {
   117  	var operator string
   118  
   119  	cmd := &cobra.Command{
   120  		Use:   "accounts",
   121  		Short: "List accounts",
   122  		Args:  MaxArgs(0),
   123  		RunE: func(cmd *cobra.Command, args []string) error {
   124  			config := GetConfig()
   125  			if config.StoreRoot == "" {
   126  				return errors.New("no store set - `env --store <dir>`")
   127  			}
   128  			if operator != "" {
   129  				if err := config.SetOperator(operator); err != nil {
   130  					return err
   131  				}
   132  			}
   133  			if config.Operator == "" {
   134  				return errors.New("no operator set - `env --operator <name>`")
   135  			}
   136  			containers, err := config.ListAccounts()
   137  			if err != nil {
   138  				return err
   139  			}
   140  			sort.Strings(containers)
   141  			s, err := config.LoadStore(config.Operator)
   142  			if err != nil {
   143  				return err
   144  			}
   145  
   146  			var infos []*EntryInfo
   147  			for _, v := range containers {
   148  				var i EntryInfo
   149  				i.Name = v
   150  				infos = append(infos, &i)
   151  				ac, err := s.ReadAccountClaim(v)
   152  				if err != nil {
   153  					i.Err = err
   154  					continue
   155  				}
   156  				i.Claims = ac
   157  			}
   158  			cmd.Println(listEntities("Accounts", infos, config.Account))
   159  			return nil
   160  		},
   161  	}
   162  
   163  	cmd.Flags().StringVarP(&operator, "operator", "o", "", "operator name")
   164  
   165  	return cmd
   166  }
   167  
   168  func ListUsers(s *store.Store, accountName string) ([]*EntryInfo, error) {
   169  	names, err := s.ListEntries(store.Accounts, accountName, store.Users)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	sort.Strings(names)
   174  
   175  	var infos []*EntryInfo
   176  	for _, v := range names {
   177  		var i EntryInfo
   178  		i.Name = v
   179  		infos = append(infos, &i)
   180  		uc, err := s.ReadUserClaim(accountName, v)
   181  		if err != nil {
   182  			i.Err = err
   183  			continue
   184  		}
   185  		if uc == nil {
   186  			i.Err = fmt.Errorf("%q jwt not found", v)
   187  			continue
   188  		}
   189  		i.Claims = uc
   190  	}
   191  	return infos, nil
   192  }
   193  
   194  func CreateListUsersCmd() *cobra.Command {
   195  	var operator string
   196  	var account string
   197  	cmd := &cobra.Command{
   198  		Use:   "users",
   199  		Short: "List users",
   200  		Args:  MaxArgs(0),
   201  		RunE: func(cmd *cobra.Command, args []string) error {
   202  			config := GetConfig()
   203  			if config.StoreRoot == "" {
   204  				return fmt.Errorf("no store set - `%s env --store <dir>`", GetToolName())
   205  			}
   206  			if operator != "" {
   207  				if err := config.SetOperator(operator); err != nil {
   208  					return err
   209  				}
   210  			}
   211  			if config.Operator == "" {
   212  				return fmt.Errorf("no operator set - `%s env --operator <name>`", GetToolName())
   213  			}
   214  			if account != "" {
   215  				if err := config.SetAccount(account); err != nil {
   216  					return err
   217  				}
   218  			}
   219  			if config.Account == "" {
   220  				return fmt.Errorf("no account set - `%s env --account <name>`", GetToolName())
   221  			}
   222  
   223  			s, err := config.LoadStore(config.Operator)
   224  			if err != nil {
   225  				return err
   226  			}
   227  
   228  			infos, err := ListUsers(s, config.Account)
   229  			if err != nil {
   230  				return err
   231  			}
   232  
   233  			cmd.Println(listEntities("Users", infos, config.Account))
   234  			return nil
   235  		},
   236  	}
   237  
   238  	cmd.Flags().StringVarP(&operator, "operator", "o", "", "operator name")
   239  	cmd.Flags().StringVarP(&account, "account", "a", "", "account name")
   240  
   241  	return cmd
   242  }
   243  
   244  func listEntities(title string, infos []*EntryInfo, current string) string {
   245  	table := tablewriter.CreateTable()
   246  	table.AddTitle(title)
   247  	if len(infos) == 0 {
   248  		table.AddRow("No entries defined")
   249  	} else {
   250  		table.AddHeaders("Name", "Public Key")
   251  		for _, v := range infos {
   252  			n := v.Name
   253  			var p string
   254  			if v.Err != nil || v.Claims == nil {
   255  				p = fmt.Sprintf("error loading jwt - %v", v.Err)
   256  			} else {
   257  				c := v.Claims.Claims()
   258  				if c != nil {
   259  					tn := c.Name
   260  					if n != tn {
   261  						n = fmt.Sprintf("%s (%s)", n, c.Name)
   262  					}
   263  					p = c.Subject
   264  				}
   265  			}
   266  			if n == current {
   267  				n = cli.Bold(n)
   268  				p = cli.Bold(p)
   269  			}
   270  			table.AddRow(n, p)
   271  		}
   272  	}
   273  	return table.Render()
   274  }