From 52242f554e31f6f73953a1431df7d7dd88b957f1 Mon Sep 17 00:00:00 2001 From: Greg <78878994+gregriff@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:15:53 -0400 Subject: [PATCH] feat: implement endpoints returning the number of members in an organization (#665) --- src/keycloak/keycloak_admin.py | 36 ++++++++++++++++++++++++++++++++++ src/keycloak/urls_patterns.py | 1 + tests/test_keycloak_admin.py | 8 ++++++++ 3 files changed, 45 insertions(+) diff --git a/src/keycloak/keycloak_admin.py b/src/keycloak/keycloak_admin.py index 167064f..fab1a71 100644 --- a/src/keycloak/keycloak_admin.py +++ b/src/keycloak/keycloak_admin.py @@ -903,6 +903,42 @@ class KeycloakAdmin: return await self.a___fetch_all(url, query) + def get_organization_members_count(self, organization_id: str) -> int: + """ + Get the number of members in the organization. + + :param organization_id: ID of the organization + :type organization_id: str + :return: Number of members in the organization + :rtype: int + """ + params_path = { + "realm-name": self.connection.realm_name, + "organization_id": organization_id, + } + data_raw = self.connection.raw_get( + urls_patterns.URL_ADMIN_ORGANIZATION_MEMBERS_COUNT.format(**params_path) + ) + return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK]) + + async def a_get_organization_members_count(self, organization_id: str) -> int: + """ + Get the number of members in the organization asynchronously. + + :param organization_id: ID of the organization + :type organization_id: str + :return: Number of members in the organization + :rtype: int + """ + params_path = { + "realm-name": self.connection.realm_name, + "organization_id": organization_id, + } + data_raw = await self.connection.a_raw_get( + urls_patterns.URL_ADMIN_ORGANIZATION_MEMBERS_COUNT.format(**params_path) + ) + return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK]) + def organization_user_add(self, user_id: str, organization_id: str) -> dict | bytes: """ Add a user to an organization. diff --git a/src/keycloak/urls_patterns.py b/src/keycloak/urls_patterns.py index aa36810..daf1889 100644 --- a/src/keycloak/urls_patterns.py +++ b/src/keycloak/urls_patterns.py @@ -244,6 +244,7 @@ URL_ADMIN_FLOWS_EXECUTION_CONFIG = URL_ADMIN_FLOWS_EXECUTION + "/config" URL_ADMIN_ORGANIZATIONS = URL_ADMIN_REALM + "/organizations" URL_ADMIN_ORGANIZATION_BY_ID = URL_ADMIN_ORGANIZATIONS + "/{organization_id}" URL_ADMIN_ORGANIZATION_MEMBERS = URL_ADMIN_ORGANIZATION_BY_ID + "/members" +URL_ADMIN_ORGANIZATION_MEMBERS_COUNT = URL_ADMIN_ORGANIZATION_MEMBERS + "/count" URL_ADMIN_ORGANIZATION_DEL_MEMBER_BY_ID = URL_ADMIN_ORGANIZATION_MEMBERS + "/{user_id}" URL_ADMIN_ORGANIZATION_IDPS = URL_ADMIN_ORGANIZATION_BY_ID + "/identity-providers" URL_ADMIN_ORGANIZATION_IDP_BY_ALIAS = URL_ADMIN_ORGANIZATION_IDPS + "/{idp_alias}" diff --git a/tests/test_keycloak_admin.py b/tests/test_keycloak_admin.py index 4bad412..5f52f72 100644 --- a/tests/test_keycloak_admin.py +++ b/tests/test_keycloak_admin.py @@ -376,6 +376,8 @@ def test_organizations(admin: KeycloakAdmin, realm: str) -> None: users = admin.get_organization_members(org_id) assert len(users) == 1, users assert users[0]["id"] == user_id, users[0]["id"] + num_users = admin.get_organization_members_count(org_id) + assert num_users == 1, num_users user_orgs = admin.get_user_organizations(user_id) assert len(user_orgs) == 1, user_orgs @@ -384,6 +386,8 @@ def test_organizations(admin: KeycloakAdmin, realm: str) -> None: admin.organization_user_remove(user_id, org_id) users = admin.get_organization_members(org_id) assert len(users) == 0, users + num_users = admin.get_organization_members_count(org_id) + assert num_users == 0, num_users for i in range(admin.PAGE_SIZE + 50): user_id = admin.create_user( @@ -3885,6 +3889,8 @@ async def a_test_organizations(admin: KeycloakAdmin, realm: str) -> None: users = await admin.a_get_organization_members(org_id) assert len(users) == 1, users assert users[0]["id"] == user_id, users[0]["id"] + num_users = await admin.a_get_organization_members_count(org_id) + assert num_users == 1, num_users user_orgs = await admin.a_get_user_organizations(user_id) assert len(user_orgs) == 1, user_orgs @@ -3893,6 +3899,8 @@ async def a_test_organizations(admin: KeycloakAdmin, realm: str) -> None: await admin.a_organization_user_remove(user_id, org_id) users = await admin.a_get_organization_members(org_id) assert len(users) == 0, users + num_users = await admin.a_get_organization_members_count(org_id) + assert num_users == 0, num_users for i in range(admin.PAGE_SIZE + 50): user_id = await admin.a_create_user(