diff --git a/tests/conftest.py b/tests/conftest.py index 8c43c77..af1f9af 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ import ipaddress import os import uuid from datetime import datetime, timedelta -from typing import Tuple +from typing import Generator, Tuple import freezegun import pytest @@ -337,7 +337,69 @@ def oid_with_credentials_authz(env: KeycloakTestEnv, realm: str, admin: Keycloak @pytest.fixture -def realm(admin: KeycloakAdmin) -> str: +def oid_with_credentials_device(env: KeycloakTestEnv, realm: str, admin: KeycloakAdmin): + """Fixture for an initialized KeycloakOpenID class and a random user credentials. + + :param env: Keycloak test environment + :type env: KeycloakTestEnv + :param realm: Keycloak realm + :type realm: str + :param admin: Keycloak admin + :type admin: KeycloakAdmin + :yields: Keycloak OpenID client with user credentials + :rtype: Tuple[KeycloakOpenID, str, str] + """ + # Set the realm + admin.change_current_realm(realm) + # Create client + client = str(uuid.uuid4()) + secret = str(uuid.uuid4()) + client_id = admin.create_client( + payload={ + "name": client, + "clientId": client, + "enabled": True, + "publicClient": False, + "protocol": "openid-connect", + "secret": secret, + "clientAuthenticatorType": "client-secret", + "attributes": {"oauth2.device.authorization.grant.enabled": True}, + } + ) + # Create user + username = str(uuid.uuid4()) + password = str(uuid.uuid4()) + user_id = admin.create_user( + payload={ + "username": username, + "email": f"{username}@test.test", + "enabled": True, + "firstName": "first", + "lastName": "last", + "emailVerified": True, + "requiredActions": [], + "credentials": [{"type": "password", "value": password, "temporary": False}], + } + ) + + yield ( + KeycloakOpenID( + server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}", + realm_name=realm, + client_id=client, + client_secret_key=secret, + ), + username, + password, + ) + + # Cleanup + admin.delete_client(client_id=client_id) + admin.delete_user(user_id=user_id) + + +@pytest.fixture +def realm(admin: KeycloakAdmin) -> Generator[str, None, None]: """Fixture for a new random realm. :param admin: Keycloak admin @@ -352,7 +414,7 @@ def realm(admin: KeycloakAdmin) -> str: @pytest.fixture -def user(admin: KeycloakAdmin, realm: str) -> str: +def user(admin: KeycloakAdmin, realm: str) -> Generator[str, None, None]: """Fixture for a new random user. :param admin: Keycloak admin @@ -370,7 +432,7 @@ def user(admin: KeycloakAdmin, realm: str) -> str: @pytest.fixture -def group(admin: KeycloakAdmin, realm: str) -> str: +def group(admin: KeycloakAdmin, realm: str) -> Generator[str, None, None]: """Fixture for a new random group. :param admin: Keycloak admin @@ -388,7 +450,7 @@ def group(admin: KeycloakAdmin, realm: str) -> str: @pytest.fixture -def client(admin: KeycloakAdmin, realm: str) -> str: +def client(admin: KeycloakAdmin, realm: str) -> Generator[str, None, None]: """Fixture for a new random client. :param admin: Keycloak admin @@ -406,7 +468,7 @@ def client(admin: KeycloakAdmin, realm: str) -> str: @pytest.fixture -def client_role(admin: KeycloakAdmin, realm: str, client: str) -> str: +def client_role(admin: KeycloakAdmin, realm: str, client: str) -> Generator[str, None, None]: """Fixture for a new random client role. :param admin: Keycloak admin @@ -426,7 +488,9 @@ def client_role(admin: KeycloakAdmin, realm: str, client: str) -> str: @pytest.fixture -def composite_client_role(admin: KeycloakAdmin, realm: str, client: str, client_role: str) -> str: +def composite_client_role( + admin: KeycloakAdmin, realm: str, client: str, client_role: str +) -> Generator[str, None, None]: """Fixture for a new random composite client role. :param admin: Keycloak admin diff --git a/tests/test_keycloak_admin.py b/tests/test_keycloak_admin.py index 7090253..6f7c3c3 100644 --- a/tests/test_keycloak_admin.py +++ b/tests/test_keycloak_admin.py @@ -335,6 +335,16 @@ def test_users(admin: KeycloakAdmin, realm: str): admin.update_user(user_id=user_id, payload={"wrong": "payload"}) assert err.match('400: b\'{"error":"Unrecognized field') + # Test disable user + res = admin.disable_user(user_id=user_id) + assert res == {}, res + assert not admin.get_user(user_id=user_id)["enabled"] + + # Test enable user + res = admin.enable_user(user_id=user_id) + assert res == {}, res + assert admin.get_user(user_id=user_id)["enabled"] + # Test get users again users = admin.get_users() usernames = [x["username"] for x in users] @@ -388,6 +398,43 @@ def test_users(admin: KeycloakAdmin, realm: str): assert err.match(USER_NOT_FOUND_REGEX) +def test_enable_disable_all_users(admin: KeycloakAdmin, realm: str): + """Test enable and disable all users. + + :param admin: Keycloak Admin client + :type admin: KeycloakAdmin + :param realm: Keycloak realm + :type realm: str + """ + admin.change_current_realm(realm) + + user_id_1 = admin.create_user( + payload={"username": "test", "email": "test@test.test", "enabled": True} + ) + user_id_2 = admin.create_user( + payload={"username": "test2", "email": "test2@test.test", "enabled": True} + ) + user_id_3 = admin.create_user( + payload={"username": "test3", "email": "test3@test.test", "enabled": True} + ) + + assert admin.get_user(user_id_1)["enabled"] + assert admin.get_user(user_id_2)["enabled"] + assert admin.get_user(user_id_3)["enabled"] + + admin.disable_all_users() + + assert not admin.get_user(user_id_1)["enabled"] + assert not admin.get_user(user_id_2)["enabled"] + assert not admin.get_user(user_id_3)["enabled"] + + admin.enable_all_users() + + assert admin.get_user(user_id_1)["enabled"] + assert admin.get_user(user_id_2)["enabled"] + assert admin.get_user(user_id_3)["enabled"] + + def test_users_roles(admin: KeycloakAdmin, realm: str): """Test users roles. @@ -1354,6 +1401,10 @@ def test_realm_roles(admin: KeycloakAdmin, realm: str): admin.get_realm_role_groups(role_name="non-existent-role") assert err.match(COULD_NOT_FIND_ROLE_REGEX) + # Test with query params + res = admin.get_realm_role_groups(role_name="test-realm-role-update", query={"max": 1}) + assert len(res) == 1 + # Test delete realm role res = admin.delete_realm_role(role_name=composite_role) assert res == dict(), res diff --git a/tests/test_keycloak_openid.py b/tests/test_keycloak_openid.py index d57e6ca..a41f454 100644 --- a/tests/test_keycloak_openid.py +++ b/tests/test_keycloak_openid.py @@ -479,3 +479,23 @@ def test_has_uma_access( == "AuthStatus(is_authorized=False, is_logged_in=False, missing_permissions=" + "{'Default Resource'})" ) + + +def test_device(oid_with_credentials_device: Tuple[KeycloakOpenID, str, str]): + """Test device authorization flow. + + :param oid_with_credentials_device: Keycloak OpenID client with pre-configured user + credentials and device authorization flow enabled + :type oid_with_credentials_device: Tuple[KeycloakOpenID, str, str] + """ + oid, _, _ = oid_with_credentials_device + res = oid.device() + assert res == { + "device_code": mock.ANY, + "user_code": mock.ANY, + "verification_uri": f"http://localhost:8081/realms/{oid.realm_name}/device", + "verification_uri_complete": f"http://localhost:8081/realms/{oid.realm_name}/" + + f"device?user_code={res['user_code']}", + "expires_in": 600, + "interval": 5, + }