diff --git a/README.md b/README.md index 79dc8439..df0d7c87 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ type GoCloak interface { GetUserGroups(accessToken string, realm string, userID string) ([]*UserGroup, error) GetComponents(accessToken string, realm string) ([]*Component, error) GetGroups(accessToken string, realm string, params GetGroupsParams) ([]*Group, error) + GetGroupsCount(token string, realm string) (int, error) GetGroup(accessToken string, realm, groupID string) (*Group, error) GetDefaultGroups(accessToken string, realm string) ([]*Group, error) AddDefaultGroup(accessToken string, realm string, groupID string) error diff --git a/client.go b/client.go index 067711c0..df1b0254 100644 --- a/client.go +++ b/client.go @@ -30,11 +30,13 @@ const ( urlSeparator string = "/" ) -var authAdminRealms = makeURL("auth", "admin", "realms") -var authRealms = makeURL("auth", "realms") -var tokenEndpoint = makeURL("protocol", "openid-connect", "token") -var logoutEndpoint = makeURL("protocol", "openid-connect", "logout") -var openIDConnect = makeURL("protocol", "openid-connect") +var ( + authAdminRealms = makeURL("auth", "admin", "realms") + authRealms = makeURL("auth", "realms") + tokenEndpoint = makeURL("protocol", "openid-connect", "token") + logoutEndpoint = makeURL("protocol", "openid-connect", "logout") + openIDConnect = makeURL("protocol", "openid-connect") +) func makeURL(path ...string) string { return strings.Join(path, urlSeparator) @@ -146,7 +148,7 @@ func (client *gocloak) getAdminRealmURL(realm string, path ...string) string { } func (client *gocloak) GetServerInfo(accessToken string) (*ServerInfoRepesentation, error) { - var errMessage = "could not get server info" + errMessage := "could not get server info" var result ServerInfoRepesentation resp, err := client.getRequestWithBearerAuth(accessToken). @@ -1015,6 +1017,22 @@ func (client *gocloak) GetGroups(token string, realm string, params GetGroupsPar return result, nil } +// GetGroupsCount gets the groups count in the realm +func (client *gocloak) GetGroupsCount(token string, realm string) (int, error) { + const errMessage = "could not get groups count" + + var result GroupsCount + resp, err := client.getRequestWithBearerAuth(token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "groups", "count")) + + if err := checkForError(resp, err, errMessage); err != nil { + return -1, errors.Wrap(err, errMessage) + } + + return result.Count, nil +} + // GetGroupMembers get a list of users of group with id in realm func (client *gocloak) GetGroupMembers(token string, realm string, groupID string, params GetGroupsParams) ([]*User, error) { const errMessage = "could not get group members" diff --git a/client_test.go b/client_test.go index 999137f3..76ef8a55 100644 --- a/client_test.go +++ b/client_test.go @@ -1451,7 +1451,6 @@ func TestGocloak_ExecuteActionsEmail_UpdatePassword(t *testing.T) { token.AccessToken, cfg.GoCloak.Realm, params) - if err != nil { if err.Error() == "500 Internal Server Error: Failed to send execute actions email" { return @@ -1934,6 +1933,19 @@ func TestGocloak_GetUserCount(t *testing.T) { assert.NoError(t, err, "GetUserCount failed") } +func TestGocloak_GetGroupsCount(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + count, err := client.GetGroupsCount( + token.AccessToken, + cfg.GoCloak.Realm) + t.Logf("Groups in Realm: %d", count) + assert.NoError(t, err, "GetGroupsCount failed") +} + func TestGocloak_AddUserToGroup(t *testing.T) { t.Parallel() cfg := GetConfig(t) diff --git a/gocloak.go b/gocloak.go index 6a46eccc..36fd24be 100644 --- a/gocloak.go +++ b/gocloak.go @@ -115,6 +115,8 @@ type GoCloak interface { RemoveDefaultGroup(accessToken string, realm string, groupID string) error // GetGroups gets all groups of the given realm GetGroups(accessToken string, realm string, params GetGroupsParams) ([]*Group, error) + // GetGroupsCount gets groups count of the given realm + GetGroupsCount(token string, realm string) (int, error) // GetGroup gets the given group GetGroup(accessToken string, realm, groupID string) (*Group, error) // GetGroupMembers get a list of users of group with id in realm diff --git a/models.go b/models.go index e29ed968..33028150 100644 --- a/models.go +++ b/models.go @@ -241,6 +241,11 @@ type Group struct { RealmRoles []string `json:"realmRoles,omitempty"` } +// GroupsCount represents the groups count response from keycloak +type GroupsCount struct { + Count int `json:"count"` +} + // GetGroupsParams represents the optional parameters for getting groups type GetGroupsParams struct { First *int `json:"first,string,omitempty"` @@ -493,10 +498,10 @@ type GroupDefinition struct { // ResourceRepresentation is a representation of a Resource type ResourceRepresentation struct { - ID *string `json:"_id,omitempty"` //TODO: is marked "_optional" in template, input error or deliberate? + ID *string `json:"_id,omitempty"` // TODO: is marked "_optional" in template, input error or deliberate? Attributes map[string][]string `json:"attributes,omitempty"` DisplayName *string `json:"displayName,omitempty"` - IconURI *string `json:"icon_uri,omitempty"` //TODO: With "_" because that's how it's written down in the template + IconURI *string `json:"icon_uri,omitempty"` // TODO: With "_" because that's how it's written down in the template Name *string `json:"name,omitempty"` Owner *ResourceOwnerRepresentation `json:"owner"` OwnerManagedAccess *bool `json:"ownerManagedAccess"`