"""Tests for authorizing many accounts.""" from unittest.mock import ANY, MagicMock, patch import pytest from python_pdp_sdk import ( ResourceWithAttributes, ) from python_pdp_sdk.backends import exceptions from python_pdp_sdk.resource_getters.base import ForwardKwargsGetter from abacus_contract.utils.authorization import ( pdp_authorize_many_accounts, pdp_authorize_many_resources_without_attributes, pdp_authorize_resource ) @pytest.mark.parametrize( 'auth_response,expected_result', [ pytest.param(True, True, id='authorized, expect True'), pytest.param(False, False, id='unauthorized, expect False'), ], ) @patch('abacus_contract.utils.authorization.authorization_backend') @patch('abacus_contract.utils.authorization.g') def test_pdp_authorize_resource( mock_g: MagicMock, mock_authorization_backend: MagicMock, auth_response: bool, expected_result: bool, ) -> None: """Test pdp_authorize_resource.""" resource_id = 1234 resource_type = 'contract' mock_authorization_backend.is_authorized.return_value = auth_response result = pdp_authorize_resource( resource_id=resource_id, resource_type=resource_type ) assert result == expected_result mock_authorization_backend.is_authorized.assert_called_once_with( action='view', resource_id=resource_id, resource_type=resource_type, resource_getter=ANY ) call_args = mock_authorization_backend.is_authorized.call_args assert call_args is not None kwargs = call_args[1] assert isinstance(kwargs['resource_getter'], ForwardKwargsGetter) if not result: mock_g.log.warn.assert_called_once_with( 'Unauthorized to access resource', resources={ 'identity_id': mock_g.request_context.jwt_identity_id, 'resource_id': resource_id, 'resource_type': resource_type, 'auth_response': auth_response } ) else: mock_g.log.warn.assert_not_called() def test_action_is_passed_to_pdp_authorize_resource(): """Test action is passed to pdp_authorize_resource.""" resource_id = 1234 resource_type = 'some_resource_type' action = 'some_action' with (patch('abacus_contract.utils.authorization.authorization_backend') as mock_authorization_backend): pdp_authorize_resource( resource_id=resource_id, resource_type=resource_type, action=action) mock_authorization_backend.is_authorized.assert_called_once_with( action=action, resource_id=resource_id, resource_type=resource_type, resource_getter=ANY, ) @pytest.mark.parametrize( 'auth_response,expected_result', [ pytest.param([True, False], False, id='partial access, expect False'), pytest.param([True, True], True, id='full access, expect True'), pytest.param([False, False], False, id='no access, expect False'), pytest.param([True], False, id='length mismatch, expect False'), ], ) @patch('abacus_contract.utils.authorization.authorization_backend') @patch('abacus_contract.utils.authorization.g') def test_pdp_authorize_many_resources_without_attributes( mock_g: MagicMock, mock_authorization_backend: MagicMock, auth_response: list[bool], expected_result: bool, ) -> None: """Test pdp_authorize_many_resources_without_attributes.""" resource_ids = [1234, 5678] resource_type = 'transaction_type' mock_authorization_backend.is_authorized_many.return_value = auth_response result = pdp_authorize_many_resources_without_attributes( resource_ids=resource_ids, resource_type=resource_type) assert result == expected_result mock_authorization_backend.is_authorized_many.assert_called_once_with( action='view', resource_type=resource_type, resources_with_attributes=[ ResourceWithAttributes( resource_id=1234, attributes={} ), ResourceWithAttributes( resource_id=5678, attributes={} ), ], ) if not result: mock_g.log.warn.assert_called_once_with( 'Unauthorized to access many resources', resources={ 'identity_id': mock_g.request_context.jwt_identity_id, 'resource_ids': resource_ids, 'resource_type': resource_type, 'auth_response': auth_response } ) else: mock_g.log.warn.assert_not_called() def test_action_is_passed_to_pdp_authorize_many_resources_without_attributes(): """Test action is passed to pdp_authorize_many_resources_without_attributes.""" resource_ids = [1234, 5678] resource_type = 'transaction_type' action = 'some_action' with (patch('abacus_contract.utils.authorization.authorization_backend') as mock_authorization_backend): pdp_authorize_many_resources_without_attributes( resource_ids=resource_ids, resource_type=resource_type, action=action) mock_authorization_backend.is_authorized_many.assert_called_once_with( action=action, resource_type=resource_type, resources_with_attributes=[ ResourceWithAttributes( resource_id=1234, attributes={} ), ResourceWithAttributes( resource_id=5678, attributes={} ), ], ) @patch('abacus_contract.utils.authorization.authorization_backend') @patch('abacus_contract.utils.authorization.g') def test_pdp_authorize_many_resources_without_attributes_error( mock_g: MagicMock, mock_authorization_backend: MagicMock ) -> None: """Test error handling of pdp_authorize_many_resources_without_attributes.""" mock_authorization_backend.is_authorized_many.side_effect = \ exceptions.InvalidRequestException('🥶') resource_ids = [1234, 5678] resource_type = 'transaction_type' result = pdp_authorize_many_resources_without_attributes( resource_ids=resource_ids, resource_type=resource_type ) assert result is False mock_g.log.warn.assert_called_with( 'Caught a PDP InvalidRequestException', resource={ 'identity_id': mock_g.request_context.jwt_identity_id, 'resource_ids': resource_ids, 'resource_type': resource_type, 'error': '🥶', } ) @pytest.mark.parametrize( 'auth_response,expected_result', [ pytest.param([True, False], False, id='partial access, expect False'), pytest.param([True, True], True, id='full access, expect True'), pytest.param([False, False], False, id='no access, expect False'), pytest.param([True], False, id='length mismatch, expect False'), ], ) @patch('abacus_contract.utils.authorization.authorization_backend') @patch('abacus_contract.utils.authorization.g') def test_pdp_authorize_many_accounts( mock_g: MagicMock, mock_authorization_backend: MagicMock, auth_response: list[bool], expected_result: bool, ) -> None: """Test authorize_many_accounts.""" account_ids = [1234, 5678] mock_authorization_backend.is_authorized_many.return_value = auth_response result = pdp_authorize_many_accounts(account_ids) assert result == expected_result mock_authorization_backend.is_authorized_many.assert_called_once_with( action='view_abacus_account_info', resource_type='account', resources_with_attributes=[ ResourceWithAttributes( resource_id=1234, attributes={ 'tenant': {'tenant_type': 'account'}, 'id_to_uuid_exchange_tenant': { 'tenant_type': 'account', 'tenant_id': 1234, } }, ), ResourceWithAttributes( resource_id=5678, attributes={ 'tenant': {'tenant_type': 'account'}, 'id_to_uuid_exchange_tenant': { 'tenant_type': 'account', 'tenant_id': 5678, } }, ), ], ) if not result: mock_g.log.warn.assert_called_once_with( 'Unauthorized to access many accounts', resources={ 'identity_id': mock_g.request_context.jwt_identity_id, 'account_ids': account_ids, 'auth_response': auth_response } ) else: mock_g.log.warn.assert_not_called() def test_action_is_passed_to_authorize_many_accounts(): """Test that the action is passed to authorize_many_accounts.""" account_ids = [1234, 5678] action = 'view_something' with (patch('abacus_contract.utils.authorization.authorization_backend') as mock_authorization_backend): pdp_authorize_many_accounts(account_ids, action) mock_authorization_backend.is_authorized_many.assert_called_once_with( action=action, resource_type='account', resources_with_attributes=[ ResourceWithAttributes( resource_id=1234, attributes={ 'tenant': {'tenant_type': 'account'}, 'id_to_uuid_exchange_tenant': { 'tenant_type': 'account', 'tenant_id': 1234, } }, ), ResourceWithAttributes( resource_id=5678, attributes={ 'tenant': {'tenant_type': 'account'}, 'id_to_uuid_exchange_tenant': { 'tenant_type': 'account', 'tenant_id': 5678, } }, ), ], ) @patch('abacus_contract.utils.authorization.authorization_backend') @patch('abacus_contract.utils.authorization.g') def test_pdp_authorize_many_accounts_error( mock_g: MagicMock, mock_authorization_backend: MagicMock ) -> None: """Test error handling of pdp_authorize_many_accounts.""" mock_authorization_backend.is_authorized_many.side_effect = \ exceptions.InvalidRequestException('🥶') account_ids = [1234, 5678] result = pdp_authorize_many_accounts(account_ids=account_ids) assert result is False mock_g.log.warn.assert_called_with( 'Caught a PDP InvalidRequestException', resources={ 'identity_id': mock_g.request_context.jwt_identity_id, 'resource_ids': account_ids, 'resource_type': 'account', 'error': '🥶', } )