|
|
|
@ -7,6 +7,7 @@ import ( |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"io/ioutil" |
|
|
|
"io/ioutil" |
|
|
|
"net/http" |
|
|
|
"net/http" |
|
|
|
|
|
|
|
"regexp" |
|
|
|
"strconv" |
|
|
|
"strconv" |
|
|
|
|
|
|
|
|
|
|
|
"golang.org/x/net/context" |
|
|
|
"golang.org/x/net/context" |
|
|
|
@ -221,39 +222,66 @@ func (c *githubConnector) user(ctx context.Context, client *http.Client) (user, |
|
|
|
// The HTTP passed client is expected to be constructed by the golang.org/x/oauth2 package,
|
|
|
|
// The HTTP passed client is expected to be constructed by the golang.org/x/oauth2 package,
|
|
|
|
// which inserts a bearer token as part of the request.
|
|
|
|
// which inserts a bearer token as part of the request.
|
|
|
|
func (c *githubConnector) teams(ctx context.Context, client *http.Client, org string) ([]string, error) { |
|
|
|
func (c *githubConnector) teams(ctx context.Context, client *http.Client, org string) ([]string, error) { |
|
|
|
req, err := http.NewRequest("GET", baseURL+"/user/teams", nil) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, fmt.Errorf("github: new req: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
req = req.WithContext(ctx) |
|
|
|
|
|
|
|
resp, err := client.Do(req) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, fmt.Errorf("github: get teams: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer resp.Body.Close() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK { |
|
|
|
groups := []string{} |
|
|
|
body, err := ioutil.ReadAll(resp.Body) |
|
|
|
|
|
|
|
|
|
|
|
// https://developer.github.com/v3/#pagination
|
|
|
|
|
|
|
|
reNext := regexp.MustCompile("<(.*)>; rel=\"next\"") |
|
|
|
|
|
|
|
reLast := regexp.MustCompile("<(.*)>; rel=\"last\"") |
|
|
|
|
|
|
|
apiURL := baseURL + "/user/teams" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for { |
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", apiURL, nil) |
|
|
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, fmt.Errorf("github: read body: %v", err) |
|
|
|
return nil, fmt.Errorf("github: new req: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
req = req.WithContext(ctx) |
|
|
|
|
|
|
|
resp, err := client.Do(req) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, fmt.Errorf("github: get teams: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer resp.Body.Close() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK { |
|
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, fmt.Errorf("github: read body: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return nil, fmt.Errorf("%s: %s", resp.Status, body) |
|
|
|
} |
|
|
|
} |
|
|
|
return nil, fmt.Errorf("%s: %s", resp.Status, body) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://developer.github.com/v3/orgs/teams/#response-12
|
|
|
|
// https://developer.github.com/v3/orgs/teams/#response-12
|
|
|
|
var teams []struct { |
|
|
|
var teams []struct { |
|
|
|
Name string `json:"name"` |
|
|
|
Name string `json:"name"` |
|
|
|
Org struct { |
|
|
|
Org struct { |
|
|
|
Login string `json:"login"` |
|
|
|
Login string `json:"login"` |
|
|
|
} `json:"organization"` |
|
|
|
} `json:"organization"` |
|
|
|
} |
|
|
|
} |
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&teams); err != nil { |
|
|
|
if err := json.NewDecoder(resp.Body).Decode(&teams); err != nil { |
|
|
|
return nil, fmt.Errorf("github: unmarshal groups: %v", err) |
|
|
|
return nil, fmt.Errorf("github: unmarshal groups: %v", err) |
|
|
|
} |
|
|
|
} |
|
|
|
groups := []string{} |
|
|
|
|
|
|
|
for _, team := range teams { |
|
|
|
for _, team := range teams { |
|
|
|
if team.Org.Login == org { |
|
|
|
if team.Org.Login == org { |
|
|
|
groups = append(groups, team.Name) |
|
|
|
groups = append(groups, team.Name) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
links := resp.Header.Get("Link") |
|
|
|
|
|
|
|
if len(reLast.FindStringSubmatch(links)) > 1 { |
|
|
|
|
|
|
|
lastPageURL := reLast.FindStringSubmatch(links)[1] |
|
|
|
|
|
|
|
if apiURL == lastPageURL { |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(reNext.FindStringSubmatch(links)) > 1 { |
|
|
|
|
|
|
|
apiURL = reNext.FindStringSubmatch(links)[1] |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return groups, nil |
|
|
|
return groups, nil |
|
|
|
|