"""Shared validation logic.""" from http import HTTPStatus from unittest.mock import call, patch import pytest from abacus_state.constants.constants import ( ACTION_STATUSES, DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES, ORCHARD_PROFILE_TYPES, PARENT_TABLE_NAMES, ) from abacus_state.constants.error import ( ERROR_DONT_HAVE_PERMISSIONS, ERROR_MESSAGE_FORBIDDEN_PROFILE_TYPE_UPDATE, ) from abacus_state.utils.permissions import ( check_create_permissions_access_checks, check_update_permissions_access_checks, ) from tests.utils.factories import AbacusStateFactory @patch('abacus_state.utils.permissions.abort') def test_invalid_profile_type(mock_abort): """Test check_permissions with not DocumentsProfile type.""" params = [ {'parent_table_name': 'some_table', 'parent_table_id': 1, 'action_name': 'init'} ] profile_type = 'some_other_profile' check_create_permissions_access_checks(params, profile_type) mock_abort.assert_not_called() @patch('abacus_state.utils.permissions.abort') @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_invalid_action(mock_validate_record_owner, mock_abort): """Test check_permissions with invalid action name.""" params = [ { 'parent_table_name': PARENT_TABLE_NAMES.ACCOUNT_PAYEE, 'parent_table_id': 1, 'action_name': 'invalid_name', } ] profile_type = ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE check_create_permissions_access_checks(params, profile_type) mock_abort.assert_called_once_with( code=HTTPStatus.BAD_REQUEST, description='Profile type DocumentsProfile is forbidden to create state for account_payee invalid_name', ) @patch('abacus_state.utils.permissions.abort') @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=False, ) def test_invalid_record_owner(mock_validate_record_owner, mock_abort): """Test check_permissions with failed validation for record owner.""" params = [ { 'parent_table_name': PARENT_TABLE_NAMES.ACCOUNT_PAYEE, 'parent_table_id': 1, 'action_name': 'banking_details_review', } ] profile_type = ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE check_create_permissions_access_checks(params, profile_type) mock_abort.assert_called_once_with( code=HTTPStatus.UNAUTHORIZED, description=ERROR_DONT_HAVE_PERMISSIONS ) @patch('abacus_state.utils.permissions.abort') @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_valid_record_owner(mock_validate_record_owner, mock_abort): """Test check_permissions with success scenario.""" params = [ { 'parent_table_name': PARENT_TABLE_NAMES.ACCOUNT_PAYEE, 'parent_table_id': 1, 'action_name': 'banking_details_review', } ] profile_type = ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE check_create_permissions_access_checks(params, profile_type) mock_abort.assert_not_called() @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_check_update_permissions_no_profile_check_success(mock_validate_record_owner): """Test check_update_permissions function.""" state = AbacusStateFactory.build() check_update_permissions_access_checks( state, { 'action_status': ACTION_STATUSES.INIT, 'message': 'test', }, ORCHARD_PROFILE_TYPES.ABACUS_PROFILE, ) assert not mock_validate_record_owner.called @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) @patch('abacus_state.utils.permissions.build_resource_access_check') def test_check_update_permissions_valid_action_success( mock_build_resource_access_check, mock_validate_record_owner, action_data ): """Test check_update_permissions function.""" (parent_table_name, action_name), action_statuses = action_data state = AbacusStateFactory.build( parent_table_name=parent_table_name, action_name=action_name ) for action_status in action_statuses: mock_validate_record_owner.reset_mock() check_update_permissions_access_checks( state, { 'action_status': action_status, 'message': 'test', }, ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, ) assert mock_validate_record_owner.called assert mock_build_resource_access_check.call_args_list[0] == call( parent_table_name, state.parent_table_id, ) @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_check_update_permissions_failure_bad_table( mock_validate_record_owner, action_data ): """Test check_update_permissions function.""" (_, action_name), action_statuses = action_data parent_table_name = 'wrong_table' state = AbacusStateFactory.build( parent_table_name=parent_table_name, action_name=action_name ) for action_status in action_statuses: with pytest.raises( Exception, match=ERROR_MESSAGE_FORBIDDEN_PROFILE_TYPE_UPDATE.format( profile_type=ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, action=action_name, table=parent_table_name, action_status=action_status, ), ): check_update_permissions_access_checks( state, { 'action_status': action_status, 'message': 'test', }, ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, ) assert not mock_validate_record_owner.called @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_check_update_permissions_failure_bad_action( mock_validate_record_owner, action_data ): """Test check_update_permissions function.""" (parent_table_name, _), action_statuses = action_data action_name = 'wrong_action' state = AbacusStateFactory.build( parent_table_name=parent_table_name, action_name=action_name ) for action_status in action_statuses: with pytest.raises( Exception, match=ERROR_MESSAGE_FORBIDDEN_PROFILE_TYPE_UPDATE.format( profile_type=ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, action=action_name, table=parent_table_name, action_status=action_status, ), ): check_update_permissions_access_checks( state, { 'action_status': action_status, 'message': 'test', }, ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, ) assert not mock_validate_record_owner.called @pytest.mark.parametrize( 'action_data', DOCUMENTS_PROFILE_ALLOWED_STATUSES_BY_PARENT_TABLE_BY_ACTION_NAMES.items(), ) @patch( 'abacus_state.utils.permissions.validate_record_owner_access_checks', return_value=True, ) def test_check_update_permissions_failure_bad_action_state( mock_validate_record_owner, action_data ): """Test check_update_permissions function.""" (parent_table_name, action_name), action_statuses = action_data action_statuses = set(ACTION_STATUSES) - set(action_statuses) state = AbacusStateFactory.build( parent_table_name=parent_table_name, action_name=action_name ) for action_status in action_statuses: with pytest.raises( Exception, match=ERROR_MESSAGE_FORBIDDEN_PROFILE_TYPE_UPDATE.format( profile_type=ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, action=action_name, table=parent_table_name, action_status=action_status, ), ): check_update_permissions_access_checks( state, { 'action_status': action_status, 'message': 'test', }, ORCHARD_PROFILE_TYPES.DOCUMENTS_PROFILE, ) assert not mock_validate_record_owner.called