Repository: Nerzal/gocloak
Pull request #283 (2021-05-27 18:49:13)

Added GetIdentityProviderMapperById, UpdateIdentityMapper and GetRoleParams added to GetRealmRoles
Hi,

This PR adds support for GetIdentityProviderMapperById, UpdateIdentityMapper and I have also added GetRoleParams to the existing GetRealmRoles function.

Let me know if any change is required 

Thanks :)


Patch:
diff --git a/client.go b/client.go
index a91d764..2980c9e 100644
--- a/client.go
+++ b/client.go
@@ -1612,12 +1612,18 @@ func (client *gocloak) GetRealmRole(ctx context.Context, token, realm, roleName
 }
 
 // GetRealmRoles get all roles of the given realm.
-func (client *gocloak) GetRealmRoles(ctx context.Context, token, realm string) ([]*Role, error) {
+func (client *gocloak) GetRealmRoles(ctx context.Context, token, realm string, params GetRoleParams) ([]*Role, error) {
 	const errMessage = "could not get realm roles"
 
 	var result []*Role
+	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, "roles"))
 
 	if err := checkForError(resp, err, errMessage); err != nil {
@@ -2400,6 +2406,33 @@ func (client *gocloak) GetIdentityProviderMappers(ctx context.Context, token, re
 	return result, nil
 }
 
+// GetIdentityProviderMapperByID gets the mapper of an identity provider
+func (client *gocloak) GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error) {
+	const errMessage = "could not get identity provider mappers"
+
+	var result IdentityProviderMapper
+	resp, err := client.getRequestWithBearerAuth(ctx, token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID))
+
+	if err := checkForError(resp, err, errMessage); err != nil {
+		return nil, err
+	}
+
+	return &result, nil
+}
+
+// UpdateIdentityProviderMapper updates mapper of an identity provider
+func (client *gocloak) UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error {
+	const errMessage = "could not update identity provider mapper"
+
+	resp, err := client.getRequestWithBearerAuth(ctx, token).
+		SetBody(mapper).
+		Put(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", PString(mapper.ID)))
+
+	return checkForError(resp, err, errMessage)
+}
+
 // ------------------
 // Protection API
 // ------------------
diff --git a/gocloak.go b/gocloak.go
index 826840d..073b604 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -180,7 +180,7 @@ type GoCloak interface {
 	// GetRealmRole returns a role from a realm by role's name
 	GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error)
 	// GetRealmRoles get all roles of the given realm. It's an alias for the GetRoles function
-	GetRealmRoles(ctx context.Context, accessToken, realm string) ([]*Role, error)
+	GetRealmRoles(ctx context.Context, accessToken, realm string, params GetRoleParams) ([]*Role, error)
 	// GetRealmRolesByUserID returns all roles assigned to the given user
 	GetRealmRolesByUserID(ctx context.Context, accessToken, realm, userID string) ([]*Role, error)
 	// GetRealmRolesByGroupID returns all roles assigned to the given group
@@ -324,6 +324,10 @@ type GoCloak interface {
 	ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error)
 	// CreateIdentityProviderMapper creates an instance of an identity provider mapper associated with the given alias
 	CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error
+	// GetIdentityProviderMapperByID gets the mapper of an identity provider
+	GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error)
+	// UpdateIdentityProviderMapper updates mapper of an identity provider
+	UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error
 	// DeleteIdentityProviderMapper deletes an instance of an identity provider mapper associated with the given alias and mapper ID
 	DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error
 	// GetIdentityProviderMappers returns list of mappers associated with an identity provider
diff --git a/models.go b/models.go
index 2ff8599..6be8536 100644
--- a/models.go
+++ b/models.go
@@ -340,6 +340,13 @@ type Role struct {
 	Attributes         *map[string][]string      `json:"attributes,omitempty"`
 }
 
+// GetRoleParams represents the optional parameters for getting roles
+type GetRoleParams struct {
+	First  *int    `json:"first,string,omitempty"`
+	Max    *int    `json:"max,string,omitempty"`
+	Search *string `json:"search,omitempty"`
+}
+
 // ClientMappingsRepresentation is a client role mappings
 type ClientMappingsRepresentation struct {
 	ID       *string `json:"id,omitempty"`
@@ -1150,6 +1157,7 @@ func (v *GroupsCount) String() string                               { return pre
 func (obj *GetGroupsParams) String() string                         { return prettyStringStruct(obj) }
 func (v *CompositesRepresentation) String() string                  { return prettyStringStruct(v) }
 func (v *Role) String() string                                      { return prettyStringStruct(v) }
+func (v *GetRoleParams) String() string                             { return prettyStringStruct(v) }
 func (v *ClientMappingsRepresentation) String() string              { return prettyStringStruct(v) }
 func (v *MappingsRepresentation) String() string                    { return prettyStringStruct(v) }
 func (v *ClientScope) String() string                               { return prettyStringStruct(v) }


Test patch:
diff --git a/client_test.go b/client_test.go
index 8a8cc8b..7e47885 100644
--- a/client_test.go
+++ b/client_test.go
@@ -1684,6 +1684,7 @@ func TestGocloak_ClientScopeMappingsRealmRoles(t *testing.T) {
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
+		gocloak.GetRoleParams{},
 	)
 	require.NoError(t, err, "GetRealmRoles failed")
 
@@ -2281,7 +2282,8 @@ func TestGocloak_GetRealmRoles(t *testing.T) {
 	roles, err := client.GetRealmRoles(
 		context.Background(),
 		token.AccessToken,
-		cfg.GoCloak.Realm)
+		cfg.GoCloak.Realm,
+		gocloak.GetRoleParams{})
 	require.NoError(t, err, "GetRealmRoles failed")
 	t.Logf("Roles: %+v", roles)
 }
@@ -3903,21 +3905,23 @@ func TestGocloak_CreateGetDeleteUserFederatedIdentity(t *testing.T) {
 	require.NoError(t, err)
 	require.Equal(t, idp, res)
 
+	mapperP := gocloak.IdentityProviderMapper{
+		Name:                   gocloak.StringP("add-google-origin-attribute"),
+		IdentityProviderMapper: gocloak.StringP("hardcoded-attribute-idp-mapper"),
+		IdentityProviderAlias:  gocloak.StringP("google"),
+		Config: &map[string]string{
+			"syncMode":        "INHERIT",
+			"attribute":       "origin",
+			"attribute.value": "google",
+		},
+	}
+
 	err = client.CreateIdentityProviderMapper(
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
 		"google",
-		gocloak.IdentityProviderMapper{
-			Name:                   gocloak.StringP("add-google-origin-attribute"),
-			IdentityProviderMapper: gocloak.StringP("hardcoded-attribute-idp-mapper"),
-			IdentityProviderAlias:  gocloak.StringP("google"),
-			Config: &map[string]string{
-				"syncMode":        "INHERIT",
-				"attribute":       "origin",
-				"attribute.value": "google",
-			},
-		},
+		mapperP,
 	)
 	require.NoError(t, err)
 
@@ -3927,9 +3931,34 @@ func TestGocloak_CreateGetDeleteUserFederatedIdentity(t *testing.T) {
 		cfg.GoCloak.Realm,
 		"google",
 	)
+	require.NoError(t, err)
 	require.Len(t, mappers, 1)
 	mapperID := mappers[0].ID
 
+	mapperP.ID = mapperID
+	// get single mapper
+	err = client.UpdateIdentityProviderMapper(
+		context.Background(),
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		"google",
+		mapperP,
+	)
+	require.NoError(t, err)
+
+	mapper, err := client.GetIdentityProviderMapperByID(
+		context.Background(),
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		"google",
+		gocloak.PString(mapperID),
+	)
+	require.NoError(t, err, "GetIdentityProviderMapperByID failed")
+	require.Equal(t, mapperP.Name, mapper.Name)
+	require.Equal(t, mapperP.IdentityProviderAlias, mapper.IdentityProviderAlias)
+	require.Equal(t, mapperP.IdentityProviderMapper, mapper.IdentityProviderMapper)
+	require.NotNil(t, mapper.Config)
+
 	defer func() {
 		err = client.DeleteIdentityProviderMapper(
 			context.Background(),
@@ -4740,6 +4769,7 @@ func TestGocloak_RolePolicy(t *testing.T) {
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
+		gocloak.GetRoleParams{},
 	)
 	require.NoError(t, err, "GetRealmRoles failed")
 	require.GreaterOrEqual(t, len(roles), 1, "GetRealmRoles failed")
diff --git a/model_test.go b/model_test.go
index a660471..818ef3a 100644
--- a/model_test.go
+++ b/model_test.go
@@ -235,6 +235,7 @@ func TestStringerOmitEmpty(t *testing.T) {
 		&gocloak.GetGroupsParams{},
 		&gocloak.CompositesRepresentation{},
 		&gocloak.Role{},
+		&gocloak.GetRoleParams{},
 		&gocloak.ClientMappingsRepresentation{},
 		&gocloak.MappingsRepresentation{},
 		&gocloak.ClientScope{},