Skip to content

Commit

Permalink
GetComponentsWithParams and UpdateComponent added (#359)
Browse files Browse the repository at this point in the history
* GetComponentsWithParams and test for it

* Possible fix for GetComponent tests

* UpdateComponent and tests for it

* Possible fix for UpdateComponent tests

* Check component name after UpdateComponent. It should be changed.

* Allow to get component by ID

* Add GetComponent for fetch component by ID.

* GetComponent always return only one component.

* Fix GetComponents query params

* Fix whitespace

Co-authored-by: Vladimir Fidunin <v.fidunin@vk.team>
  • Loading branch information
Tolyar and Vladimir Fidunin authored Oct 13, 2022
1 parent 1a6a98e commit b4b5d20
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 11 deletions.
51 changes: 50 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ func injectTracingHeaders(ctx context.Context, req *resty.Request) *resty.Reques

// inject tracing header into request
err := tracer.Inject(span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))

if err != nil {
return req
}
Expand Down Expand Up @@ -1440,6 +1439,56 @@ func (client *gocloak) GetComponents(ctx context.Context, token, realm string) (
return result, nil
}

// GetComponentsWithParams get all components in realm with query params
func (client *gocloak) GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) {
const errMessage = "could not get components"
var result []*Component

queryParams, err := GetQueryParams(params)
if err != nil {
return nil, errors.Wrap(err, errMessage)
}
resp, err := client.getRequestWithBearerAuth(ctx, token).
SetResult(&result).
SetQueryParams(queryParams).
Get(client.getAdminRealmURL(realm, "components"))

if err := checkForError(resp, err, errMessage); err != nil {
return nil, err
}

return result, nil
}

// GetComponent get exactly one component by ID
func (client *gocloak) GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) {
const errMessage = "could not get components"
var result *Component

componentURL := fmt.Sprintf("components/%s", componentID)

resp, err := client.getRequestWithBearerAuth(ctx, token).
SetResult(&result).
Get(client.getAdminRealmURL(realm, componentURL))

if err := checkForError(resp, err, errMessage); err != nil {
return nil, err
}

return result, nil
}

// UpdateComponent updates the given component
func (client *gocloak) UpdateComponent(ctx context.Context, token, realm string, component Component) error {
const errMessage = "could not update component"

resp, err := client.getRequestWithBearerAuth(ctx, token).
SetBody(component).
Put(client.getAdminRealmURL(realm, "components", PString(component.ID)))

return checkForError(resp, err, errMessage)
}

// GetDefaultGroups returns a list of default groups
func (client *gocloak) GetDefaultGroups(ctx context.Context, token, realm string) ([]*Group, error) {
const errMessage = "could not get default groups"
Expand Down
118 changes: 113 additions & 5 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5321,7 +5321,6 @@ func Test_ErrorsGetAuthorizationPolicyScopes(t *testing.T) {
},
},
})

})

// Create SCOPE
Expand Down Expand Up @@ -6405,10 +6404,9 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlo
cfg := GetConfig(t)
client := NewClientWithDebug(t)
token := GetAdminToken(t, client)
authExec :=
gocloak.CreateAuthenticationExecutionRepresentation{
Provider: gocloak.StringP("idp-auto-link"),
}
authExec := gocloak.CreateAuthenticationExecutionRepresentation{
Provider: gocloak.StringP("idp-auto-link"),
}
authFlow := gocloak.AuthenticationFlowRepresentation{
Alias: gocloak.StringP("testauthflow2"),
BuiltIn: gocloak.BoolP(false),
Expand Down Expand Up @@ -6611,3 +6609,113 @@ func TestGocloak_UpdateRequiredAction(t *testing.T) {
err := client.UpdateRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction)
require.NoError(t, err, "Failed to update required action")
}

func CreateComponent(t *testing.T, client gocloak.GoCloak) (func(), *gocloak.Component) {
newComponent := &gocloak.Component{
Name: GetRandomNameP("CreateComponent"),
ProviderID: gocloak.StringP("rsa-generated"),
ProviderType: gocloak.StringP("org.keycloak.keys.KeyProvider"),
}
cfg := GetConfig(t)
token := GetAdminToken(t, client)
createdID, err := client.CreateComponent(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
*newComponent,
)
require.NoError(t, err, "CreateComponent failed")
tearDown := func() {
_ = client.DeleteComponent(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
createdID,
)
}
newComponent.ID = &createdID
return tearDown, newComponent
}

func Test_GetComponentsWithParams(t *testing.T) {
// t.Parallel()
cfg := GetConfig(t)
client := NewClientWithDebug(t)
token := GetAdminToken(t, client)
tearDownComponent, component := CreateComponent(t, client)
defer tearDownComponent()

components, err := client.GetComponentsWithParams(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
gocloak.GetComponentsParams{
Name: component.Name,
ProviderType: component.ProviderType,
ParentID: component.ParentID,
},
)
require.NoError(t, err, "GetComponentsWithParams failed")
if len(components) != 1 {
require.NoError(t, fmt.Errorf("Expected 1 component, got %d", len(components)), "GetComponentsWithParams failed")
}
}

func Test_GetComponent(t *testing.T) {
// t.Parallel()
cfg := GetConfig(t)
client := NewClientWithDebug(t)
token := GetAdminToken(t, client)
tearDownComponent, component := CreateComponent(t, client)
defer tearDownComponent()

_, err := client.GetComponent(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
*component.ID,
)
require.NoError(t, err, "GetComponent failed")
}

func Test_UpdateComponent(t *testing.T) {
// t.Parallel()
cfg := GetConfig(t)
client := NewClientWithDebug(t)
token := GetAdminToken(t, client)
tearDownComponent, component := CreateComponent(t, client)
defer tearDownComponent()

component.Name = GetRandomNameP("UpdateComponent")

err := client.UpdateComponent(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
*component,
)
require.NoError(t, err, "UpdateComponent failed")

components, err := client.GetComponentsWithParams(
context.Background(),
token.AccessToken,
cfg.GoCloak.Realm,
gocloak.GetComponentsParams{
Name: component.Name,
ProviderType: component.ProviderType,
ParentID: component.ParentID,
},
)
require.NoError(t, err, "GetComponentWithParams after UpdateComponent failed")

if len(components) != 1 {
require.NoError(t, fmt.Errorf("Expected 1 component, got %d", len(components)), "UpdateComponent failed")
}
if *components[0].Name != *component.Name {
require.NoError(
t,
fmt.Errorf("Expected name after update '%s', got '%s'", *component.Name, *components[0].Name),
"UpdateComponent failed",
)
}
}
6 changes: 6 additions & 0 deletions gocloak.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ type GoCloak interface {
GetKeyStoreConfig(ctx context.Context, accessToken, realm string) (*KeyStoreConfig, error)
// GetComponents gets components of the given realm
GetComponents(ctx context.Context, accessToken, realm string) ([]*Component, error)
// GetComponentsWithParams get all components in realm with query params
GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error)
// GetComponent get exactly one component by ID
GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error)
// UpdateComponent updates the given component
UpdateComponent(ctx context.Context, token, realm string, component Component) error
// GetDefaultGroups returns a list of default groups
GetDefaultGroups(ctx context.Context, accessToken, realm string) ([]*Group, error)
// AddDefaultGroup adds group to the list of default groups
Expand Down
5 changes: 1 addition & 4 deletions model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,13 @@ func TestStringer(t *testing.T) {
"displayName": "someRealm"
}`
assert.Equal(t, expectedStr, str)

}

type Stringable interface {
String() string
}

func TestStringerOmitEmpty(t *testing.T) {

customs := []Stringable{
&gocloak.CertResponseKey{},
&gocloak.CertResponse{},
Expand Down Expand Up @@ -333,14 +331,13 @@ func TestStringerOmitEmpty(t *testing.T) {
&gocloak.GetResourcePoliciesParams{},
&gocloak.CredentialRepresentation{},
&gocloak.GetUsersParams{},
&gocloak.GetComponentsParams{},
&gocloak.GetClientsParams{},
&gocloak.RequestingPartyTokenOptions{},
&gocloak.RequestingPartyPermission{},
}

for _, custom := range customs {

assert.Equal(t, "{}", custom.(Stringable).String())
}

}
9 changes: 8 additions & 1 deletion models.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ type GetUsersParams struct {
Username *string `json:"username,omitempty"`
}

// GetComponentsParams represents the optional parameters for getting components
type GetComponentsParams struct {
Name *string `json:"name,omitempty"`
ProviderType *string `json:"provider,omitempty"`
ParentID *string `json:"parent,omitempty"`
}

// ExecuteActionsEmail represents parameters for executing action emails
type ExecuteActionsEmail struct {
UserID *string `json:"-"`
Expand Down Expand Up @@ -1361,7 +1368,6 @@ type RequiredActionProviderRepresentation struct {

// prettyStringStruct returns struct formatted into pretty string
func prettyStringStruct(t interface{}) string {

json, err := json.MarshalIndent(t, "", "\t")
if err != nil {
return ""
Expand All @@ -1388,6 +1394,7 @@ func (v *Attributes) String() string { return pre
func (v *Access) String() string { return prettyStringStruct(v) }
func (v *UserGroup) String() string { return prettyStringStruct(v) }
func (v *GetUsersParams) String() string { return prettyStringStruct(v) }
func (v *GetComponentsParams) String() string { return prettyStringStruct(v) }
func (v *ExecuteActionsEmail) String() string { return prettyStringStruct(v) }
func (v *Group) String() string { return prettyStringStruct(v) }
func (v *GroupsCount) String() string { return prettyStringStruct(v) }
Expand Down

0 comments on commit b4b5d20

Please sign in to comment.