Enhance ssh-key list to show signing ssh keys also
This commit is contained in:
parent
0d8b5ab9d7
commit
4668810cbe
3 changed files with 147 additions and 11 deletions
|
|
@ -1,10 +1,14 @@
|
|||
package list
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/cli/cli/v2/api"
|
||||
"github.com/cli/cli/v2/internal/config"
|
||||
"github.com/cli/cli/v2/internal/text"
|
||||
"github.com/cli/cli/v2/pkg/cmd/ssh-key/shared"
|
||||
|
|
@ -55,12 +59,22 @@ func listRun(opts *ListOptions) error {
|
|||
}
|
||||
|
||||
host, _ := cfg.Authentication().DefaultHost()
|
||||
|
||||
sshKeys, err := shared.UserKeys(apiClient, host, "")
|
||||
if err != nil {
|
||||
return err
|
||||
sshAuthKeys, authKeyErr := shared.UserKeys(apiClient, host, "")
|
||||
if authKeyErr != nil {
|
||||
printError(opts.IO.ErrOut, authKeyErr)
|
||||
}
|
||||
|
||||
sshSigningKeys, signKeyErr := shared.UserSigningKeys(apiClient, host, "")
|
||||
if signKeyErr != nil {
|
||||
printError(opts.IO.ErrOut, signKeyErr)
|
||||
}
|
||||
|
||||
if authKeyErr != nil && signKeyErr != nil {
|
||||
return cmdutil.SilentError
|
||||
}
|
||||
|
||||
sshKeys := append(sshAuthKeys, sshSigningKeys...)
|
||||
|
||||
if len(sshKeys) == 0 {
|
||||
return cmdutil.NewNoResultsError("no SSH keys present in the GitHub account")
|
||||
}
|
||||
|
|
@ -74,6 +88,7 @@ func listRun(opts *ListOptions) error {
|
|||
t.AddField("TITLE", nil, nil)
|
||||
t.AddField("ID", nil, nil)
|
||||
t.AddField("KEY", nil, nil)
|
||||
t.AddField("TYPE", nil, nil)
|
||||
t.AddField("ADDED", nil, nil)
|
||||
t.EndRow()
|
||||
}
|
||||
|
|
@ -86,12 +101,14 @@ func listRun(opts *ListOptions) error {
|
|||
t.AddField(sshKey.Title, nil, nil)
|
||||
t.AddField(id, nil, nil)
|
||||
t.AddField(sshKey.Key, truncateMiddle, nil)
|
||||
t.AddField(sshKey.Type, nil, nil)
|
||||
t.AddField(text.FuzzyAgoAbbr(now, sshKey.CreatedAt), nil, cs.Gray)
|
||||
} else {
|
||||
t.AddField(sshKey.Title, nil, nil)
|
||||
t.AddField(sshKey.Key, nil, nil)
|
||||
t.AddField(createdAt, nil, nil)
|
||||
t.AddField(id, nil, nil)
|
||||
t.AddField(sshKey.Type, nil, nil)
|
||||
}
|
||||
|
||||
t.EndRow()
|
||||
|
|
@ -114,3 +131,13 @@ func truncateMiddle(maxWidth int, t string) string {
|
|||
remainder := (maxWidth - len(ellipsis)) % 2
|
||||
return t[0:halfWidth+remainder] + ellipsis + t[len(t)-halfWidth:]
|
||||
}
|
||||
|
||||
func printError(w io.Writer, err error) {
|
||||
fmt.Fprintln(w, "warning: ", err)
|
||||
var httpErr api.HTTPError
|
||||
if errors.As(err, &httpErr) {
|
||||
if msg := httpErr.ScopesSuggestion(); msg != "" {
|
||||
fmt.Fprintln(w, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func TestListRun(t *testing.T) {
|
|||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list tty",
|
||||
name: "list authentication and signing keys; in tty",
|
||||
opts: ListOptions{
|
||||
HTTPClient: func() (*http.Client, error) {
|
||||
createdAt := time.Now().Add(time.Duration(-24) * time.Hour)
|
||||
|
|
@ -44,19 +44,31 @@ func TestListRun(t *testing.T) {
|
|||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StringResponse(fmt.Sprintf(`[
|
||||
{
|
||||
"id": 321,
|
||||
"key": "ssh-rsa AAAABbBB123",
|
||||
"title": "Mac Signing",
|
||||
"created_at": "%[1]s"
|
||||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
isTTY: true,
|
||||
wantStdout: heredoc.Doc(`
|
||||
TITLE ID KEY ADDED
|
||||
Mac 1234 ssh-rsa AAAABbBB123 1d
|
||||
hubot@Windows 5678 ssh-rsa EEEEEEEK247 1d
|
||||
TITLE ID KEY TYPE ADDED
|
||||
Mac 1234 ssh-rsa AAAABbBB123 authentication 1d
|
||||
hubot@Windows 5678 ssh-rsa EEEEEEEK247 authentication 1d
|
||||
Mac Signing 321 ssh-rsa AAAABbBB123 signing 1d
|
||||
`),
|
||||
wantStderr: "",
|
||||
},
|
||||
{
|
||||
name: "list non-tty",
|
||||
name: "list authentication and signing keys; in non-tty",
|
||||
opts: ListOptions{
|
||||
HTTPClient: func() (*http.Client, error) {
|
||||
createdAt, _ := time.Parse(time.RFC3339, "2020-08-31T15:44:24+02:00")
|
||||
|
|
@ -78,16 +90,96 @@ func TestListRun(t *testing.T) {
|
|||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StringResponse(fmt.Sprintf(`[
|
||||
{
|
||||
"id": 321,
|
||||
"key": "ssh-rsa AAAABbBB123",
|
||||
"title": "Mac Signing",
|
||||
"created_at": "%[1]s"
|
||||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
isTTY: false,
|
||||
wantStdout: heredoc.Doc(`
|
||||
Mac ssh-rsa AAAABbBB123 2020-08-31T15:44:24+02:00 1234
|
||||
hubot@Windows ssh-rsa EEEEEEEK247 2020-08-31T15:44:24+02:00 5678
|
||||
Mac ssh-rsa AAAABbBB123 2020-08-31T15:44:24+02:00 1234 authentication
|
||||
hubot@Windows ssh-rsa EEEEEEEK247 2020-08-31T15:44:24+02:00 5678 authentication
|
||||
Mac Signing ssh-rsa AAAABbBB123 2020-08-31T15:44:24+02:00 321 signing
|
||||
`),
|
||||
wantStderr: "",
|
||||
},
|
||||
{
|
||||
name: "only authentication ssh keys are available",
|
||||
opts: ListOptions{
|
||||
HTTPClient: func() (*http.Client, error) {
|
||||
createdAt := time.Now().Add(time.Duration(-24) * time.Hour)
|
||||
reg := &httpmock.Registry{}
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/keys"),
|
||||
httpmock.StringResponse(fmt.Sprintf(`[
|
||||
{
|
||||
"id": 1234,
|
||||
"key": "ssh-rsa AAAABbBB123",
|
||||
"title": "Mac",
|
||||
"created_at": "%[1]s"
|
||||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StatusStringResponse(404, "Not Found"),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
wantStdout: heredoc.Doc(`
|
||||
TITLE ID KEY TYPE ADDED
|
||||
Mac 1234 ssh-rsa AAAABbBB123 authentication 1d
|
||||
`),
|
||||
wantStderr: heredoc.Doc(`
|
||||
warning: HTTP 404 (https://api.github.com/user/ssh_signing_keys?per_page=100)
|
||||
`),
|
||||
wantErr: false,
|
||||
isTTY: true,
|
||||
},
|
||||
{
|
||||
name: "only signing ssh keys are available",
|
||||
opts: ListOptions{
|
||||
HTTPClient: func() (*http.Client, error) {
|
||||
createdAt := time.Now().Add(time.Duration(-24) * time.Hour)
|
||||
reg := &httpmock.Registry{}
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StringResponse(fmt.Sprintf(`[
|
||||
{
|
||||
"id": 1234,
|
||||
"key": "ssh-rsa AAAABbBB123",
|
||||
"title": "Mac",
|
||||
"created_at": "%[1]s"
|
||||
}
|
||||
]`, createdAt.Format(time.RFC3339))),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/keys"),
|
||||
httpmock.StatusStringResponse(404, "Not Found"),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
wantStdout: heredoc.Doc(`
|
||||
TITLE ID KEY TYPE ADDED
|
||||
Mac 1234 ssh-rsa AAAABbBB123 signing 1d
|
||||
`),
|
||||
wantStderr: heredoc.Doc(`
|
||||
warning: HTTP 404 (https://api.github.com/user/keys?per_page=100)
|
||||
`),
|
||||
wantErr: false,
|
||||
isTTY: true,
|
||||
},
|
||||
{
|
||||
name: "no keys tty",
|
||||
opts: ListOptions{
|
||||
|
|
@ -97,6 +189,10 @@ func TestListRun(t *testing.T) {
|
|||
httpmock.REST("GET", "user/keys"),
|
||||
httpmock.StringResponse(`[]`),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StringResponse(`[]`),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
|
|
@ -114,6 +210,10 @@ func TestListRun(t *testing.T) {
|
|||
httpmock.REST("GET", "user/keys"),
|
||||
httpmock.StringResponse(`[]`),
|
||||
)
|
||||
reg.Register(
|
||||
httpmock.REST("GET", "user/ssh_signing_keys"),
|
||||
httpmock.StringResponse(`[]`),
|
||||
)
|
||||
return &http.Client{Transport: reg}, nil
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type sshKey struct {
|
|||
ID int
|
||||
Key string
|
||||
Title string
|
||||
Type string
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +37,10 @@ func UserKeys(httpClient *http.Client, host, userHandle string) ([]sshKey, error
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i].Type = AuthenticationKey
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +57,10 @@ func UserSigningKeys(httpClient *http.Client, host, userHandle string) ([]sshKey
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i].Type = SigningKey
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue