Browse Source

Merge branch 'master' into add_more_requests

pull/632/head
Aleksey Kuznetsov 2 days ago
parent
commit
06ae6cc2ec
Failed to extract signature
  1. 6
      CHANGELOG.md
  2. 6
      docs/source/conf.py
  3. 76
      src/keycloak/keycloak_admin.py
  4. 1
      src/keycloak/urls_patterns.py
  5. 45
      tests/test_keycloak_admin.py

6
CHANGELOG.md

@ -1,3 +1,9 @@
## v5.2.0 (2025-01-30)
### Feat
- Add functions to get/update realm users profile (#634)
## v5.1.2 (2025-01-26)
### Fix

6
docs/source/conf.py

@ -22,6 +22,8 @@
"""Sphinx documentation configuration."""
import os
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@ -68,9 +70,9 @@ author = "Marcos Pereira"
# built documents.
#
# The short X.Y version.
version = "0.0.0"
version = os.getenv("READTHEDOCS_VERSION", "latest")
# The full version, including alpha/beta/rc tags.
release = "0.0.0"
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

76
src/keycloak/keycloak_admin.py

@ -2297,6 +2297,24 @@ class KeycloakAdmin:
)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK])
def get_realm_users_profile(self) -> dict:
"""
Get list of attributes and group for given realm.
Related documentation:
https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#_get_adminrealmsrealmusersprofile
Return https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#UPConfig
:returns: UPConfig
"""
params_path = {"realm-name": self.connection.realm_name}
data_raw = self.connection.raw_get(
urls_patterns.URL_ADMIN_REALM_USER_PROFILE.format(**params_path),
)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK])
def get_realm_roles(self, brief_representation: bool = True, search_text: str = "") -> list:
"""
Get all roles for the realm or client.
@ -2911,6 +2929,26 @@ class KeycloakAdmin:
expected_codes=[HTTP_NO_CONTENT],
)
def update_realm_users_profile(self, payload: dict) -> dict:
"""
Update realm users profile for the current realm.
:param up_config: List of attributes, groups, unmamagedAttributePolicy
Related documentation:
https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#UPConfig
"""
params_path = {"realm-name": self.connection.realm_name}
data_raw = self.connection.raw_put(
urls_patterns.URL_ADMIN_REALM_USER_PROFILE.format(**params_path),
data=json.dumps(payload),
)
return raise_error_from_response(
data_raw,
KeycloakPutError,
expected_codes=[HTTP_OK],
)
def delete_realm_role(self, role_name: str) -> bytes:
"""
Delete a role for the realm by name.
@ -5577,6 +5615,26 @@ class KeycloakAdmin:
expected_codes=[HTTP_NO_CONTENT],
)
async def a_update_realm_users_profile(self, payload: dict) -> dict:
"""
Update realm users profile for the current realm.
:param up_config: List of attributes, groups, unmamagedAttributePolicy
Related documentation:
https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#UPConfig
"""
params_path = {"realm-name": self.connection.realm_name}
data_raw = await self.connection.a_raw_put(
urls_patterns.URL_ADMIN_REALM_USER_PROFILE.format(**params_path),
data=json.dumps(payload),
)
return raise_error_from_response(
data_raw,
KeycloakPutError,
expected_codes=[HTTP_OK],
)
async def a_delete_realm(self, realm_name: str) -> bytes:
"""
Delete a realm asynchronously.
@ -7478,6 +7536,24 @@ class KeycloakAdmin:
)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK])
async def a_get_realm_users_profile(self) -> dict:
"""
Get list of attributes and group for given realm.
Related documentation:
https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#_get_adminrealmsrealmusersprofile
Return https://www.keycloak.org/docs-api/26.0.0/rest-api/index.html#UPConfig
:returns: UPConfig
"""
params_path = {"realm-name": self.connection.realm_name}
data_raw = await self.connection.a_raw_get(
urls_patterns.URL_ADMIN_REALM_USER_PROFILE.format(**params_path),
)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[HTTP_OK])
async def a_get_realm_roles(
self,
brief_representation: bool = True,

1
src/keycloak/urls_patterns.py

@ -153,6 +153,7 @@ URL_ADMIN_CLIENT_SCOPE_ROLE_MAPPINGS_CLIENT = (
URL_ADMIN_REALM_ROLES = "admin/realms/{realm-name}/roles"
URL_ADMIN_REALM_ROLES_MEMBERS = URL_ADMIN_REALM_ROLES + "/{role-name}/users"
URL_ADMIN_REALM_ROLES_GROUPS = URL_ADMIN_REALM_ROLES + "/{role-name}/groups"
URL_ADMIN_REALM_USER_PROFILE = "admin/realms/{realm-name}/users/profile"
URL_ADMIN_REALMS = "admin/realms"
URL_ADMIN_REALM = "admin/realms/{realm-name}"
URL_ADMIN_IDPS = "admin/realms/{realm-name}/identity-provider/instances"

45
tests/test_keycloak_admin.py

@ -204,6 +204,28 @@ def test_realms(admin: KeycloakAdmin) -> None:
assert "master" in realm_names, realm_names
assert "test" in realm_names, realm_names
if os.environ["KEYCLOAK_DOCKER_IMAGE_TAG"] == "latest" or Version(
os.environ["KEYCLOAK_DOCKER_IMAGE_TAG"],
) >= Version("24"):
# Get users profile, add an attribute
user_profile = admin.get_realm_users_profile()
assert "attributes" in user_profile
new_attribute = {
"name": "surname",
"displayName": "",
"validations": {},
"annotations": {},
"permissions": {"view": [], "edit": ["admin"]},
"multivalued": False,
}
user_profile["attributes"].append(new_attribute)
res = admin.update_realm_users_profile(user_profile)
# Check for new attribute in result
assert "surname" in [x["name"] for x in res["attributes"]]
# Delete the realm
res = admin.delete_realm(realm_name="test")
assert res == {}, res
@ -3427,6 +3449,29 @@ async def test_a_realms(admin: KeycloakAdmin) -> None:
assert "master" in realm_names, realm_names
assert "test" in realm_names, realm_names
# Get users profile, add an attribute and check
user_profile = await admin.a_get_realm_users_profile()
assert "attributes" in user_profile
if os.environ["KEYCLOAK_DOCKER_IMAGE_TAG"] == "latest" or Version(
os.environ["KEYCLOAK_DOCKER_IMAGE_TAG"],
) >= Version("24"):
new_attribute = {
"name": "nickname",
"displayName": "",
"validations": {},
"annotations": {},
"permissions": {"view": [], "edit": ["admin"]},
"multivalued": False,
}
user_profile["attributes"].append(new_attribute)
res = await admin.a_update_realm_users_profile(user_profile)
# Check for new attribute in result
assert "nickname" in [x["name"] for x in res["attributes"]]
# Delete the realm
res = await admin.a_delete_realm(realm_name="test")
assert res == {}, res

Loading…
Cancel
Save