Repository: Nerzal/gocloak
Pull request #90 (2019-08-13 13:21:30)

add create and delete client protocol mappers
Thanks for merging my other merge request. Maybe you are interested in this change, too. It creates and deletes protocol mappers in the client. :)



Patch:
diff --git a/README.md b/README.md
index c25d285..ccf96a4 100644
--- a/README.md
+++ b/README.md
@@ -166,6 +166,8 @@ type GoCloak interface {
 	GetClients(accessToken string, realm string, params GetClientsParams) ([]*Client, error)
 	GetUsersByRoleName(token string, realm string, roleName string) ([]*User, error)
 	UserAttributeContains(attributes map[string][]string, attribute string, value string) bool
+	CreateClientProtocolMapper(token, realm, clientID string, mapper ProtocolMapperRepresentation) error
+	DeleteClientProtocolMapper(token, realm, clientID, mapperID string) error
 
 	// *** Realm Roles ***
 
diff --git a/client.go b/client.go
index 5a29aee..6df1c9a 100644
--- a/client.go
+++ b/client.go
@@ -684,6 +684,23 @@ func (client *gocloak) GetClientUserSessions(token, realm, clientID string) ([]*
 	return res, nil
 }
 
+// CreateClientProtocolMapper creates a protocol mapper in client scope
+func (client *gocloak) CreateClientProtocolMapper(token, realm, clientID string, mapper ProtocolMapperRepresentation) error {
+	resp, err := client.getRequestWithBearerAuth(token).
+		SetBody(mapper).
+		Post(client.getAdminRealmURL(realm, "clients", clientID, "protocol-mappers", "models"))
+
+	return checkForError(resp, err)
+}
+
+// DeleteClientProtocolMapper deletes a protocol mapper in client scope
+func (client *gocloak) DeleteClientProtocolMapper(token, realm, clientID, mapperID string) error {
+	resp, err := client.getRequestWithBearerAuth(token).
+		Delete(client.getAdminRealmURL(realm, "clients", clientID, "protocol-mappers", "models", mapperID))
+
+	return checkForError(resp, err)
+}
+
 // GetKeyStoreConfig get keystoreconfig of the realm
 func (client *gocloak) GetKeyStoreConfig(token string, realm string) (*KeyStoreConfig, error) {
 	var result KeyStoreConfig
diff --git a/gocloak.go b/gocloak.go
index 506968e..51c2f2e 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -125,6 +125,10 @@ type GoCloak interface {
 	GetClientOfflineSessions(token, realm, clientID string) ([]*UserSessionRepresentation, error)
 	// GetClientUserSessions returns user sessions associated with the client
 	GetClientUserSessions(token, realm, clientID string) ([]*UserSessionRepresentation, error)
+	// CreateClientProtocolMapper creates a protocol mapper in client scope
+	CreateClientProtocolMapper(token, realm, clientID string, mapper ProtocolMapperRepresentation) error
+	// DeleteClientProtocolMapper deletes a protocol mapper in client scope
+	DeleteClientProtocolMapper(token, realm, clientID, mapperID string) error
 
 	// UserAttributeContains checks if the given attribute has the given value
 	UserAttributeContains(attributes map[string][]string, attribute string, value string) bool


Test patch:
diff --git a/client_test.go b/client_test.go
index e377487..85f749c 100644
--- a/client_test.go
+++ b/client_test.go
@@ -1818,6 +1818,38 @@ func TestGocloak_GetClientUserSessions(t *testing.T) {
 	FailIf(t, len(sessions) == 0, "GetClientUserSessions returned an empty list")
 }
 
+func TestGocloak_CreateDeleteClientProtocolMapper(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	testClient := GetClientByClientID(t, client, cfg.GoCloak.ClientID)
+	token := GetAdminToken(t, client)
+	id := "50d69716-86a4-41a7-93bd-f9d31f408ddb"
+	err := client.CreateClientProtocolMapper(token.AccessToken, cfg.GoCloak.Realm, cfg.GoCloak.ClientID, ProtocolMapperRepresentation{
+		ID:             id,
+		Name:           "test",
+		Protocol:       "openid-connect",
+		ProtocolMapper: "oidc-usermodel-attribute-mapper",
+		Config: map[string]string{
+			"access.token.claim":   "true",
+			"aggregate.attrs":      "",
+			"claim.name":           "test",
+			"id.token.claim":       "true",
+			"jsonType.label":       "String",
+			"multivalued":          "",
+			"user.attribute":       "test",
+			"userinfo.token.claim": "true",
+		},
+	})
+	FailIfErr(t, err, "CreateClientProtocolMapper failed")
+	testClientAfter := GetClientByClientID(t, client, cfg.GoCloak.ClientID)
+	FailIf(t, len(testClient.ProtocolMappers) >= len(testClientAfter.ProtocolMappers), "protocol mapper has not been created")
+	err = client.DeleteClientProtocolMapper(token.AccessToken, cfg.GoCloak.Realm, cfg.GoCloak.ClientID, id)
+	FailIfErr(t, err, "DeleteClientProtocolMapper failed")
+	testClientAgain := GetClientByClientID(t, client, cfg.GoCloak.ClientID)
+	FailIf(t, len(testClient.ProtocolMappers) != len(testClientAgain.ProtocolMappers), "protocol mapper has not been deleted")
+}
+
 func TestGocloak_GetClientOfflineSessions(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)