Iterate through group membership http response

Follows the nextLink in http response to iterate through
paginated group membership response in order to obtain all
groups that the user is a member of.

Also, checks cache to make sure we don't add empty groups
to the cache.
This commit is contained in:
Samir Patel 2022-04-07 14:05:55 -05:00
parent 4a155eba88
commit eea6a40fe0
2 changed files with 61 additions and 25 deletions

View file

@ -52,7 +52,8 @@ type Group struct {
// Groups holds a slice of Group for marshalling from JSON
type Groups struct {
Groups []Group `json:"value"`
NextLink string `json:"@odata.nextLink"`
Groups []Group `json:"value"`
}
// Auth holds state, configuration, and utilities needed for authentication.
@ -240,25 +241,39 @@ func (a *Auth) Redirect(w http.ResponseWriter, r *http.Request) {
func (a *Auth) getGroups(token string) ([]Group, error) {
var groups Groups
g, ok := a.groupsCache[token]
if ok && (time.Now().Sub(g.cacheTime) < a.cacheTTL) {
return g.groups, nil
gc, ok := a.groupsCache[token]
if ok && (time.Now().Sub(gc.cacheTime) < a.cacheTTL) && len(gc.groups) > 0 {
return gc.groups, nil
}
req, err := http.NewRequest("GET", a.groupEndpoint, nil)
if err != nil {
return groups.Groups, errors.Wrap(err, "creating new request to group endpoint")
nextLink := a.groupEndpoint
for nextLink != "" {
req, err := http.NewRequest("GET", nextLink, nil)
if err != nil {
return nil, errors.Wrap(err, "creating new request to group endpoint")
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
response, err := http.DefaultClient.Do(req)
if err != nil {
return nil, errors.Wrap(err, "getting group membership info")
}
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("getting group membership info: %s", response.Status)
}
var g Groups
if err = json.NewDecoder(response.Body).Decode(&g); err != nil {
return groups.Groups, errors.Wrap(err, "failed unmarshalling group membership response")
}
response.Body.Close()
groups.Groups = append(groups.Groups, g.Groups...)
nextLink = g.NextLink
}
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
response, err := http.DefaultClient.Do(req)
if err != nil {
return groups.Groups, errors.Wrap(err, "getting group membership info")
}
defer response.Body.Close()
if err = json.NewDecoder(response.Body).Decode(&groups); err != nil {
return groups.Groups, errors.Wrap(err, "failed unmarshalling group membership response")
if len(groups.Groups) == 0 {
return nil, fmt.Errorf("no groups found")
}
a.groupsCache[token] = cachedGroups{

View file

@ -352,19 +352,36 @@ func TestGetGroups(t *testing.T) {
cacheTime: time.Now(),
groups: []Group{
{
GroupID: "i feel it in the water",
GroupName: "i feel it in the earth",
GroupID: "a han noston ned wilith",
GroupName: "I smell it in the air",
},
},
},
}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
srvNext := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := json.Marshal(
Groups{
Groups: []Group{
{
GroupID: "much that once was is lost",
GroupName: "for none now live who remember it",
GroupID: "han mathon ne chae",
GroupName: "I feel it in the earth",
},
},
},
)
if err != nil {
t.Fatalf("unexpected error marshalling groups response: %v", err)
}
fmt.Fprintf(w, "%s", body)
}))
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := json.Marshal(
Groups{
NextLink: srvNext.URL,
Groups: []Group{
{
GroupID: "han mathon ne nen",
GroupName: "i feel it in the water",
},
},
},
@ -384,8 +401,8 @@ func TestGetGroups(t *testing.T) {
token: "the world is changed",
groups: []Group{
{
GroupID: "i feel it in the water",
GroupName: "i feel it in the earth",
GroupID: "a han noston ned wilith",
GroupName: "I smell it in the air",
},
},
},
@ -393,8 +410,12 @@ func TestGetGroups(t *testing.T) {
token: "i smell it in the air",
groups: []Group{
{
GroupID: "much that once was is lost",
GroupName: "for none now live who remember it",
GroupID: "han mathon ne nen",
GroupName: "i feel it in the water",
},
{
GroupID: "han mathon ne chae",
GroupName: "I feel it in the earth",
},
},
},