github.com/secman-team/gh-api@v1.8.2/pkg/cmd/ssh-key/list/list.go (about) 1 package list 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "time" 8 9 "github.com/secman-team/gh-api/core/config" 10 "github.com/secman-team/gh-api/pkg/cmdutil" 11 "github.com/secman-team/gh-api/pkg/iostreams" 12 "github.com/secman-team/gh-api/utils" 13 "github.com/spf13/cobra" 14 ) 15 16 type ListOptions struct { 17 IO *iostreams.IOStreams 18 Config func() (config.Config, error) 19 HTTPClient func() (*http.Client, error) 20 } 21 22 func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command { 23 opts := &ListOptions{ 24 IO: f.IOStreams, 25 Config: f.Config, 26 HTTPClient: f.HttpClient, 27 } 28 29 cmd := &cobra.Command{ 30 Use: "list", 31 Short: "Lists SSH keys in your GitHub account", 32 Args: cobra.ExactArgs(0), 33 RunE: func(cmd *cobra.Command, args []string) error { 34 if runF != nil { 35 return runF(opts) 36 } 37 return listRun(opts) 38 }, 39 } 40 41 return cmd 42 } 43 44 func listRun(opts *ListOptions) error { 45 apiClient, err := opts.HTTPClient() 46 if err != nil { 47 return err 48 } 49 50 cfg, err := opts.Config() 51 if err != nil { 52 return err 53 } 54 55 host, err := cfg.DefaultHost() 56 if err != nil { 57 return err 58 } 59 60 sshKeys, err := userKeys(apiClient, host, "") 61 if err != nil { 62 if errors.Is(err, scopesError) { 63 cs := opts.IO.ColorScheme() 64 fmt.Fprint(opts.IO.ErrOut, "Error: insufficient OAuth scopes to list SSH keys\n") 65 fmt.Fprintf(opts.IO.ErrOut, "Run the following to grant scopes: %s\n", cs.Bold("gh auth refresh -s read:public_key")) 66 return cmdutil.SilentError 67 } 68 return err 69 } 70 71 if len(sshKeys) == 0 { 72 fmt.Fprintln(opts.IO.ErrOut, "No SSH keys present in GitHub account.") 73 return cmdutil.SilentError 74 } 75 76 t := utils.NewTablePrinter(opts.IO) 77 cs := opts.IO.ColorScheme() 78 now := time.Now() 79 80 for _, sshKey := range sshKeys { 81 t.AddField(sshKey.Title, nil, nil) 82 t.AddField(sshKey.Key, truncateMiddle, nil) 83 84 createdAt := sshKey.CreatedAt.Format(time.RFC3339) 85 if t.IsTTY() { 86 createdAt = utils.FuzzyAgoAbbr(now, sshKey.CreatedAt) 87 } 88 t.AddField(createdAt, nil, cs.Gray) 89 t.EndRow() 90 } 91 92 return t.Render() 93 } 94 95 func truncateMiddle(maxWidth int, t string) string { 96 if len(t) <= maxWidth { 97 return t 98 } 99 100 ellipsis := "..." 101 if maxWidth < len(ellipsis)+2 { 102 return t[0:maxWidth] 103 } 104 105 halfWidth := (maxWidth - len(ellipsis)) / 2 106 remainder := (maxWidth - len(ellipsis)) % 2 107 return t[0:halfWidth+remainder] + ellipsis + t[len(t)-halfWidth:] 108 }