Fix formatting in MissingScopesError

This commit is contained in:
Mislav Marohnić 2020-10-16 16:54:07 +00:00 committed by GitHub
parent 38f0f607e9
commit 626be2a095
2 changed files with 80 additions and 11 deletions

View file

@ -3,7 +3,6 @@ package api
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@ -155,7 +154,20 @@ func (err HTTPError) Error() string {
}
type MissingScopesError struct {
error
MissingScopes []string
}
func (e MissingScopesError) Error() string {
var missing []string
for _, s := range e.MissingScopes {
missing = append(missing, fmt.Sprintf("'%s'", s))
}
scopes := strings.Join(missing, ", ")
if len(e.MissingScopes) == 1 {
return "missing required scope " + scopes
}
return "missing required scopes " + scopes
}
func (c Client) HasMinimumScopes(hostname string) error {
@ -183,31 +195,29 @@ func (c Client) HasMinimumScopes(hostname string) error {
return HandleHTTPError(res)
}
hasScopes := strings.Split(res.Header.Get("X-Oauth-Scopes"), ",")
scopesHeader := res.Header.Get("X-Oauth-Scopes")
search := map[string]bool{
"repo": false,
"read:org": false,
"admin:org": false,
}
for _, s := range hasScopes {
for _, s := range strings.Split(scopesHeader, ",") {
search[strings.TrimSpace(s)] = true
}
errorMsgs := []string{}
var missingScopes []string
if !search["repo"] {
errorMsgs = append(errorMsgs, "missing required scope 'repo'")
missingScopes = append(missingScopes, "repo")
}
if !search["read:org"] && !search["admin:org"] {
errorMsgs = append(errorMsgs, "missing required scope 'read:org'")
missingScopes = append(missingScopes, "read:org")
}
if len(errorMsgs) > 0 {
return &MissingScopesError{error: errors.New(strings.Join(errorMsgs, ";"))}
if len(missingScopes) > 0 {
return &MissingScopesError{MissingScopes: missingScopes}
}
return nil
}

View file

@ -104,3 +104,62 @@ func TestRESTError(t *testing.T) {
}
}
func Test_HasMinimumScopes(t *testing.T) {
tests := []struct {
name string
header string
wantErr string
}{
{
name: "default scopes",
header: "repo, read:org",
wantErr: "",
},
{
name: "admin:org satisfies read:org",
header: "repo, admin:org",
wantErr: "",
},
{
name: "insufficient scope",
header: "repo",
wantErr: "missing required scope 'read:org'",
},
{
name: "insufficient scopes",
header: "gist",
wantErr: "missing required scopes 'repo', 'read:org'",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fakehttp := &httpmock.Registry{}
client := NewClient(ReplaceTripper(fakehttp))
fakehttp.Register(httpmock.REST("GET", ""), func(req *http.Request) (*http.Response, error) {
return &http.Response{
Request: req,
StatusCode: 200,
Body: ioutil.NopCloser(&bytes.Buffer{}),
Header: map[string][]string{
"X-Oauth-Scopes": {tt.header},
},
}, nil
})
err := client.HasMinimumScopes("github.com")
if tt.wantErr == "" {
if err != nil {
t.Errorf("error: %v", err)
}
return
}
if err.Error() != tt.wantErr {
t.Errorf("want %q, got %q", tt.wantErr, err.Error())
}
})
}
}