Repository: Nerzal/gocloak
Pull request #129 (2020-01-08 21:44:59)

Adding methods to lookup client roles




Patch:
diff --git a/README.md b/README.md
index 1c3766f..5a7d068 100644
--- a/README.md
+++ b/README.md
@@ -179,6 +179,10 @@ type GoCloak interface {
 
 	AddClientRoleToGroup(token string, realm string, clientID string, groupID string, roles []Role) error
 	DeleteClientRoleFromGroup(token string, realm string, clientID string, groupID string, roles []Role) error
+	GetClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error)
+	GetClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error)
+	GetCompositeClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error)
+	GetCompositeClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error)
 
 	// *** Realm ***
 
diff --git a/client.go b/client.go
index 3e425d3..411169a 100644
--- a/client.go
+++ b/client.go
@@ -871,6 +871,62 @@ func (client *gocloak) GetClientRoles(token string, realm string, clientID strin
 	return result, nil
 }
 
+// GetRealmRolesByUserID returns all client roles assigned to the given user
+func (client *gocloak) GetClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error) {
+	var result []*Role
+	resp, err := client.getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", clientID))
+
+	if err = checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+// GetClientRolesByGroupID returns all client roles assigned to the given group
+func (client *gocloak) GetClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error) {
+	var result []*Role
+	resp, err := client.getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", clientID))
+
+	if err = checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+// GetCompositeClientRolesByUserID returns all client roles and composite roles assigned to the given user
+func (client *gocloak) GetCompositeClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error) {
+	var result []*Role
+	resp, err := client.getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", clientID, "composite"))
+
+	if err = checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+// GetCompositeClientRolesByGroupID returns all client roles and composite roles assigned to the given group
+func (client *gocloak) GetCompositeClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error) {
+	var result []*Role
+	resp, err := client.getRequestWithBearerAuth(token).
+		SetResult(&result).
+		Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", clientID, "composite"))
+
+	if err = checkForError(resp, err); err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
 // GetClientRole get a role for the given client in a realm by role name
 func (client *gocloak) GetClientRole(token string, realm string, clientID string, roleName string) (*Role, error) {
 	var result Role
diff --git a/gocloak.go b/gocloak.go
index ae6847c..37db00f 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -172,6 +172,14 @@ type GoCloak interface {
 	DeleteClientRoleFromGroup(token string, realm string, clientID string, groupID string, roles []Role) error
 	// GetClientRoles gets roles for the given client
 	GetClientRoles(accessToken string, realm string, clientID string) ([]*Role, error)
+	// GetRealmRolesByUserID returns all client roles assigned to the given user
+	GetClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error)
+	// GetClientRolesByGroupID returns all client roles assigned to the given group
+	GetClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error)
+	// GetCompositeClientRolesByUserID returns all client roles and composite roles assigned to the given user
+	GetCompositeClientRolesByUserID(token string, realm string, clientID string, userID string) ([]*Role, error)
+	// GetCompositeClientRolesByGroupID returns all client roles and composite roles assigned to the given group
+	GetCompositeClientRolesByGroupID(token string, realm string, clientID string, groupID string) ([]*Role, error)
 	// GetClientRole get a role for the given client in a realm by role name
 	GetClientRole(token string, realm string, clientID string, roleName string) (*Role, error)
 	// AddClientRoleComposite adds roles as composite


Test patch:
diff --git a/client_test.go b/client_test.go
index 0864bc8..49c05f0 100644
--- a/client_test.go
+++ b/client_test.go
@@ -2393,6 +2393,94 @@ func TestGocloak_AddClientRoleToUser_DeleteClientRoleFromUser(t *testing.T) {
 	assert.NoError(t, err, "DeleteClientRoleFromUser failed")
 }
 
+func TestGocloak_GetClientRolesByUserID(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	token := GetAdminToken(t, client)
+
+	tearDownUser, userID := CreateUser(t, client)
+	defer tearDownUser()
+	tearDownRole, roleName := CreateClientRole(t, client)
+	defer tearDownRole()
+	role, err := client.GetClientRole(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		roleName)
+	assert.NoError(t, err)
+
+	err = client.AddClientRoleToUser(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		userID,
+		[]Role{
+			*role,
+		})
+	assert.NoError(t, err)
+
+	roles, err := client.GetClientRolesByUserID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		userID)
+	assert.NoError(t, err)
+	t.Logf("User roles: %+v", roles)
+	var found bool
+	for _, r := range roles {
+		if r.Name == nil {
+			continue
+		}
+		if *(r.Name) == *(role.Name) {
+			found = true
+			break
+		}
+	}
+	assert.True(t, found, "The role has not been found in the assigned roles. Role: %+v", *role)
+
+	roles, err = client.GetCompositeClientRolesByUserID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		userID)
+	assert.NoError(t, err)
+	t.Logf("User roles: %+v", roles)
+	for _, r := range roles {
+		if r.Name == nil {
+			continue
+		}
+		if *(r.Name) == *(role.Name) {
+			return
+		}
+	}
+	assert.Fail(t, "The role has not been found in the assigned composite roles. Role: %+v", *role)
+}
+
+func TestGocloak_GetClientRolesByGroupID(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	token := GetAdminToken(t, client)
+
+	tearDown, groupID := CreateGroup(t, client)
+	defer tearDown()
+
+	_, err := client.GetClientRolesByGroupID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		groupID)
+	assert.NoError(t, err, "GetClientRolesByGroupID failed")
+
+	_, err = client.GetCompositeClientRolesByGroupID(
+		token.AccessToken,
+		cfg.GoCloak.Realm,
+		gocloakClientID,
+		groupID)
+	assert.NoError(t, err, "GetCompositeClientRolesByGroupID failed")
+}
+
 func TestGocloak_AddClientRoleToGroup_DeleteClientRoleFromGroup(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)