Skip to content

Commit

Permalink
adding operations to get cloud foundry users via v3 api
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb Washburn committed Aug 3, 2022
1 parent 61577e4 commit 5e81c20
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 6 deletions.
91 changes: 91 additions & 0 deletions payloads_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8388,3 +8388,94 @@ const GetV3ServiceCredentialBindingsByGUIDPayload = `{
}
}
}`

const listV3UsersPayload = `{
"pagination": {
"total_results": 3,
"total_pages": 2,
"first": {
"href": "https://api.example.org/v3/users?page=1&per_page=2"
},
"last": {
"href": "https://api.example.org/v3/users?page=2&per_page=2"
},
"next": {
"href": "https://api.example.org/v3/userspage2?page=2&per_page=2"
},
"previous": null
},
"resources": [
{
"guid": "16f43d50-43a2-4981-bae8-633e8248a637",
"created_at": "2022-08-02T21:37:52Z",
"updated_at": "2022-08-02T21:37:52Z",
"username": "smoke_tests",
"presentation_name": "smoke_tests",
"origin": "uaa",
"metadata": {
"labels": {},
"annotations": {}
},
"links": {
"self": {
"href": "https://api.example.org/v3/users/16f43d50-43a2-4981-bae8-633e8248a637"
}
}
},
{
"guid": "test1",
"created_at": "2022-08-02T21:40:34Z",
"updated_at": "2022-08-02T21:40:34Z",
"username": "test1",
"presentation_name": "test1",
"origin": "uaa",
"metadata": {
"labels": {},
"annotations": {}
},
"links": {
"self": {
"href": "https://api.example.org/v3/users/test1"
}
}
}
]
}`

const listV3UsersPayloadPage2 = `{
"pagination": {
"total_results": 3,
"total_pages": 2,
"first": {
"href": "https://api.example.org/v3/users?page=1&per_page=2"
},
"last": {
"href": "https://api.example.org/v3/users?page=2&per_page=2"
},
"next": {
"href": ""
},
"previous": {
"href": "https://api.example.org/v3/users?page=1&per_page=2"
}
},
"resources": [
{
"guid": "test2",
"created_at": "2022-08-02T21:41:59Z",
"updated_at": "2022-08-02T21:41:59Z",
"username": "test2",
"presentation_name": "test2",
"origin": "uaa",
"metadata": {
"labels": {},
"annotations": {}
},
"links": {
"self": {
"href": "https://api.example.org/v3/users/test2"
}
}
}
]
}`
49 changes: 45 additions & 4 deletions v3roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,53 @@ func (c *Client) ListV3RoleUsersByQuery(query url.Values) ([]V3User, error) {
return users, nil
}

func (c *Client) ListV3RoleAndUsersByQuery(query url.Values) ([]V3Role, []V3User, error) {
var roles []V3Role
var users []V3User
requestURL, err := url.Parse("/v3/roles")
if err != nil {
return nil, nil, err
}
requestURL.RawQuery = query.Encode()

for {
r := c.NewRequest("GET", fmt.Sprintf("%s?%s", requestURL.Path, requestURL.RawQuery))
resp, err := c.DoRequest(r)
if err != nil {
return nil, nil, errors.Wrap(err, "Error requesting v3 roles")
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, nil, fmt.Errorf("Error listing v3 roles, response code: %d", resp.StatusCode)
}

var data listV3RolesResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, nil, errors.Wrap(err, "Error parsing JSON from list v3 roles")
}

roles = append(roles, data.Resources...)
users = append(users, data.Included.Users...)

requestURL, err = url.Parse(data.Pagination.Next.Href)
if err != nil {
return nil, nil, errors.Wrap(err, "Error parsing next page URL")
}
if requestURL.String() == "" {
break
}
}

return roles, users, nil
}

// ListV3SpaceRolesByGUID retrieves roles based on query
func (c *Client) ListV3SpaceRolesByGUID(spaceGUID string) ([]V3User, error) {
func (c *Client) ListV3SpaceRolesByGUID(spaceGUID string) ([]V3Role, []V3User, error) {
query := url.Values{}
query["space_guids"] = []string{spaceGUID}
query["include"] = []string{"user"}
return c.ListV3RoleUsersByQuery(query)
return c.ListV3RoleAndUsersByQuery(query)
}

// ListV3SpaceRolesByGUIDAndType retrieves roles based on query
Expand All @@ -209,11 +250,11 @@ func (c *Client) ListV3OrganizationRolesByGUIDAndType(orgGUID string, roleType s
}

// ListV3OrganizationRolesByGUID retrieves roles based on query
func (c *Client) ListV3OrganizationRolesByGUID(orgGUID string) ([]V3User, error) {
func (c *Client) ListV3OrganizationRolesByGUID(orgGUID string) ([]V3Role, []V3User, error) {
query := url.Values{}
query["organization_guids"] = []string{orgGUID}
query["include"] = []string{"user"}
return c.ListV3RoleUsersByQuery(query)
return c.ListV3RoleAndUsersByQuery(query)
}

func (c *Client) DeleteV3Role(roleGUID string) error {
Expand Down
6 changes: 4 additions & 2 deletions v3roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ func TestListV3SpaceRolesByGUID(t *testing.T) {
client, err := NewClient(c)
So(err, ShouldBeNil)

users, err := client.ListV3SpaceRolesByGUID("spaceGUID1")
roles, users, err := client.ListV3SpaceRolesByGUID("spaceGUID1")
So(err, ShouldBeNil)
So(roles, ShouldHaveLength, 3)
So(users, ShouldHaveLength, 3)

So(users[0].Username, ShouldEqual, "user1")
Expand Down Expand Up @@ -159,8 +160,9 @@ func TestListV3OrgRolesByGUID(t *testing.T) {
client, err := NewClient(c)
So(err, ShouldBeNil)

users, err := client.ListV3OrganizationRolesByGUID("orgGUID1")
roles, users, err := client.ListV3OrganizationRolesByGUID("orgGUID1")
So(err, ShouldBeNil)
So(roles, ShouldHaveLength, 3)
So(users, ShouldHaveLength, 3)

So(users[0].Username, ShouldEqual, "user1")
Expand Down
54 changes: 54 additions & 0 deletions v3users.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package cfclient

import (
"encoding/json"
"fmt"
"net/http"
"net/url"

"github.com/pkg/errors"
)

// V3User implements the user object
type V3User struct {
GUID string `json:"guid,omitempty"`
Expand All @@ -11,3 +20,48 @@ type V3User struct {
Links map[string]Link `json:"links,omitempty"`
Metadata V3Metadata `json:"metadata,omitempty"`
}

type listV3UsersResponse struct {
Pagination Pagination `json:"pagination,omitempty"`
Resources []V3User `json:"resources,omitempty"`
}

// ListV3UsersByQuery by query
func (c *Client) ListV3UsersByQuery(query url.Values) ([]V3User, error) {
var users []V3User
requestURL, err := url.Parse("/v3/users")
if err != nil {
return nil, err
}
requestURL.RawQuery = query.Encode()

for {
r := c.NewRequest("GET", fmt.Sprintf("%s?%s", requestURL.Path, requestURL.RawQuery))
resp, err := c.DoRequest(r)
if err != nil {
return nil, errors.Wrap(err, "Error requesting v3 users")
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Error listing v3 users, response code: %d", resp.StatusCode)
}

var data listV3UsersResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, errors.Wrap(err, "Error parsing JSON from list v3 users")
}

users = append(users, data.Resources...)

requestURL, err = url.Parse(data.Pagination.Next.Href)
if err != nil {
return nil, errors.Wrap(err, "Error parsing next page URL")
}
if requestURL.String() == "" {
break
}
}

return users, nil
}
34 changes: 34 additions & 0 deletions v3users_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cfclient

import (
"net/http"
"net/url"
"testing"

. "github.com/smartystreets/goconvey/convey"
)

func TestListV3UserByQuery(t *testing.T) {
Convey("List V3 Users by Query", t, func() {
mocks := []MockRoute{
{"GET", "/v3/users", []string{listV3UsersPayload}, "", http.StatusOK, "", nil},
{"GET", "/v3/userspage2", []string{listV3UsersPayloadPage2}, "", http.StatusOK, "page=2&per_page=2", nil},
}
setupMultiple(mocks, t)
defer teardown()

c := &Config{ApiAddress: server.URL, Token: "foobar"}
client, err := NewClient(c)
So(err, ShouldBeNil)

query := url.Values{}
users, err := client.ListV3UsersByQuery(query)
So(err, ShouldBeNil)
So(users, ShouldHaveLength, 3)

So(users[0].Username, ShouldEqual, "smoke_tests")
So(users[1].Username, ShouldEqual, "test1")
So(users[2].Username, ShouldEqual, "test2")
})

}

0 comments on commit 5e81c20

Please sign in to comment.