Browse Source

Merge pull request #401 from marcospereirampj/feat/default_realm_roles

feat: added default realm roles handlers
pull/403/head v2.9.0
Richard Nemeth 2 years ago
committed by GitHub
parent
commit
b3d1a6e088
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 62
      src/keycloak/keycloak_admin.py
  2. 6
      src/keycloak/urls_patterns.py
  3. 73
      tests/test_keycloak_admin.py

62
src/keycloak/keycloak_admin.py

@ -988,7 +988,7 @@ class KeycloakAdmin:
data_raw = self.raw_put( data_raw = self.raw_put(
urls_patterns.URL_ADMIN_SEND_UPDATE_ACCOUNT.format(**params_path), urls_patterns.URL_ADMIN_SEND_UPDATE_ACCOUNT.format(**params_path),
data=json.dumps(payload), data=json.dumps(payload),
**params_query
**params_query,
) )
return raise_error_from_response(data_raw, KeycloakPutError) return raise_error_from_response(data_raw, KeycloakPutError)
@ -1012,7 +1012,7 @@ class KeycloakAdmin:
data_raw = self.raw_put( data_raw = self.raw_put(
urls_patterns.URL_ADMIN_SEND_VERIFY_EMAIL.format(**params_path), urls_patterns.URL_ADMIN_SEND_VERIFY_EMAIL.format(**params_path),
data={}, data={},
**params_query
**params_query,
) )
return raise_error_from_response(data_raw, KeycloakPutError) return raise_error_from_response(data_raw, KeycloakPutError)
@ -1657,6 +1657,62 @@ class KeycloakAdmin:
urls_patterns.URL_ADMIN_REALM_ROLES_MEMBERS.format(**params_path), query urls_patterns.URL_ADMIN_REALM_ROLES_MEMBERS.format(**params_path), query
) )
def get_default_realm_role_id(self):
"""Get the ID of the default realm role.
:return: Realm role ID
:rtype: str
"""
all_realm_roles = self.get_realm_roles()
default_realm_roles = [
realm_role
for realm_role in all_realm_roles
if realm_role["name"] == f"default-roles-{self.realm_name}"
]
return default_realm_roles[0]["id"]
def get_realm_default_roles(self):
"""Get all the default realm roles.
:return: Keycloak Server Response (UserRepresentation)
:rtype: list
"""
params_path = {"realm-name": self.realm_name, "role-id": self.get_default_realm_role_id()}
data_raw = self.raw_get(
urls_patterns.URL_ADMIN_REALM_ROLE_COMPOSITES_REALM.format(**params_path)
)
return raise_error_from_response(data_raw, KeycloakGetError)
def remove_realm_default_roles(self, payload):
"""Remove a set of default realm roles.
:param payload: List of RoleRepresentations
:type payload: list
:return: Keycloak Server Response
:rtype: dict
"""
params_path = {"realm-name": self.realm_name, "role-id": self.get_default_realm_role_id()}
data_raw = self.raw_delete(
urls_patterns.URL_ADMIN_REALM_ROLE_COMPOSITES.format(**params_path),
data=json.dumps(payload),
)
return raise_error_from_response(data_raw, KeycloakDeleteError)
def add_realm_default_roles(self, payload):
"""Add a set of default realm roles.
:param payload: List of RoleRepresentations
:type payload: list
:return: Keycloak Server Response
:rtype: dict
"""
params_path = {"realm-name": self.realm_name, "role-id": self.get_default_realm_role_id()}
data_raw = self.raw_post(
urls_patterns.URL_ADMIN_REALM_ROLE_COMPOSITES.format(**params_path),
data=json.dumps(payload),
)
return raise_error_from_response(data_raw, KeycloakPostError)
def get_client_roles(self, client_id, brief_representation=True): def get_client_roles(self, client_id, brief_representation=True):
"""Get all roles for the client. """Get all roles for the client.
@ -2664,7 +2720,7 @@ class KeycloakAdmin:
data_raw = self.raw_post( data_raw = self.raw_post(
urls_patterns.URL_ADMIN_USER_STORAGE.format(**params_path), urls_patterns.URL_ADMIN_USER_STORAGE.format(**params_path),
data=json.dumps(data), data=json.dumps(data),
**params_query
**params_query,
) )
return raise_error_from_response(data_raw, KeycloakPostError) return raise_error_from_response(data_raw, KeycloakPostError)

6
src/keycloak/urls_patterns.py

@ -189,9 +189,9 @@ URL_ADMIN_EVENTS_CONFIG = URL_ADMIN_EVENTS + "/config"
URL_ADMIN_CLIENT_SESSION_STATS = "admin/realms/{realm-name}/client-session-stats" URL_ADMIN_CLIENT_SESSION_STATS = "admin/realms/{realm-name}/client-session-stats"
URL_ADMIN_GROUPS_CLIENT_ROLES_COMPOSITE = URL_ADMIN_GROUPS_CLIENT_ROLES + "/composite" URL_ADMIN_GROUPS_CLIENT_ROLES_COMPOSITE = URL_ADMIN_GROUPS_CLIENT_ROLES + "/composite"
URL_ADMIN_CLIENT_ROLE_CHILDREN = (
"admin/realms/{realm-name}/roles-by-id/{role-id}/composites/clients/{client-id}"
)
URL_ADMIN_REALM_ROLE_COMPOSITES = "admin/realms/{realm-name}/roles-by-id/{role-id}/composites"
URL_ADMIN_REALM_ROLE_COMPOSITES_REALM = URL_ADMIN_REALM_ROLE_COMPOSITES + "/realm"
URL_ADMIN_CLIENT_ROLE_CHILDREN = URL_ADMIN_REALM_ROLE_COMPOSITES + "/clients/{client-id}"
URL_ADMIN_CLIENT_CERT_UPLOAD = URL_ADMIN_CLIENT_CERTS + "/upload-certificate" URL_ADMIN_CLIENT_CERT_UPLOAD = URL_ADMIN_CLIENT_CERTS + "/upload-certificate"
URL_ADMIN_REQUIRED_ACTIONS = URL_ADMIN_REALM + "/authentication/required-actions" URL_ADMIN_REQUIRED_ACTIONS = URL_ADMIN_REALM + "/authentication/required-actions"
URL_ADMIN_REQUIRED_ACTIONS_ALIAS = URL_ADMIN_REQUIRED_ACTIONS + "/{action-alias}" URL_ADMIN_REQUIRED_ACTIONS_ALIAS = URL_ADMIN_REQUIRED_ACTIONS + "/{action-alias}"

73
tests/test_keycloak_admin.py

@ -2421,3 +2421,76 @@ def test_clear_bruteforce_attempts_for_all_users(
res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": False}) res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": False})
res = admin.get_realm(realm_name=realm) res = admin.get_realm(realm_name=realm)
assert res["bruteForceProtected"] is False assert res["bruteForceProtected"] is False
def test_default_realm_role_present(realm: str, admin: KeycloakAdmin) -> None:
"""Test that the default realm role is present in a brand new realm.
:param realm: Realm name
:type realm: str
:param admin: Keycloak admin
:type admin: KeycloakAdmin
"""
admin.realm_name = realm
assert f"default-roles-{realm}" in [x["name"] for x in admin.get_realm_roles()]
assert (
len([x["name"] for x in admin.get_realm_roles() if x["name"] == f"default-roles-{realm}"])
== 1
)
def test_get_default_realm_role_id(realm: str, admin: KeycloakAdmin) -> None:
"""Test getter for the ID of the default realm role.
:param realm: Realm name
:type realm: str
:param admin: Keycloak admin
:type admin: KeycloakAdmin
"""
admin.realm_name = realm
assert (
admin.get_default_realm_role_id()
== [x["id"] for x in admin.get_realm_roles() if x["name"] == f"default-roles-{realm}"][0]
)
def test_realm_default_roles(admin: KeycloakAdmin, realm: str) -> None:
"""Test getting, adding and deleting default realm roles.
:param realm: Realm name
:type realm: str
:param admin: Keycloak admin
:type admin: KeycloakAdmin
"""
admin.realm_name = realm
# Test listing all default realm roles
roles = admin.get_realm_default_roles()
assert len(roles) == 2
assert {x["name"] for x in roles} == {"offline_access", "uma_authorization"}
with pytest.raises(KeycloakGetError) as err:
admin.realm_name = "doesnotexist"
admin.get_realm_default_roles()
assert err.match('404: b\'{"error":"Realm not found."}\'')
admin.realm_name = realm
# Test removing a default realm role
res = admin.remove_realm_default_roles(payload=[roles[0]])
assert res == {}
assert roles[0] not in admin.get_realm_default_roles()
assert len(admin.get_realm_default_roles()) == 1
with pytest.raises(KeycloakDeleteError) as err:
admin.remove_realm_default_roles(payload=[{"id": "bad id"}])
assert err.match('404: b\'{"error":"Could not find composite role"}\'')
# Test adding a default realm role
res = admin.add_realm_default_roles(payload=[roles[0]])
assert res == {}
assert roles[0] in admin.get_realm_default_roles()
assert len(admin.get_realm_default_roles()) == 2
with pytest.raises(KeycloakPostError) as err:
admin.add_realm_default_roles(payload=[{"id": "bad id"}])
assert err.match('404: b\'{"error":"Could not find composite role"}\'')
Loading…
Cancel
Save