From 626be2a0951b5550562fc1352bb3630b9813138e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 16 Oct 2020 16:54:07 +0000 Subject: [PATCH] Fix formatting in MissingScopesError --- api/client.go | 32 ++++++++++++++++--------- api/client_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/api/client.go b/api/client.go index 47eb2a373..b290aae3d 100644 --- a/api/client.go +++ b/api/client.go @@ -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 } diff --git a/api/client_test.go b/api/client_test.go index 348f5678a..fd24a5404 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -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()) + + } + }) + } + +}