github.com/adevinta/maiao@v0.0.0-20240318133227-b6f9656b5e07/pkg/credentials/keyring.go (about) 1 package credentials 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "os" 8 9 "github.com/99designs/keyring" 10 "github.com/manifoldco/promptui" 11 ) 12 13 type Keyring struct { 14 kr keyring.Keyring 15 } 16 17 var _ CredentialGetter = &Keyring{} 18 19 func (k Keyring) CredentialForHost(h string) (*Credentials, error) { 20 secretKey := fmt.Sprintf("%s-credentials", h) 21 v, err := k.kr.Get(secretKey) 22 creds := &Credentials{} 23 if err == nil { 24 err = json.NewDecoder(bytes.NewReader(v.Data)).Decode(creds) 25 if err != nil { 26 return nil, err 27 } 28 } 29 30 if err == keyring.ErrKeyNotFound { 31 prompt := promptui.Prompt{ 32 Label: fmt.Sprintf("username for %s", h), 33 Stdin: os.Stdin, 34 Stdout: os.Stdout, 35 } 36 creds.Username, err = prompt.Run() 37 if err != nil { 38 return nil, err 39 } 40 prompt = promptui.Prompt{ 41 Label: fmt.Sprintf("password for %s (usually your Personal Access Token)", h), 42 Mask: '*', 43 Stdin: os.Stdin, 44 Stdout: os.Stdout, 45 } 46 creds.Password, err = prompt.Run() 47 if err != nil { 48 return nil, err 49 } 50 d := bytes.NewBuffer(nil) 51 err = json.NewEncoder(d).Encode(creds) 52 if err != nil { 53 return creds, nil 54 } 55 err = k.kr.Set(keyring.Item{ 56 Key: secretKey, 57 Label: h, 58 Description: fmt.Sprintf("json encoded user/password to access %s", h), 59 Data: d.Bytes(), 60 }) 61 if err != nil { 62 return creds, nil 63 } 64 } 65 if err != nil { 66 return nil, err 67 } 68 69 return creds, nil 70 } 71 72 func NewKeyring(cfg keyring.Config) (CredentialGetter, error) { 73 kr, err := keyring.Open(cfg) 74 if err != nil { 75 return nil, err 76 } 77 return &Keyring{kr: kr}, nil 78 } 79 80 func MustNewKeyring(cfg keyring.Config) CredentialGetter { 81 c, err := NewKeyring(cfg) 82 if err != nil { 83 panic(err) 84 } 85 return c 86 }