Skip to content

Commit

Permalink
Implement operation to fetch access request belonging to an app (#36)
Browse files Browse the repository at this point in the history
* Add method to get AR belonging to an app

* Add GetAR method to Apps interface

* Regenearet mocks

* Create an internal ARDetails type to allow conversion of strings to []string

* Remove ARSummary

* Implement UnmarshalJSON in ARDetails

* Add unit test for apps.GetAR

* Use a fake JWT for credentials

* Update fixture
  • Loading branch information
edsonmichaque committed Aug 17, 2023
1 parent 4643c02 commit 42a7edb
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 28 deletions.
28 changes: 24 additions & 4 deletions apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
)

const (
pathAppARs = "/portal-api/apps"
pathAppAR = "/portal-api/apps/%v"
pathAppAR = "/portal-api/apps/%v/access-requests/%v"
pathAppARs = "/portal-api/apps/%v/access-requests"
pathApps = "/portal-api/apps"
pathApp = "/portal-api/apps/%v"
pathAppProvision = "/portal-api/apps/%v/provision"
Expand All @@ -26,6 +26,7 @@ type Apps interface {
ListApps(ctx context.Context, opts ...Option) (*ListAppsOutput, error)
ListARs(ctx context.Context, id int64, opts ...Option) (*ListARsOutput, error)
ProvisionApp(ctx context.Context, id int64, opts ...Option) (*StatusOutput, error)
GetAR(ctx context.Context, appID int64, arID int64, opts ...Option) (*AROutput, error)
}

type apps struct {
Expand Down Expand Up @@ -110,14 +111,33 @@ func (p apps) ListARs(ctx context.Context, id int64, opts ...Option) (*ListARsOu
return nil, err
}

var ars []ARSummary
var ars struct {
AccessRequests []ARDetails `json:"AccessRequests,omitempty"`
}

if err := resp.Unmarshal(&ars); err != nil {
return nil, err
}

return &ListARsOutput{
Data: ars,
Data: ars.AccessRequests,
}, nil
}

func (p apps) GetAR(ctx context.Context, appID int64, arID int64, opts ...Option) (*AROutput, error) {
resp, err := p.client.doGet(ctx, fmt.Sprintf(pathAppAR, appID, arID), nil, opts...)
if err != nil {
return nil, err
}

var ar ARDetails

if err := resp.Unmarshal(&ar); err != nil {
return nil, err
}

return &AROutput{
Data: &ar,
}, nil
}

Expand Down
46 changes: 46 additions & 0 deletions apps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,56 @@ func TestApps_Get(t *testing.T) {
assertApps(t, want, resp.Data)
}

func TestApps_GetAR(t *testing.T) {
srv := NewServer(t)
defer srv.Close()

token := "TOKEN"

srv.mux.HandleFunc("/portal-api/apps/1/access-requests/30", func(w http.ResponseWriter, r *http.Request) {
httpResponse := httpParse(t, "portal-api/get_ar_success.txt")
defer httpResponse.Body.Close()

assertMethod(t, "GET", r)
assertHeader(t, r, "Authorization", token)

w.WriteHeader(httpResponse.StatusCode)
_, err := io.Copy(w, httpResponse.Body)
assert.NoError(t, err)
})

client, err := New(
WithBaseURL(srv.srv.URL),
WithToken(token),
)
assert.NoError(t, err)

resp, err := client.Apps().GetAR(context.Background(), 1, 30)
assert.NoError(t, err)

want := &ARDetails{
Client: "v34",
Catalogue: "Public Catalogue",
Plan: "free_plan",
Products: []string{
"puvlic_product",
},
}

assertAR(t, want, resp.Data)
}

func assertApps(t *testing.T, want, got []App) {
require.Equal(t, len(want), len(got), "wanted len %v but got len", len(want), len(got))

for k, v := range want {
assert.Equal(t, v, got[k])
}
}

func assertAR(t *testing.T, want, got *ARDetails) {
assert.Equal(t, want.AuthType, got.AuthType, "wanted auth type %v but got %v", want.AuthType, got.AuthType)
assert.Equal(t, want.Catalogue, got.Catalogue, "wanted catalogue %v but got %v", want.Catalogue, got.Catalogue)
assert.Equal(t, want.Client, got.Client, "wanted client %v but got %v", want.Client, got.Client)
assert.Equal(t, want.Plan, got.Plan, "wanted plan %v but got %v", want.Plan, got.Plan)
}
79 changes: 55 additions & 24 deletions ars.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package portal

import (
"context"
"encoding/json"
"fmt"
"net/http"
)
Expand Down Expand Up @@ -53,7 +54,7 @@ func (p ars) ListARs(ctx context.Context, opts ...Option) (*ListARsOutput, error
return nil, err
}

var ars []ARSummary
var ars []ARDetails

if err := resp.Unmarshal(&ars); err != nil {
return nil, err
Expand Down Expand Up @@ -123,36 +124,66 @@ func (p ars) DeleteAR(ctx context.Context, id int64, opts ...Option) (*StatusOut
}

type ARDetails struct {
Catalog string `json:"Catalog,omitempty"`
AuthType string `json:"AuthType,omitempty"`
Catalogue string `json:"Catalogue,omitempty"`
Client string `json:"Client,omitempty"`
CreatedAt string `json:"CreatedAt,omitempty"`
UpdatedAt string `json:"UpdatedAt,omitempty"`
DeletedAt string `json:"DeletedAt,omitempty"`
Plan string `json:"Plan,omitempty"`
User string `json:"User,omitempty"`
AuthType string `json:"AuthType,omitempty"`
Credentials []Credentials `json:"Credentials,omitempty"`
DCREnabled bool `json:"DCREnabled,omitempty"`
DeletedAt string `json:"DeletedAt,omitempty"`
ID int64 `json:"ID,omitempty"`
Plan string `json:"Plan,omitempty"`
Products []string `json:"Products,omitempty"`
ProvisionImmediately bool `json:"ProvisionImmediately,omitempty"`
Status string `json:"Status,omitempty"`
Products string `json:"Products,omitempty"`
Credentials []Credentials `json:"Credentials,omitempty"`
UpdatedAt string `json:"UpdatedAt,omitempty"`
User string `json:"User,omitempty"`
}

type ARSummary struct {
Catalog string `json:"Catalog,omitempty"`
Client string `json:"Client,omitempty"`
CreatedAt string `json:"CreatedAt,omitempty"`
UpdatedAt string `json:"UpdatedAt,omitempty"`
DeletedAt string `json:"DeletedAt,omitempty"`
Plan string `json:"Plan,omitempty"`
User string `json:"User,omitempty"`
AuthType string `json:"AuthType,omitempty"`
DCREnabled bool `json:"DCREnabled,omitempty"`
ID int16 `json:"ID,omitempty"`
ProvisionImmediately bool `json:"ProvisionImmediately,omitempty"`
Status string `json:"Status,omitempty"`
Products string `json:"Products,omitempty"`
func (a *ARDetails) UnmarshalJSON(b []byte) error {
var customAR struct {
AuthType string `json:"AuthType,omitempty"`
Catalogue string `json:"Catalogue,omitempty"`
Client string `json:"Client,omitempty"`
CreatedAt string `json:"CreatedAt,omitempty"`
Credentials []Credentials `json:"Credentials,omitempty"`
DCREnabled bool `json:"DCREnabled,omitempty"`
DeletedAt string `json:"DeletedAt,omitempty"`
ID int64 `json:"ID,omitempty"`
Plan string `json:"Plan,omitempty"`
Products interface{} `json:"Products,omitempty"`
ProvisionImmediately bool `json:"ProvisionImmediately,omitempty"`
Status string `json:"Status,omitempty"`
UpdatedAt string `json:"UpdatedAt,omitempty"`
User string `json:"User,omitempty"`
}

if err := json.Unmarshal(b, &customAR); err != nil {
return err
}

a.AuthType = customAR.AuthType
a.Catalogue = customAR.Catalogue
a.Client = customAR.Client
a.CreatedAt = customAR.CreatedAt
a.Credentials = customAR.Credentials
a.DCREnabled = customAR.DCREnabled
a.DeletedAt = customAR.DeletedAt
a.ID = customAR.ID
a.Plan = customAR.Plan
a.ProvisionImmediately = customAR.ProvisionImmediately
a.Status = customAR.Status
a.UpdatedAt = customAR.UpdatedAt
a.User = customAR.User

switch k := customAR.Products.(type) {
case []string:
a.Products = k
case string:
a.Products = []string{k}
}

return nil
}

type Credentials struct {
Expand All @@ -174,7 +205,7 @@ type Credentials struct {
}

type ListARsOutput struct {
Data []ARSummary
Data []ARDetails
Response *http.Response
}

Expand Down
33 changes: 33 additions & 0 deletions mocks/apps.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions testdata/portal-api/get_ar_success.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Date: Tue, 15 Aug 2023 19:42:37 GMT
Content-Length: 802

{
"Catalogue": "Public Catalogue",
"Client": "v34",
"CreatedAt": "2023-08-14 19:09",
"Credentials": [
{
"AccessRequest": "AccessRequest#30",
"Credential": "eyJvcmciOiI2MTcwMDZjMTgyOWI2ZjAwMDFjNmMwMzkiLCJpZCI6IjQ0ZDc1OWYwZGVjYzQ2MDliYmMxNDVjYjJkMTJhNjM4IiwiaCI6Im11cm11cjY0In0=",
"CredentialHash": "60bf6ae8aeddde79",
"DCRRegistrationAccessToken": "",
"DCRRegistrationClientURI": "",
"DCRResponse": "",
"Expires": "1970-01-01 02:00",
"GrantType": "",
"ID": 29,
"JWKSURI": "",
"OAuthClientID": "",
"OAuthClientSecret": "",
"RedirectURI": "",
"ResponseType": "",
"Scope": "",
"TokenEndpoints": ""
}
],
"DeletedAt": "",
"Plan": "free_plan",
"PolicyService": [],
"Products": "public_product",
"UpdatedAt": "2023-08-14 19:09",
"User": "User#1"
}
44 changes: 44 additions & 0 deletions testdata/portal-api/list_app_access_requests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json
Pragma: no-cache
Date: Tue, 15 Aug 2023 19:22:56 GMT
Content-Length: 933

[
{
"AuthType": "multiAuth",
"Catalogue": "Public Catalogue",
"Client": "v34",
"CreatedAt": "2023-08-14 19:09",
"Credentials": [
{
"AccessRequest": "AccessRequest#30",
"Credential": "eyJvcmciOiI2MTcwMDZjMTgyOWI2ZjAwMDFjNmMwMzkiLCJpZCI6IjQ0ZDc1OWYwZGVjYzQ2MDliYmMxNDVjYjJkMTJhNjM4IiwiaCI6Im11cm11cjY0In0=",
"CredentialHash": "60bf6ae8aeddde79",
"DCRRegistrationAccessToken": "",
"DCRRegistrationClientURI": "",
"DCRResponse": "",
"Expires": "1970-01-01 02:00",
"GrantType": "",
"ID": 29,
"JWKSURI": "",
"OAuthClientID": "",
"OAuthClientSecret": "",
"RedirectURI": "",
"ResponseType": "",
"Scope": "",
"TokenEndpoints": ""
}
],
"DCREnabled": false,
"DeletedAt": "",
"ID": 30,
"Plan": "free_plan",
"Products": "public_product",
"ProvisionImmediately": false,
"Status": "approved",
"UpdatedAt": "2023-08-14 19:09",
"User": "User#1"
}
]

0 comments on commit 42a7edb

Please sign in to comment.