github.com/kbehouse/nsc@v0.0.6/cmd/importcollector.go (about) 1 /* 2 * Copyright 2018-2019 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 "github.com/nats-io/jwt/v2" 25 ) 26 27 type AccountExport struct { 28 OperatorName string 29 jwt.AccountClaims 30 } 31 32 func (ae *AccountExport) Choices() []AccountExportChoice { 33 var choices []AccountExportChoice 34 // choice without a selection is an account label 35 choices = append(choices, AccountExportChoice{AccountExport: *ae}) 36 for _, v := range ae.Exports { 37 choices = append(choices, AccountExportChoice{*ae, v}) 38 } 39 return choices 40 } 41 42 type ByAccountName []AccountExport 43 44 func (a ByAccountName) Len() int { return len(a) } 45 func (a ByAccountName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 46 func (a ByAccountName) Less(i, j int) bool { return a[i].Name < a[j].Name } 47 48 type AccountExportChoice struct { 49 AccountExport 50 Selection *jwt.Export 51 } 52 53 type AccountExportChoices []AccountExportChoice 54 55 func (aes AccountExportChoices) String() []string { 56 var choices []string 57 for _, c := range aes { 58 choices = append(choices, c.String()) 59 } 60 return choices 61 } 62 63 func (aec *AccountExportChoice) String() string { 64 // label 65 if aec.Selection == nil { 66 footer := "" 67 if aec.AccountExport.Description != "" { 68 footer = aec.AccountExport.Description 69 } 70 if aec.AccountExport.InfoURL != "" { 71 footer = fmt.Sprintf("%s\n Link: %s", footer, aec.AccountExport.InfoURL) 72 } 73 return fmt.Sprintf("%s: %s", aec.Name, footer) 74 } 75 // an actual export 76 k := "->" 77 if aec.Selection.IsService() { 78 k = "<-" 79 } 80 81 p := "" 82 if aec.Selection.TokenReq { 83 p = "[!]" 84 } 85 86 footer := "" 87 if aec.Selection.Description != "" { 88 footer = fmt.Sprintf("\n Description: %s", aec.Selection.Description) 89 } 90 if aec.Selection.InfoURL != "" { 91 footer = fmt.Sprintf("%s\n Link: %s", footer, aec.Selection.InfoURL) 92 } 93 94 if aec.Selection.Name == string(aec.Selection.Subject) { 95 return fmt.Sprintf(" %s %s %s%s", k, aec.Selection.Subject, p, footer) 96 } 97 98 return fmt.Sprintf(" %s [%s] %s %s%s", k, aec.Selection.Name, aec.Selection.Subject, p, footer) 99 } 100 101 type AccountImport struct { 102 Name string 103 ID string 104 } 105 106 type AccountImportChoice struct { 107 AccountImport 108 Selection *jwt.Import 109 } 110 111 type AccountImportChoices []AccountImportChoice 112 113 func (aes AccountImportChoices) String() []string { 114 var choices []string 115 for _, c := range aes { 116 choices = append(choices, c.String()) 117 } 118 return choices 119 } 120 121 func (aec *AccountImportChoice) String() string { 122 label := aec.Name 123 if label == "" { 124 label = aec.ID 125 } 126 127 // an actual export 128 k := "->" 129 if aec.Selection.IsService() { 130 k = "<-" 131 } 132 133 p := "" 134 if aec.Selection.Token != "" { 135 p = "[!]" 136 } 137 138 if aec.Selection.Name == string(aec.Selection.Subject) { 139 return fmt.Sprintf(" %s %s %s (%s)", k, aec.Selection.Subject, p, label) 140 } 141 142 return fmt.Sprintf(" %s [%s] %s %s (%s)", k, aec.Selection.Name, aec.Selection.Subject, p, label) 143 } 144 145 func GetAccountImports(ac *jwt.AccountClaims) (AccountImportChoices, error) { 146 config := GetConfig() 147 if config.StoreRoot == "" { 148 return nil, errors.New("no store set - `env --store <dir>`") 149 } 150 idToName := make(map[string]string) 151 operators := config.ListOperators() 152 for _, o := range operators { 153 if o == "" { 154 continue 155 } 156 s, err := config.LoadStore(o) 157 if err != nil { 158 return nil, err 159 } 160 accounts, err := s.ListSubContainers(store.Accounts) 161 if err != nil { 162 return nil, err 163 } 164 for _, a := range accounts { 165 ac, err := s.ReadAccountClaim(a) 166 if err != nil { 167 if store.IsNotExist(err) { 168 // ignore it and move on 169 continue 170 } 171 return nil, err 172 } 173 if ac != nil { 174 idToName[ac.Subject] = ac.Name 175 } 176 } 177 } 178 179 var a AccountImportChoices 180 for _, v := range ac.Imports { 181 var aic AccountImportChoice 182 aic.ID = v.Account 183 aic.Name = idToName[aic.ID] 184 aic.Selection = v 185 a = append(a, aic) 186 } 187 return a, nil 188 } 189 190 func GetAccountExports(ac *jwt.AccountClaims) ([]AccountExportChoice, error) { 191 if ac == nil { 192 return nil, nil 193 } 194 if len(ac.Exports) == 0 { 195 return nil, nil 196 } 197 var export AccountExport 198 export.Exports = ac.Exports 199 export.AccountClaims = *ac 200 return export.Choices()[1:], nil 201 } 202 203 func GetAllExports() ([]AccountExport, error) { 204 var exports []AccountExport 205 206 config := GetConfig() 207 if config.StoreRoot == "" { 208 return nil, errors.New("no store set - `env --store <dir>`") 209 } 210 operators := config.ListOperators() 211 for _, o := range operators { 212 if o == "" { 213 continue 214 } 215 216 s, err := config.LoadStore(o) 217 if err != nil { 218 return nil, err 219 } 220 accounts, err := s.ListSubContainers(store.Accounts) 221 if err != nil { 222 return nil, err 223 } 224 for _, a := range accounts { 225 ac, err := s.ReadAccountClaim(a) 226 if err != nil { 227 if store.IsNotExist(err) { 228 // ignore it and move on 229 continue 230 } 231 return nil, err 232 } 233 234 if len(ac.Exports) == 0 { 235 continue 236 } 237 238 var export AccountExport 239 export.OperatorName = o 240 export.Exports = ac.Exports 241 export.AccountClaims = *ac 242 exports = append(exports, export) 243 } 244 } 245 246 sort.Sort(ByAccountName(exports)) 247 return exports, nil 248 }