github.com/nats-io/nsc@v0.0.0-20221206222106-35db9400b257/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 cli "github.com/nats-io/cliprompts/v2" 24 "github.com/nats-io/jwt/v2" 25 "github.com/nats-io/nsc/cmd/store" 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 }