diff --git a/src/keycloak/authorization/role.py b/src/keycloak/authorization/role.py index 05da243..4ee6ec9 100644 --- a/src/keycloak/authorization/role.py +++ b/src/keycloak/authorization/role.py @@ -38,7 +38,6 @@ class Role: self.name = name self.required = required - @property def get_name(self): """Get name.""" return self.name diff --git a/src/keycloak/connection.py b/src/keycloak/connection.py index 361d95d..44978e5 100644 --- a/src/keycloak/connection.py +++ b/src/keycloak/connection.py @@ -25,7 +25,7 @@ try: from urllib.parse import urljoin -except ImportError: +except ImportError: # pragma: no cover from urlparse import urljoin import requests @@ -46,10 +46,10 @@ class ConnectionManager(object): def __init__(self, base_url, headers={}, timeout=60, verify=True, proxies=None): """Init method.""" - self._base_url = base_url - self._headers = headers - self._timeout = timeout - self._verify = verify + self.base_url = base_url + self.headers = headers + self.timeout = timeout + self.verify = verify self._s = requests.Session() self._s.auth = lambda x: x # don't let requests add auth headers diff --git a/src/keycloak/uma_permissions.py b/src/keycloak/uma_permissions.py index 1bf2136..94779f1 100644 --- a/src/keycloak/uma_permissions.py +++ b/src/keycloak/uma_permissions.py @@ -206,13 +206,9 @@ def build_permission_param(permissions): except AttributeError: pass - try: # treat as any other iterable of permissions - result = set() - for permission in permissions: - if not isinstance(permission, (str, UMAPermission)): - raise KeycloakPermissionFormatError("misbuilt permission {}".format(permissions)) - result.add(str(permission)) - return result - except TypeError: - pass - raise KeycloakPermissionFormatError("misbuilt permission {}".format(permissions)) + result = set() + for permission in permissions: + if not isinstance(permission, (str, UMAPermission)): + raise KeycloakPermissionFormatError("misbuilt permission {}".format(permissions)) + result.add(str(permission)) + return result diff --git a/tests/test_authorization.py b/tests/test_authorization.py new file mode 100644 index 0000000..a9ffc54 --- /dev/null +++ b/tests/test_authorization.py @@ -0,0 +1,42 @@ +"""Test authorization module.""" +import pytest + +from keycloak.authorization import Permission, Policy, Role +from keycloak.exceptions import KeycloakAuthorizationConfigError + + +def test_authorization_objects(): + """Test authorization objects.""" + # Test permission + p = Permission(name="test", type="test", logic="test", decision_strategy="test") + assert p.name == "test" + assert p.type == "test" + assert p.logic == "test" + assert p.decision_strategy == "test" + p.resources = ["test"] + assert p.resources == ["test"] + p.scopes = ["test"] + assert p.scopes == ["test"] + + # Test policy + p = Policy(name="test", type="test", logic="test", decision_strategy="test") + assert p.name == "test" + assert p.type == "test" + assert p.logic == "test" + assert p.decision_strategy == "test" + p.roles = ["test"] + assert p.roles == ["test"] + p.permissions = ["test"] + assert p.permissions == ["test"] + p.add_permission(permission="test2") + assert p.permissions == ["test", "test2"] + with pytest.raises(KeycloakAuthorizationConfigError): + p.add_role(role="test2") + + # Test role + r = Role(name="test") + assert r.name == "test" + assert not r.required + assert r.get_name() == "test" + assert r == r + assert r == "test" diff --git a/tests/test_connection.py b/tests/test_connection.py new file mode 100644 index 0000000..85730cd --- /dev/null +++ b/tests/test_connection.py @@ -0,0 +1,41 @@ +"""Connection test module.""" + +import pytest + +from keycloak.connection import ConnectionManager +from keycloak.exceptions import KeycloakConnectionError + + +def test_connection_proxy(): + """Test proxies of connection manager.""" + cm = ConnectionManager( + base_url="http://test.test", proxies={"http://test.test": "localhost:8080"} + ) + assert cm._s.proxies == {"http://test.test": "localhost:8080"} + + +def test_headers(): + """Test headers manipulation.""" + cm = ConnectionManager(base_url="http://test.test", headers={"H": "A"}) + assert cm.param_headers(key="H") == "A" + assert cm.param_headers(key="A") is None + cm.clean_headers() + assert cm.headers == dict() + cm.add_param_headers(key="H", value="B") + assert cm.exist_param_headers(key="H") + assert not cm.exist_param_headers(key="B") + cm.del_param_headers(key="H") + assert not cm.exist_param_headers(key="H") + + +def test_bad_connection(): + """Test bad connection.""" + cm = ConnectionManager(base_url="http://not.real.domain") + with pytest.raises(KeycloakConnectionError): + cm.raw_get(path="bad") + with pytest.raises(KeycloakConnectionError): + cm.raw_delete(path="bad") + with pytest.raises(KeycloakConnectionError): + cm.raw_post(path="bad", data={}) + with pytest.raises(KeycloakConnectionError): + cm.raw_put(path="bad", data={}) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py new file mode 100644 index 0000000..72e7161 --- /dev/null +++ b/tests/test_exceptions.py @@ -0,0 +1,20 @@ +"""Test the exceptions module.""" + +from unittest.mock import Mock + +import pytest + +from keycloak.exceptions import KeycloakOperationError, raise_error_from_response + + +def test_raise_error_from_response_from_dict(): + """Test raise error from response using a dictionary.""" + response = Mock() + response.json.return_value = {"key": "value"} + response.status_code = 408 + response.content = "Error" + + with pytest.raises(KeycloakOperationError): + raise_error_from_response( + response=response, error=dict(), expected_codes=[200], skip_exists=False + ) diff --git a/tests/test_uma_permissions.py b/tests/test_uma_permissions.py index 581faf4..8179ff9 100644 --- a/tests/test_uma_permissions.py +++ b/tests/test_uma_permissions.py @@ -22,7 +22,32 @@ import re import pytest from keycloak.exceptions import KeycloakPermissionFormatError, PermissionDefinitionError -from keycloak.uma_permissions import Resource, Scope, build_permission_param +from keycloak.uma_permissions import ( + AuthStatus, + Resource, + Scope, + UMAPermission, + build_permission_param, +) + + +def test_uma_permission_obj(): + """Test generic UMA permission.""" + with pytest.raises(PermissionDefinitionError): + UMAPermission(permission="bad") + + p1 = UMAPermission(permission=Resource("Resource")) + assert p1.resource == "Resource" + assert p1.scope == "" + assert repr(p1) == "Resource" + assert str(p1) == "Resource" + + p2 = UMAPermission(permission=Scope("Scope")) + assert p2.resource == "" + assert p2.scope == "Scope" + assert repr(p2) == "#Scope" + assert str(p2) == "#Scope" + assert {p1, p1} != {p2, p2} def test_resource_with_scope_obj(): @@ -174,3 +199,14 @@ def test_build_permission_misbuilt_dict_non_iterable(): with pytest.raises(KeycloakPermissionFormatError) as err: build_permission_param({"res1": 5}) assert err.match(re.escape("misbuilt permission {'res1': 5}")) + + +def test_auth_status_bool(): + """Test bool method of AuthStatus.""" + assert not bool(AuthStatus(is_logged_in=True, is_authorized=False, missing_permissions="")) + assert bool(AuthStatus(is_logged_in=True, is_authorized=True, missing_permissions="")) + + +def test_build_permission_without_scopes(): + """Test build permission param with scopes.""" + assert build_permission_param(permissions={"Resource": None}) == {"Resource"}