Skip to content

Commit c3b6717

Browse files
authored
Merge pull request #148 from Kump3r/master
Switching to CloudFoundry v3 API
2 parents 8337b8f + 4efbde3 commit c3b6717

File tree

2 files changed

+400
-98
lines changed

2 files changed

+400
-98
lines changed

connector/cloudfoundry/cloudfoundry.go

+80-57
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,40 @@ type Config struct {
4646
}
4747

4848
type ccResponse struct {
49-
NextURL string `json:"next_url"`
50-
Resources []resource `json:"resources"`
51-
TotalResults int `json:"total_results"`
49+
Pagination pagination `json:"pagination"`
50+
Resources []resource `json:"resources"`
51+
}
52+
53+
type pagination struct {
54+
Next href `json:"next"`
55+
}
56+
57+
type href struct {
58+
Href string `json:"href"`
5259
}
5360

5461
type resource struct {
55-
Metadata metadata `json:"metadata"`
56-
Entity entity `json:"entity"`
62+
GUID string `json:"guid"`
63+
Name string `json:"name,omitempty"`
64+
Type string `json:"type,omitempty"`
65+
Relationships relationships `json:"relationships"`
5766
}
5867

59-
type metadata struct {
60-
GUID string `json:"guid"`
68+
type relationships struct {
69+
Organization relOrganization `json:"organization"`
70+
Space relSpace `json:"space"`
71+
}
72+
73+
type relOrganization struct {
74+
Data data `json:"data"`
6175
}
6276

63-
type entity struct {
64-
Name string `json:"name"`
65-
OrganizationGUID string `json:"organization_guid"`
77+
type relSpace struct {
78+
Data data `json:"data"`
79+
}
80+
81+
type data struct {
82+
GUID string `json:"guid"`
6683
}
6784

6885
type space struct {
@@ -77,6 +94,18 @@ type org struct {
7794
GUID string
7895
}
7996

97+
type infoResp struct {
98+
Links links `json:"links"`
99+
}
100+
101+
type links struct {
102+
Login login `json:"login"`
103+
}
104+
105+
type login struct {
106+
Href string `json:"href"`
107+
}
108+
80109
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
81110
var err error
82111

@@ -94,7 +123,7 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
94123
}
95124

96125
apiURL := strings.TrimRight(c.APIURL, "/")
97-
apiResp, err := cloudfoundryConn.httpClient.Get(fmt.Sprintf("%s/v2/info", apiURL))
126+
apiResp, err := cloudfoundryConn.httpClient.Get(apiURL)
98127
if err != nil {
99128
logger.Errorf("failed-to-send-request-to-cloud-controller-api", err)
100129
return nil, err
@@ -108,10 +137,11 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
108137
return nil, err
109138
}
110139

111-
var apiResult map[string]interface{}
140+
var apiResult infoResp
141+
112142
json.NewDecoder(apiResp.Body).Decode(&apiResult)
113143

114-
uaaURL := strings.TrimRight(apiResult["authorization_endpoint"].(string), "/")
144+
uaaURL := strings.TrimRight(apiResult.Links.Login.Href, "/")
115145
uaaResp, err := cloudfoundryConn.httpClient.Get(fmt.Sprintf("%s/.well-known/openid-configuration", uaaURL))
116146
if err != nil {
117147
logger.Errorf("failed-to-send-request-to-uaa-api", err)
@@ -191,40 +221,39 @@ func (c *cloudfoundryConnector) LoginURL(scopes connector.Scopes, callbackURL, s
191221
return oauth2Config.AuthCodeURL(state), nil
192222
}
193223

194-
func fetchRoleSpaces(baseURL, path, role string, client *http.Client) ([]space, error) {
195-
resources, err := fetchResources(baseURL, path, client)
196-
if err != nil {
197-
return nil, fmt.Errorf("failed to fetch resources: %v", err)
198-
}
224+
func filterUserOrgsSpaces(userOrgsSpaces []resource, orgs []resource, spaces []resource) ([]org, []space) {
225+
var filteredOrgs []org
226+
var filteredSpaces []space
199227

200-
spaces := make([]space, len(resources))
201-
for i, resource := range resources {
202-
spaces[i] = space{
203-
Name: resource.Entity.Name,
204-
GUID: resource.Metadata.GUID,
205-
OrgGUID: resource.Entity.OrganizationGUID,
206-
Role: role,
228+
orgMap := make(map[string]org)
229+
spaceMap := make(map[string]space)
230+
231+
for _, org_resource := range orgs {
232+
orgMap[org_resource.GUID] = org{
233+
Name: org_resource.Name,
234+
GUID: org_resource.GUID,
207235
}
208236
}
209237

210-
return spaces, nil
211-
}
212-
213-
func fetchOrgs(baseURL, path string, client *http.Client) ([]org, error) {
214-
resources, err := fetchResources(baseURL, path, client)
215-
if err != nil {
216-
return nil, fmt.Errorf("failed to fetch resources: %v", err)
238+
for _, space_resource := range spaces {
239+
spaceMap[space_resource.GUID] = space{
240+
Name: space_resource.Name,
241+
GUID: space_resource.GUID,
242+
OrgGUID: space_resource.Relationships.Organization.Data.GUID,
243+
}
217244
}
218245

219-
orgs := make([]org, len(resources))
220-
for i, resource := range resources {
221-
orgs[i] = org{
222-
Name: resource.Entity.Name,
223-
GUID: resource.Metadata.GUID,
246+
for _, userOrgSpace := range userOrgsSpaces {
247+
if space, ok := spaceMap[userOrgSpace.Relationships.Space.Data.GUID]; ok {
248+
space.Role = strings.TrimPrefix(userOrgSpace.Type, "space_")
249+
filteredSpaces = append(filteredSpaces, space)
250+
}
251+
if org, ok := orgMap[userOrgSpace.Relationships.Organization.Data.GUID]; ok {
252+
filteredOrgs = append(filteredOrgs, org)
224253
}
225254
}
226255

227-
return orgs, nil
256+
return filteredOrgs, filteredSpaces
228257
}
229258

230259
func fetchResources(baseURL, path string, client *http.Client) ([]resource, error) {
@@ -249,12 +278,12 @@ func fetchResources(baseURL, path string, client *http.Client) ([]resource, erro
249278
response := ccResponse{}
250279
err = json.NewDecoder(resp.Body).Decode(&response)
251280
if err != nil {
252-
return nil, fmt.Errorf("failed to parse spaces: %v", err)
281+
return nil, fmt.Errorf("failed to parse response: %v", err)
253282
}
254283

255284
resources = append(resources, response.Resources...)
256285

257-
path = response.NextURL
286+
path = strings.TrimPrefix(response.Pagination.Next.Href, baseURL)
258287
if path == "" {
259288
break
260289
}
@@ -349,36 +378,30 @@ func (c *cloudfoundryConnector) HandleCallback(s connector.Scopes, r *http.Reque
349378
identity.EmailVerified, _ = userInfoResult["email_verified"].(bool)
350379

351380
var (
352-
devPath = fmt.Sprintf("/v2/users/%s/spaces", identity.UserID)
353-
auditorPath = fmt.Sprintf("/v2/users/%s/audited_spaces", identity.UserID)
354-
managerPath = fmt.Sprintf("/v2/users/%s/managed_spaces", identity.UserID)
355-
orgsPath = fmt.Sprintf("/v2/users/%s/organizations", identity.UserID)
381+
orgsPath = "/v3/organizations"
382+
spacesPath = "/v3/spaces"
383+
userOrgsSpacesPath = fmt.Sprintf("/v3/roles?user_guids=%s&types=space_developer,space_manager,space_auditor,organization_user", identity.UserID)
356384
)
357385

358386
if s.Groups {
359-
orgs, err := fetchOrgs(c.apiURL, orgsPath, client)
387+
userOrgsSpaces, err := fetchResources(c.apiURL, userOrgsSpacesPath, client)
360388
if err != nil {
361-
return identity, fmt.Errorf("failed to fetch organizaitons: %v", err)
389+
return identity, fmt.Errorf("failed to fetch user organizations: %v", err)
362390
}
363391

364-
developerSpaces, err := fetchRoleSpaces(c.apiURL, devPath, "developer", client)
392+
orgs, err := fetchResources(c.apiURL, orgsPath, client)
365393
if err != nil {
366-
return identity, fmt.Errorf("failed to fetch spaces for developer roles: %v", err)
367-
}
368-
369-
auditorSpaces, err := fetchRoleSpaces(c.apiURL, auditorPath, "auditor", client)
370-
if err != nil {
371-
return identity, fmt.Errorf("failed to fetch spaces for developer roles: %v", err)
394+
return identity, fmt.Errorf("failed to fetch organizaitons: %v", err)
372395
}
373396

374-
managerSpaces, err := fetchRoleSpaces(c.apiURL, managerPath, "manager", client)
397+
spaces, err := fetchResources(c.apiURL, spacesPath, client)
375398
if err != nil {
376-
return identity, fmt.Errorf("failed to fetch spaces for developer roles: %v", err)
399+
return identity, fmt.Errorf("failed to fetch spaces: %v", err)
377400
}
378401

379-
developerSpaces = append(developerSpaces, append(auditorSpaces, managerSpaces...)...)
402+
developerOrgs, developerSpaces := filterUserOrgsSpaces(userOrgsSpaces, orgs, spaces)
380403

381-
identity.Groups = getGroupsClaims(orgs, developerSpaces)
404+
identity.Groups = getGroupsClaims(developerOrgs, developerSpaces)
382405
}
383406

384407
if s.OfflineAccess {

0 commit comments

Comments
 (0)