"""Unit tests for handlers related to tenants.""" import json from unittest.mock import patch import pytest from owsrequest import error_response from owsresponse import response from pythonfeatures import pythonfeatures from permissions import config from permissions.connectors import redis from permissions.constants import constants from permissions.logic import resource @pytest.mark.parametrize( ('headers', 'logic_response', 'context_type', 'profile_type'), [ [ { 'Orchard-Identity-Id': 'admin-uuid', 'Orchard-Profile-Id': 122, 'Orchard-Profile-Type': 'InsightsProfile', 'Content-Type': 'application/json', }, response.Response(message={'data': {'foo': 'bar'}, 'total': 1}), 'profile', 'InsightsProfile', ], [ { 'Orchard-Identity-Id': 'admin-uuid', 'Orchard-Profile-Id': 122, 'Orchard-Profile-Type': 'InsightsProfile', 'Content-Type': 'application/json', }, error_response.create_error_incomplete_profile_headers(), 'not profile', 'InsightsProfile', ], [ { 'Orchard-Identity-Id': 'admin-uuid', 'Orchard-Profile-Type': 'InsightsProfile', 'Content-Type': 'application/json', }, error_response.create_error_incomplete_profile_headers(), 'profile', 'InsightsProfile', ], [ { 'Orchard-Identity-Id': 'admin-uuid', 'Orchard-Profile-Id': 122, 'Content-Type': 'application/json', }, error_response.create_error_incomplete_profile_headers(), 'profile', None, ], [ { 'Orchard-Identity-Id': 'admin-uuid', 'Orchard-Profile-Id': 122, 'Orchard-Profile-Type': 'LabelProfile', 'Content-Type': 'application/json', }, error_response.create_error_forbidden_user(), 'profile', 'LabelProfile', ], ], ) @patch('permissions.handlers.handlers.g') def test_get_profiles_for_admin( mock_g, app_context, mocker, fixture_client, headers, logic_response, context_type, profile_type ): """Verify get_profiles_for_admin.""" mock_g.request_context.context_type = context_type mock_g.request_context.profile_type = profile_type mocker.patch( 'permissions.logic.resource.get_user_profiles_for_admin', return_value=logic_response ) mocker.patch.object( pythonfeatures, 'get_single_feature', return_value=response.Response(message='enabled') ) handler_response = fixture_client.get('identity/admin/profiles', json={}, headers=headers) result = json.loads(handler_response.data.decode()) assert handler_response.status_code == logic_response.status if logic_response.status == 200: assert result['items'] == logic_response.message.get('data') else: assert result == logic_response.errors @pytest.mark.parametrize( ('identity_uuid', 'status_code', 'logic_response'), [ ( 'admin-uuid', 200, response.Response( message={ 'items': {'foo': 'bar'}, 'pagination': { 'total_records': 143, 'type': 'standard', }, } ), ), (None, 401, None), ], ) @patch('permissions.handlers.handlers.g') def test_get_my_adminable_resources( mock_g, app_context, mocker, fixture_client, identity_uuid, status_code, logic_response ): """Test get_my_adminable_resources.""" mock_g.request_context.jwt_identity_id = identity_uuid mock_get_resources_key = mocker.patch( 'permissions.handlers.handlers.get_resources_key', return_value='some-key' ) mocker.patch('permissions.connectors.redis.get', return_value=None) mocker.patch( 'permissions.logic.resource.get_resources_for_identity_uuid', return_value=logic_response ) mocker.patch('permissions.connectors.redis.set', return_value={}) handler_response = fixture_client.get('identity/admin/resources/all/') result = json.loads(handler_response.data) assert handler_response.status_code == status_code if status_code == 200: mock_get_resources_key.assert_called() redis.get.assert_called_with('some-key') resource.get_resources_for_identity_uuid.assert_called_with( identity_uuid, constants.DEFAULT_LIMIT, constants.DEFAULT_OFFSET ) redis.set.assert_called() assert result['items'] == {'foo': 'bar'} assert result['pagination'] == { 'type': 'standard', 'total_records': logic_response.message['pagination']['total_records'], } @patch('permissions.handlers.handlers.g') def test_get_my_adminable_resources_with_cached_data(mock_g, app_context, mocker, fixture_client): """Test get_my_adminable_resources when cached data is available.""" mock_g.request_context.jwt_identity_id = 'admin-uuid' mock_get_resources_key = mocker.patch( 'permissions.handlers.handlers.get_resources_key', return_value='some-key' ) mocker.patch( 'permissions.connectors.redis.get', return_value={'items': 'some cached data', 'pagination': {}}, ) mocker.patch('permissions.logic.resource.get_resources_for_identity_uuid') mocker.patch('permissions.connectors.redis.set') handler_response = fixture_client.get('identity/admin/resources/all/') result = json.loads(handler_response.data) assert handler_response.status_code == 200 mock_get_resources_key.assert_called() redis.get.assert_called_with('some-key') resource.get_resources_for_identity_uuid.assert_not_called() redis.set.assert_not_called() assert result['items'] == 'some cached data' @pytest.mark.parametrize( ('cache_response'), [ (None), ({'items': 'some cached data', 'pagination': {}}), ], ) @pytest.mark.parametrize( ('logic_response'), [ (response.Response(status=400, message={'status': 'fake error'})), ( response.Response( message={ 'items': {'foo': 'bar'}, 'pagination': { 'type': 'standard', 'total_records': 384, }, } ) ), ], ) @patch('permissions.handlers.handlers.g') def test_get_my_adminable_resources_limit_offset_defaults( mock_g, app_context, mocker, fixture_client, cache_response, logic_response ): """Test get_my_adminable_resources with limit and offset defaults.""" mock_g.request_context.jwt_identity_id = 'admin-uuid' mocker.patch('permissions.handlers.handlers.get_resources_key', return_value='some-key') # We are not getting any cached data. mocker.patch('permissions.connectors.redis.get', return_value=cache_response) mocker.patch( 'permissions.logic.resource.get_resources_for_identity_uuid', return_value=logic_response ) mocker.patch('permissions.connectors.redis.set') handler_response = fixture_client.get( f'identity/admin/resources/all/?limit={constants.DEFAULT_LIMIT}&offset={constants.DEFAULT_OFFSET}' # noqa ) # Expect to set the cache when the limit and offset are the defaults. if not cache_response: assert json.loads(handler_response.data) == logic_response.message if logic_response: redis.set.assert_called_with('some-key', logic_response.message, config.REDIS_CACHE_TTL) else: redis.set.assert_not_called() # If we get back a cache response, expect to not set the cache. else: assert json.loads(handler_response.data) == cache_response redis.set.assert_not_called() @pytest.mark.parametrize( ('cache_response', 'limit', 'offset'), [ (None, 10, constants.DEFAULT_OFFSET), (None, constants.DEFAULT_LIMIT, 10), (None, 10, 10), ({'items': 'some cached data', 'pagination': {}}, 10, constants.DEFAULT_OFFSET), ({'items': 'some cached data', 'pagination': {}}, constants.DEFAULT_LIMIT, 10), ({'items': 'some cached data', 'pagination': {}}, 10, 10), ], ) def test_get_my_adminable_resources_limit_offset_values( app_context, mocker, fixture_client, cache_response, limit, offset ): """Test get_my_adminable_resources with limit and offset values.""" mocker.patch('permissions.utils.cache_utils.get_resources_key', return_value='some-key') mocker.patch('permissions.connectors.redis.get', return_value=cache_response) mocker.patch( 'permissions.logic.resource.get_resources_for_identity_uuid', return_value=response.Response(message={'foo': 'bar'}), ) mocker.patch('permissions.connectors.redis.set') handler_response = fixture_client.get( f'identity/admin/resources/all/?limit={limit}&offset={offset}' ) json.loads(handler_response.data) # Expect to never set the cache if limit or offset are not the default. redis.set.assert_not_called()