Skip to content

Commit 4a3f7d9

Browse files
Merge pull request cli#12914 from cli/revert-12845-refactor/deduplicate-scope-error-handling
Revert "refactor: deduplicate scope error handling between api/client.go and project queries"
2 parents 2bf1669 + d45acae commit 4a3f7d9

3 files changed

Lines changed: 66 additions & 4 deletions

File tree

api/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ func GenerateScopeErrorForGQL(gqlErr *ghAPI.GraphQLError) error {
203203
}
204204
if missing.Len() > 0 {
205205
s := missing.ToSlice()
206+
// TODO: this duplicates parts of generateScopesSuggestion
206207
return fmt.Errorf(
207208
"error: your authentication token is missing required scopes %v\n"+
208209
"To request it, run: gh auth refresh -s %s",

pkg/cmd/project/shared/queries/queries.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import (
55
"fmt"
66
"net/http"
77
"net/url"
8+
"regexp"
89
"strings"
910

1011
"github.com/cli/cli/v2/api"
1112
"github.com/cli/cli/v2/internal/prompter"
1213
"github.com/cli/cli/v2/pkg/iostreams"
14+
"github.com/cli/cli/v2/pkg/set"
1315
"github.com/shurcooL/githubv4"
1416
)
1517

@@ -1662,15 +1664,42 @@ func (c *Client) UnlinkProjectFromTeam(projectID string, teamID string) error {
16621664
}
16631665

16641666
func handleError(err error) error {
1665-
var gqlErr api.GraphQLError
1666-
if errors.As(err, &gqlErr) {
1667-
if scopeErr := api.GenerateScopeErrorForGQL(gqlErr.GraphQLError); scopeErr != nil {
1668-
return scopeErr
1667+
var gerr api.GraphQLError
1668+
if errors.As(err, &gerr) {
1669+
missing := set.NewStringSet()
1670+
for _, e := range gerr.Errors {
1671+
if e.Type != "INSUFFICIENT_SCOPES" {
1672+
continue
1673+
}
1674+
missing.AddValues(requiredScopesFromServerMessage(e.Message))
1675+
}
1676+
if missing.Len() > 0 {
1677+
s := missing.ToSlice()
1678+
// TODO: this duplicates parts of generateScopesSuggestion
1679+
return fmt.Errorf(
1680+
"error: your authentication token is missing required scopes %v\n"+
1681+
"To request it, run: gh auth refresh -s %s",
1682+
s,
1683+
strings.Join(s, ","))
16691684
}
16701685
}
16711686
return err
16721687
}
16731688

1689+
var scopesRE = regexp.MustCompile(`one of the following scopes: \[(.+?)]`)
1690+
1691+
func requiredScopesFromServerMessage(msg string) []string {
1692+
m := scopesRE.FindStringSubmatch(msg)
1693+
if m == nil {
1694+
return nil
1695+
}
1696+
var scopes []string
1697+
for _, mm := range strings.Split(m[1], ",") {
1698+
scopes = append(scopes, strings.Trim(mm, "' "))
1699+
}
1700+
return scopes
1701+
}
1702+
16741703
func projectFieldValueData(v FieldValueNodes) interface{} {
16751704
switch v.Type {
16761705
case "ProjectV2ItemFieldDateValue":

pkg/cmd/project/shared/queries/queries_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package queries
33
import (
44
"io"
55
"net/http"
6+
"reflect"
67
"strings"
78
"testing"
89

@@ -563,6 +564,37 @@ func TestProjectFields_NoLimit(t *testing.T) {
563564
assert.Len(t, project.Fields.Nodes, 3)
564565
}
565566

567+
func Test_requiredScopesFromServerMessage(t *testing.T) {
568+
tests := []struct {
569+
name string
570+
msg string
571+
want []string
572+
}{
573+
{
574+
name: "no scopes",
575+
msg: "SERVER OOPSIE",
576+
want: []string(nil),
577+
},
578+
{
579+
name: "one scope",
580+
msg: "Your token has not been granted the required scopes to execute this query. The 'dataType' field requires one of the following scopes: ['read:project'], but your token has only been granted the: ['codespace', repo'] scopes. Please modify your token's scopes at: https://github.com/settings/tokens.",
581+
want: []string{"read:project"},
582+
},
583+
{
584+
name: "multiple scopes",
585+
msg: "Your token has not been granted the required scopes to execute this query. The 'dataType' field requires one of the following scopes: ['read:project', 'read:discussion', 'codespace'], but your token has only been granted the: [repo'] scopes. Please modify your token's scopes at: https://github.com/settings/tokens.",
586+
want: []string{"read:project", "read:discussion", "codespace"},
587+
},
588+
}
589+
for _, tt := range tests {
590+
t.Run(tt.name, func(t *testing.T) {
591+
if got := requiredScopesFromServerMessage(tt.msg); !reflect.DeepEqual(got, tt.want) {
592+
t.Errorf("requiredScopesFromServerMessage() = %v, want %v", got, tt.want)
593+
}
594+
})
595+
}
596+
}
597+
566598
func TestNewProject_nonTTY(t *testing.T) {
567599
client := NewTestClient()
568600
_, err := client.NewProject(false, &Owner{}, 0, false)

0 commit comments

Comments
 (0)