Merge pull request #414 from relaxdiego/multi-page-org

Iterate through pages returned by List Your Organizations endpoint
This commit is contained in:
Heather Hendy 2017-12-04 15:12:25 -07:00 committed by GitHub
commit d75f626cdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 37 deletions

View File

@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"path"
"strconv"
"strings"
)
@ -61,36 +62,51 @@ func (p *GitHubProvider) hasOrg(accessToken string) (bool, error) {
Login string `json:"login"`
}
params := url.Values{
"limit": {"100"},
type orgsPage []struct {
Login string `json:"login"`
}
endpoint := &url.URL{
Scheme: p.ValidateURL.Scheme,
Host: p.ValidateURL.Host,
Path: path.Join(p.ValidateURL.Path, "/user/orgs"),
RawQuery: params.Encode(),
}
req, _ := http.NewRequest("GET", endpoint.String(), nil)
req.Header.Set("Accept", "application/vnd.github.v3+json")
req.Header.Set("Authorization", fmt.Sprintf("token %s", accessToken))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}
pn := 1
for {
params := url.Values{
"limit": {"200"},
"page": {strconv.Itoa(pn)},
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, fmt.Errorf(
"got %d from %q %s", resp.StatusCode, endpoint.String(), body)
}
endpoint := &url.URL{
Scheme: p.ValidateURL.Scheme,
Host: p.ValidateURL.Host,
Path: path.Join(p.ValidateURL.Path, "/user/orgs"),
RawQuery: params.Encode(),
}
req, _ := http.NewRequest("GET", endpoint.String(), nil)
req.Header.Set("Accept", "application/vnd.github.v3+json")
req.Header.Set("Authorization", fmt.Sprintf("token %s", accessToken))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}
if err := json.Unmarshal(body, &orgs); err != nil {
return false, err
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, fmt.Errorf(
"got %d from %q %s", resp.StatusCode, endpoint.String(), body)
}
var op orgsPage
if err := json.Unmarshal(body, &op); err != nil {
return false, err
}
if len(op) == 0 {
break
}
orgs = append(orgs, op...)
pn += 1
}
var presentOrgs []string
@ -118,7 +134,7 @@ func (p *GitHubProvider) hasOrgAndTeam(accessToken string) (bool, error) {
}
params := url.Values{
"limit": {"100"},
"limit": {"200"},
}
endpoint := &url.URL{

View File

@ -27,23 +27,32 @@ func testGitHubProvider(hostname string) *GitHubProvider {
return p
}
func testGitHubBackend(payload string) *httptest.Server {
pathToQueryMap := map[string]string{
"/user": "",
"/user/emails": "",
func testGitHubBackend(payload []string) *httptest.Server {
pathToQueryMap := map[string][]string{
"/user": []string{""},
"/user/emails": []string{""},
"/user/orgs": []string{"limit=200&page=1", "limit=200&page=2", "limit=200&page=3"},
}
return httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
url := r.URL
query, ok := pathToQueryMap[url.Path]
validQuery := false
index := 0
for i, q := range query {
if q == url.RawQuery {
validQuery = true
index = i
}
}
if !ok {
w.WriteHeader(404)
} else if url.RawQuery != query {
} else if !validQuery {
w.WriteHeader(404)
} else {
w.WriteHeader(200)
w.Write([]byte(payload))
w.Write([]byte(payload[index]))
}
}))
}
@ -89,7 +98,7 @@ func TestGitHubProviderOverrides(t *testing.T) {
}
func TestGitHubProviderGetEmailAddress(t *testing.T) {
b := testGitHubBackend(`[ {"email": "michael.bland@gsa.gov", "primary": true} ]`)
b := testGitHubBackend([]string{`[ {"email": "michael.bland@gsa.gov", "primary": true} ]`})
defer b.Close()
bURL, _ := url.Parse(b.URL)
@ -101,10 +110,28 @@ func TestGitHubProviderGetEmailAddress(t *testing.T) {
assert.Equal(t, "michael.bland@gsa.gov", email)
}
func TestGitHubProviderGetEmailAddressWithOrg(t *testing.T) {
b := testGitHubBackend([]string{
`[ {"email": "michael.bland@gsa.gov", "primary": true, "login":"testorg"} ]`,
`[ {"email": "michael.bland1@gsa.gov", "primary": true, "login":"testorg1"} ]`,
`[ ]`,
})
defer b.Close()
bURL, _ := url.Parse(b.URL)
p := testGitHubProvider(bURL.Host)
p.Org = "testorg1"
session := &SessionState{AccessToken: "imaginary_access_token"}
email, err := p.GetEmailAddress(session)
assert.Equal(t, nil, err)
assert.Equal(t, "michael.bland@gsa.gov", email)
}
// Note that trying to trigger the "failed building request" case is not
// practical, since the only way it can fail is if the URL fails to parse.
func TestGitHubProviderGetEmailAddressFailedRequest(t *testing.T) {
b := testGitHubBackend("unused payload")
b := testGitHubBackend([]string{"unused payload"})
defer b.Close()
bURL, _ := url.Parse(b.URL)
@ -120,7 +147,7 @@ func TestGitHubProviderGetEmailAddressFailedRequest(t *testing.T) {
}
func TestGitHubProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) {
b := testGitHubBackend("{\"foo\": \"bar\"}")
b := testGitHubBackend([]string{"{\"foo\": \"bar\"}"})
defer b.Close()
bURL, _ := url.Parse(b.URL)
@ -133,7 +160,7 @@ func TestGitHubProviderGetEmailAddressEmailNotPresentInPayload(t *testing.T) {
}
func TestGitHubProviderGetUserName(t *testing.T) {
b := testGitHubBackend(`{"email": "michael.bland@gsa.gov", "login": "mbland"}`)
b := testGitHubBackend([]string{`{"email": "michael.bland@gsa.gov", "login": "mbland"}`})
defer b.Close()
bURL, _ := url.Parse(b.URL)