github.com/nats-io/nsc/v2@v2.8.7-0.20240307184528-efd7023c6896/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/v2/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.Printf("no operators defined in store dir %q\n"+ 62 "init an environment or change the store root with `env --store <dir>`", config.StoreRoot) 63 } else { 64 sort.Strings(operators) 65 var infos []*EntryInfo 66 for _, v := range operators { 67 var i EntryInfo 68 infos = append(infos, &i) 69 i.Name = v 70 s, err := config.LoadStore(v) 71 if err != nil { 72 i.Err = err 73 continue 74 } 75 c, err := s.LoadRootClaim() 76 if err != nil { 77 i.Err = err 78 continue 79 } 80 if c == nil { 81 i.Err = fmt.Errorf("%q jwt not found", v) 82 continue 83 } 84 i.Claims = c 85 } 86 cmd.Println(listEntities("Operators", infos, config.Operator)) 87 } 88 89 return nil 90 }, 91 } 92 return cmd 93 } 94 95 func ListAccounts(s *store.Store) ([]*EntryInfo, error) { 96 accounts, err := s.ListSubContainers(store.Accounts) 97 if err != nil { 98 return nil, err 99 } 100 sort.Strings(accounts) 101 102 var infos []*EntryInfo 103 for _, v := range accounts { 104 var i EntryInfo 105 i.Name = v 106 infos = append(infos, &i) 107 ac, err := s.ReadAccountClaim(v) 108 if err != nil { 109 i.Err = err 110 continue 111 } 112 i.Claims = ac 113 } 114 return infos, nil 115 } 116 117 func createListAccountsCmd() *cobra.Command { 118 var operator string 119 120 cmd := &cobra.Command{ 121 Use: "accounts", 122 Short: "List accounts", 123 Args: MaxArgs(0), 124 RunE: func(cmd *cobra.Command, args []string) error { 125 config := GetConfig() 126 if config.StoreRoot == "" { 127 return errors.New("no store set - `env --store <dir>`") 128 } 129 if operator != "" { 130 if err := config.SetOperator(operator); err != nil { 131 return err 132 } 133 } 134 if config.Operator == "" { 135 return errors.New("no operator set - `env --operator <name>`") 136 } 137 containers, err := config.ListAccounts() 138 if err != nil { 139 return err 140 } 141 sort.Strings(containers) 142 s, err := config.LoadStore(config.Operator) 143 if err != nil { 144 return err 145 } 146 147 var infos []*EntryInfo 148 for _, v := range containers { 149 var i EntryInfo 150 i.Name = v 151 infos = append(infos, &i) 152 ac, err := s.ReadAccountClaim(v) 153 if err != nil { 154 i.Err = err 155 continue 156 } 157 i.Claims = ac 158 } 159 cmd.Println(listEntities("Accounts", infos, config.Account)) 160 return nil 161 }, 162 } 163 164 cmd.Flags().StringVarP(&operator, "operator", "o", "", "operator name") 165 166 return cmd 167 } 168 169 func ListUsers(s *store.Store, accountName string) ([]*EntryInfo, error) { 170 names, err := s.ListEntries(store.Accounts, accountName, store.Users) 171 if err != nil { 172 return nil, err 173 } 174 sort.Strings(names) 175 176 var infos []*EntryInfo 177 for _, v := range names { 178 var i EntryInfo 179 i.Name = v 180 infos = append(infos, &i) 181 uc, err := s.ReadUserClaim(accountName, v) 182 if err != nil { 183 i.Err = err 184 continue 185 } 186 if uc == nil { 187 i.Err = fmt.Errorf("%q jwt not found", v) 188 continue 189 } 190 i.Claims = uc 191 } 192 return infos, nil 193 } 194 195 func createListUsersCmd() *cobra.Command { 196 var operator string 197 var account string 198 cmd := &cobra.Command{ 199 Use: "users", 200 Short: "List users", 201 Args: MaxArgs(0), 202 RunE: func(cmd *cobra.Command, args []string) error { 203 config := GetConfig() 204 if config.StoreRoot == "" { 205 return fmt.Errorf("no store set - `%s env --store <dir>`", GetToolName()) 206 } 207 if operator != "" { 208 if err := config.SetOperator(operator); err != nil { 209 return err 210 } 211 } 212 if config.Operator == "" { 213 return fmt.Errorf("no operator set - `%s env --operator <name>`", GetToolName()) 214 } 215 if account != "" { 216 if err := config.SetAccount(account); err != nil { 217 return err 218 } 219 } 220 if config.Account == "" { 221 return fmt.Errorf("no account set - `%s env --account <name>`", GetToolName()) 222 } 223 224 s, err := config.LoadStore(config.Operator) 225 if err != nil { 226 return err 227 } 228 229 infos, err := ListUsers(s, config.Account) 230 if err != nil { 231 return err 232 } 233 234 cmd.Println(listEntities("Users", infos, config.Account)) 235 return nil 236 }, 237 } 238 239 cmd.Flags().StringVarP(&operator, "operator", "o", "", "operator name") 240 cmd.Flags().StringVarP(&account, "account", "a", "", "account name") 241 242 return cmd 243 } 244 245 func listEntities(title string, infos []*EntryInfo, current string) string { 246 table := tablewriter.CreateTable() 247 table.AddTitle(title) 248 if len(infos) == 0 { 249 table.AddRow("No entries defined") 250 } else { 251 table.AddHeaders("Name", "Public Key") 252 for _, v := range infos { 253 n := v.Name 254 var p string 255 if v.Err != nil || v.Claims == nil { 256 p = fmt.Sprintf("error loading jwt - %v", v.Err) 257 } else { 258 c := v.Claims.Claims() 259 if c != nil { 260 tn := c.Name 261 if n != tn { 262 n = fmt.Sprintf("%s (%s)", n, c.Name) 263 } 264 p = c.Subject 265 } 266 } 267 if n == current { 268 n = cli.Bold(n) 269 p = cli.Bold(p) 270 } 271 table.AddRow(n, p) 272 } 273 } 274 return table.Render() 275 }