"""Test the OwsPdpClient Connector.""" from typing import Any import httpx import pytest from owsclient.test import OwsClientMock from pytest_mock import MockerFixture from python_pdp_sdk.backends.exceptions import PdpAuthenticationError from python_pdp_sdk.connectors.ows_pdp.models.auth_effect import AuthEffect from python_pdp_sdk.connectors.ows_pdp.models.check_resources_request import ( CheckResourcesRequest, ) from python_pdp_sdk.connectors.ows_pdp.models.get_allowed_tenants_request import ( GetAllowedTenantsRequest, ) from python_pdp_sdk.connectors.ows_pdp.models.tenant_type import TenantType from python_pdp_sdk.connectors.ows_pdp.ows_pdp import OwsPdpClient def test_check_my_resources( ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock ) -> None: """Test the check_my_resources method.""" request = { "resources": [ { "resource": { "resource_id": "890", "resource_type": "audience", "attributes": { "tenant": { "tenant_type": "account", "tenant_uuid": "42879e8c-9f47-4214-b611-1e6feb0be6af", # noqa: E501 } }, }, "action": "view", } ], "include_resource_attributes_in_response": False, } expected_response = { "request_id": "96812af8-4868-11ef-8e76-aa7635b21e50", "resources": [ { "resource": { "resource_id": "890", "resource_type": "audience", "attributes": {}, }, "action": "view", "effect": "deny", "errors": {"validation_errors": None}, } ], } ows_client_mock.post( "ows-pdp", path="/identity/self/check/resources/", json=request, ).mock( return_value=httpx.Response( 200, json=expected_response, ), ) expected_resource_response = [ { "resource": { "resource_id": "890", "resource_type": "audience", "attributes": {}, }, "action": "view", "effect": AuthEffect.DENY, "errors": {"validation_errors": None}, } ] crr = CheckResourcesRequest.from_dict(request) assert crr response = ows_pdp_client.check_my_resources(crr) if response is not None: assert expected_resource_response == response.to_dict()["resources"] else: pytest.fail("Check Resources Response is None") @pytest.mark.parametrize( "status_code,expected_exception", [ pytest.param( 401, PdpAuthenticationError, id="401 raises PdpAuthenticationError" ), pytest.param(403, httpx.RequestError, id="403 raises httpx.RequestError"), pytest.param(500, httpx.RequestError, id="500 raises httpx.RequestError"), ], ) def test_check_my_resources_failure( ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock, status_code: int, expected_exception: type[Exception], ) -> None: """Test the check_my_resources raises appropriate exception for non-200 responses.""" request = { "resources": [ { "resource": { "resource_id": "890", "resource_type": "audience", }, "action": "view", } ], "include_resource_attributes_in_response": False, } ows_client_mock.post( "ows-pdp", path="/identity/self/check/resources/", json=request, ).mock( return_value=httpx.Response( status_code, json={ "code": "error", "message": f"Error with status {status_code}", }, ), ) crr = CheckResourcesRequest.from_dict(request) assert crr with pytest.raises(expected_exception): ows_pdp_client.check_my_resources(crr) def test_check_my_resources_none_response( ows_pdp_client: OwsPdpClient, mocker: MockerFixture ) -> None: """Test that check_my_resources raises httpx.RequestError when response is None.""" request = { "resources": [ { "resource": { "resource_id": "890", "resource_type": "audience", }, "action": "view", } ], "include_resource_attributes_in_response": False, } # Mock the ows_client.post method to return None mocker.patch.object(ows_pdp_client.ows_client, "post", return_value=None) crr = CheckResourcesRequest.from_dict(request) assert crr with pytest.raises(httpx.RequestError) as exc_info: ows_pdp_client.check_my_resources(crr) assert "unexpected response" in str(exc_info.value).lower() @pytest.mark.parametrize( "response", [ pytest.param(None, id="null response raises error"), pytest.param(True, id="bool response raises error"), pytest.param(3392, id="int response raises error"), pytest.param("", id="empty string response raises error"), pytest.param("something", id="string that isn't json raises error"), pytest.param("{}", id="empty json raises error"), pytest.param( { "request_id": "1234", }, id="incomplete response raises error", ), ], ) def test_check_my_resources_invalid_response( response: Any, ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock ) -> None: """Test the check_my_resources method raises exception when response cannot be parsed.""" request = { "resources": [ { "resource": { "resource_id": "890", "resource_type": "audience", }, "action": "view", } ], "include_resource_attributes_in_response": False, } ows_client_mock.post( "ows-pdp", path="/identity/self/check/resources/", json=request, ).mock( return_value=httpx.Response( 200, json=response, ), ) crr = CheckResourcesRequest.from_dict(request) assert crr with pytest.raises(httpx.DecodingError): ows_pdp_client.check_my_resources(crr) def test_get_allowed_tenants( ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock ) -> None: """Test the get_allowed_tenants method.""" request = { "resource_type": "audience", "action": "view", } expected_response = { "resource_type": "audience", "action": "view", "tenants": [ { "tenant_type": "account", "tenant_uuid": "3467989a-e428-43d0-b560-aedbbec33ae0", } ], } ows_client_mock.post( "ows-pdp", path="/identity/self/allowed-tenants/", json=request, ).mock( return_value=httpx.Response( 200, json=expected_response, ), ) expected_get_allowed_tenants_response = { "resource_type": "audience", "action": "view", "tenants": [ { "tenant_id": None, "tenant_type": TenantType.ACCOUNT, "tenant_uuid": "3467989a-e428-43d0-b560-aedbbec33ae0", } ], } gatr = GetAllowedTenantsRequest.from_dict(request) assert gatr response = ows_pdp_client.get_allowed_tenants(gatr) if response is not None: assert expected_get_allowed_tenants_response == response.to_dict() else: pytest.fail("Get Allowed Tenants Response is None") @pytest.mark.parametrize( "status_code,expected_exception", [ pytest.param( 401, PdpAuthenticationError, id="401 raises PdpAuthenticationError" ), pytest.param(403, httpx.RequestError, id="403 raises httpx.RequestError"), pytest.param(500, httpx.RequestError, id="500 raises httpx.RequestError"), ], ) def test_get_allowed_tenants_failure( ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock, status_code: int, expected_exception: type[Exception], ) -> None: """Test the get_allowed_tenants raises appropriate exception for non-200 responses.""" request = { "resource_type": "audience", "action": "some cool action", } ows_client_mock.post( "ows-pdp", path="/identity/self/allowed-tenants/", json=request, ).mock( return_value=httpx.Response( status_code, content=f'{{"code":"error","message":"Error with status {status_code}"}}'.encode(), json={ "code": "error", "message": f"Error with status {status_code}", }, ), ) gatr = GetAllowedTenantsRequest.from_dict(request) assert gatr with pytest.raises(expected_exception): ows_pdp_client.get_allowed_tenants(gatr) def test_get_allowed_tenants_none_response( ows_pdp_client: OwsPdpClient, mocker: MockerFixture ) -> None: """Test that get_allowed_tenants raises httpx.RequestError when response is None.""" request = { "resource_type": "audience", "action": "some cool action", } # Mock the ows_client.post method to return None mocker.patch.object(ows_pdp_client.ows_client, "post", return_value=None) gatr = GetAllowedTenantsRequest.from_dict(request) assert gatr with pytest.raises(httpx.RequestError) as exc_info: ows_pdp_client.get_allowed_tenants(gatr) assert "unexpected response" in str(exc_info.value).lower() @pytest.mark.parametrize( "response", [ pytest.param(None, id="null response raises error"), pytest.param(True, id="bool response raises error"), pytest.param(3392, id="int response raises error"), pytest.param("", id="empty string response raises error"), pytest.param("something", id="string that isn't json raises error"), pytest.param("{}", id="empty json raises error"), pytest.param( { "action": "edit", }, id="incomplete response raises error", ), pytest.param( { "resource_type": "audience", "action": "edit", }, id="incomplete response raises error", ), ], ) def test_get_allowed_tenants_invalid_response( response: Any, ows_pdp_client: OwsPdpClient, ows_client_mock: OwsClientMock ) -> None: """Test the get_allowed_tenants method raises exception when response cannot be parsed.""" request = { "resource_type": "audience", "action": "some cool action", } ows_client_mock.post( "ows-pdp", path="/identity/self/allowed-tenants/", json=request, ).mock( return_value=httpx.Response( 200, json=response, ), ) gatr = GetAllowedTenantsRequest.from_dict(request) assert gatr with pytest.raises(httpx.DecodingError): ows_pdp_client.get_allowed_tenants(gatr) def test_get_my_roles(ows_pdp_client: OwsPdpClient) -> None: """Test the get_my_roles method.""" with pytest.raises(NotImplementedError): ows_pdp_client.get_my_roles()