"""Test permissions logic layer.""" from unittest.mock import patch import flexmock import pytest from oto import response as oto_response from owsrequest.constants.headers import ( GRASS_ACCOUNT_ID, GRASS_ACCOUNT_TYPE, ORCHARD_PROFILE_ID, ORCHARD_PROFILE_TYPE, ORCHARD_USER_ID, PROFILE_TYPE_ARTIST, PROFILE_TYPE_CONTENT, PROFILE_TYPE_INSIGHTS, PROFILE_TYPE_LABEL, ) from owsrequest.context import RequestContext from requests.structures import CaseInsensitiveDict from analytics.logic import permissions from analytics.services import ows_permissions from analytics.services.ows_permissions import ( ARTIST_INFO_RESOURCE_TYPE, SUBACCOUNT_RESOURCE_TYPE, VENDOR_RESOURCE_TYPE, ) class TestGetArtistInfoIds: """Test call to get_artist_info_ids.""" profile_id = "1346777" profile_type = "ArtistProfile" response = { "items": [ { "type": ARTIST_INFO_RESOURCE_TYPE, "name": "BTS in Bighit Entertainment", "id": 917636, "roles": ["analytics"], }, { "type": ARTIST_INFO_RESOURCE_TYPE, "name": "BTS in Bighit Soundtrack", "id": 1552280, "roles": ["analytics"], }, ] } @pytest.fixture def mock_ows_permissions_response(self): """Return mock response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_artist_info_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(self.response) ) @pytest.fixture(autouse=True) def no_cache(self): """Mock out caching of ows-permissions response.""" with patch("analytics.connectors.redis.client.get") as get: get.return_value = None yield get @pytest.fixture def mock_ows_permissions_failure_response(self): """Return mock failure response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_artist_info_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(status=500) ) def test_success(self, mock_ows_permissions_response): """Test get_artist_info_ids returns array of ids from response.""" result = permissions.get_artist_info_ids(self.profile_type, self.profile_id) assert result == list(map(lambda item: item["id"], self.response["items"])) def test_failure(self, mock_ows_permissions_failure_response): """Test get_artist_info_ids returns [] from ows_permissions failure.""" result = permissions.get_artist_info_ids(self.profile_type, self.profile_id) assert result == [] def test_called_with_empty_params(self): """Test get_artist_info_ids returns [] for empty parameters.""" result = permissions.get_artist_info_ids(None, None) assert result == [] class TestGetVendorAndSubaccount: """Test call to get_vendor_and_subaccount.""" profile_id = 67344 profile_type = "LabelProfile" vendor_id = 15073 subaccount_id = 123 vendor_response = {"items": [{"type": VENDOR_RESOURCE_TYPE, "id": vendor_id}]} subaccount_response = { "items": [ { "type": SUBACCOUNT_RESOURCE_TYPE, "id": subaccount_id, "vendor_id": vendor_id, } ] } caps_subaccount_response = { "items": [ { "type": SUBACCOUNT_RESOURCE_TYPE.upper(), "id": subaccount_id, "vendor_id": vendor_id, } ] } multi_subaccount_response = { "items": [ { "type": SUBACCOUNT_RESOURCE_TYPE, "id": subaccount_id, "vendor_id": vendor_id, }, {"type": "Subaccount", "id": subaccount_id, "vendor_id": vendor_id}, ] } @pytest.fixture def mock_vendor_response(self): """Return mock vendor response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_label_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(self.vendor_response) ) @pytest.fixture def mock_subaccount_response(self): """Return mock subaccount response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_label_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(self.subaccount_response) ) @pytest.fixture def mock_caps_subaccount_response(self): """Return mock different_case_subaccount from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_label_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(self.caps_subaccount_response) ) @pytest.fixture def mock_multi_subaccount_response(self): """Return mock multi_subaccount response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_label_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(self.multi_subaccount_response) ) @pytest.fixture def mock_ows_permissions_failure_response(self): """Return mock failure response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_label_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(status=500) ) @pytest.fixture(autouse=True) def no_cache(self): """Mock out caching of ows-permissions response.""" with patch("analytics.connectors.redis.client.get") as get: get.return_value = None yield get def test_vendor_success(self, mock_vendor_response): """Test get_vendor_and_subaccount returns vendor_id.""" result = permissions.get_vendor_and_subaccount( self.profile_type, self.profile_id ) assert result == (self.vendor_id, None) def test_subaccount_success(self, mock_subaccount_response): """Test get_vendor_and_subaccount returns vendor_id & subaccount_id.""" result = permissions.get_vendor_and_subaccount( self.profile_type, self.profile_id ) assert result == (None, self.subaccount_id) def test_caps_subaccount_success(self, mock_caps_subaccount_response): """Test get_vendor_and_subaccount returns vendor_id & subaccount_id.""" result = permissions.get_vendor_and_subaccount( self.profile_type, self.profile_id ) assert result == (None, self.subaccount_id) def test_multi_subaccount_success(self, mock_multi_subaccount_response): """Test get_vendor_and_subaccount returns vendor_id & subaccount_id.""" result = permissions.get_vendor_and_subaccount( self.profile_type, self.profile_id ) assert result == (None, self.subaccount_id) def test_failure(self, mock_ows_permissions_failure_response): """Test get_artist_info_ids returns [] from ows_permissions failure.""" result = permissions.get_vendor_and_subaccount( self.profile_type, self.profile_id ) assert result == (None, None) def test_called_with_empty_params(self): """Test get_artist_info_ids returns [] for empty parameters.""" result = permissions.get_vendor_and_subaccount(None, None) assert result == (None, None) class TestGetPermissionForInsightsProfile: """Test call to get_all_permissions_for_profile.""" profile_id = "1234" profile_type = "InsightsProfile" response = {"items": []} vendor_item = { "type": VENDOR_RESOURCE_TYPE, "name": "Frenchkiss", "id": 6971, "roles": ["analytics"], } artist_items = [ { "type": ARTIST_INFO_RESOURCE_TYPE, "name": "BTS in Bighit Entertainment", "id": 917636, "roles": ["analytics"], }, { "type": ARTIST_INFO_RESOURCE_TYPE, "name": "BTS in Bighit Soundtrack", "id": 1552280, "roles": ["analytics"], }, ] employee_item = { "type": VENDOR_RESOURCE_TYPE, "name": "All Orchard Labels", "id": "*", "roles": ["analytics"], } @pytest.fixture def mock_ows_permissions_employee_response(self): """Return mock response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_all_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response({"items": [self.employee_item]}) ) @pytest.fixture def mock_ows_permissions_vendor_response(self): """Return mock response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_all_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response({"items": [self.vendor_item]}) ) @pytest.fixture def mock_ows_permissions_artist_response(self): """Return mock response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_all_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response({"items": self.artist_items}) ) @pytest.fixture def mock_ows_permissions_failure_response(self): """Return mock failure response from ows_permissions.""" flexmock.flexmock(ows_permissions).should_receive( "get_all_resources" ).with_args(self.profile_type, self.profile_id).and_return( oto_response.Response(status=500) ) def test_employee_success(self, mock_ows_permissions_employee_response): """Test get_all_permissions_for_profile returns permissions.""" result = permissions.get_all_permissions_for_profile( PROFILE_TYPE_INSIGHTS, self.profile_id ) assert result == { "artist_ids": [], "label_ids": [], "subaccount_ids": [], "label_participant_ids": [], } def test_artist_ignored(self, mock_ows_permissions_artist_response): """Test get_all_permissions_for_profile returns permissions.""" result = permissions.get_all_permissions_for_profile( PROFILE_TYPE_INSIGHTS, self.profile_id ) assert result == { "artist_ids": None, "label_ids": None, "subaccount_ids": None, "label_participant_ids": None, } def test_vendor_success(self, mock_ows_permissions_vendor_response): """Test get_all_permissions_for_profile returns permissions.""" result = permissions.get_all_permissions_for_profile( PROFILE_TYPE_INSIGHTS, self.profile_id ) assert result == { "artist_ids": [], "label_ids": [6971], "subaccount_ids": [], "label_participant_ids": [], } def test_failure(self, mock_ows_permissions_failure_response): """Test get_artist_info_ids returns [] from ows_permissions failure.""" result = permissions.get_all_permissions_for_profile( PROFILE_TYPE_INSIGHTS, self.profile_id ) assert result == { "artist_ids": None, "label_ids": None, "subaccount_ids": None, "label_participant_ids": None, } def test_called_with_empty_params(self): """Test get_artist_info_ids returns [] for empty parameters.""" result = permissions.get_all_permissions_for_profile(None, None) assert result == { "artist_ids": None, "label_ids": None, "subaccount_ids": None, "label_participant_ids": None, } class TestGetPermissionsFilter: """Test call to get_permissions_filter.""" user_id = "alw:777" artist_ids = [123, 456] vendor_id = 456 subaccount_id = 789 profile_id = 999 @pytest.fixture def mock_artist_info_ids(self): """Mock out get_artist_info_ids.""" with patch("analytics.logic.permissions.get_artist_info_ids") as get: get.return_value = self.artist_ids yield get @pytest.fixture def mock_vendor_and_subaccount(self): """Mock out get_vendor_and_subaccount.""" with patch("analytics.logic.permissions.get_vendor_and_subaccount") as get: get.return_value = (self.vendor_id, self.subaccount_id) yield get @pytest.fixture def mock_permissions_for_service_profile(self): """Mock out get_all_permissions_for_profile.""" with patch( "analytics.logic.permissions." "get_all_permissions_for_profile" ) as get: get.return_value = { "artist_ids": [], "label_ids": [self.vendor_id], "subaccount_ids": None, "label_participant_ids": None, } yield get def test_label_profile(self, mock_vendor_and_subaccount): """Test label profile returns vendor and subaccount permissions.""" request_context = RequestContext( CaseInsensitiveDict( { ORCHARD_PROFILE_TYPE: PROFILE_TYPE_LABEL, ORCHARD_PROFILE_ID: self.profile_id, } ) ) assert permissions.get_permissions_filter(request_context) == { "artist_ids": None, "label_ids": [self.vendor_id], "subaccount_ids": [self.subaccount_id], "label_participant_ids": None, "feed_ids": [1, 2, 38], } def test_legacy_label_headers(self, mock_vendor_and_subaccount): """Test legacy headers returns vendor and subaccount permissions.""" request_context = RequestContext( CaseInsensitiveDict({ORCHARD_USER_ID: self.user_id}), label_profile=True ) assert permissions.get_permissions_filter(request_context) == { "artist_ids": None, "label_ids": [self.vendor_id], "subaccount_ids": [self.subaccount_id], "label_participant_ids": None, "feed_ids": [1, 2, 38], } def test_artist_profile(self, mock_artist_info_ids): """Test artist profile returns artist_ids.""" request_context = RequestContext( CaseInsensitiveDict( { ORCHARD_PROFILE_TYPE: PROFILE_TYPE_ARTIST, ORCHARD_PROFILE_ID: self.profile_id, } ) ) assert permissions.get_permissions_filter(request_context) == { "artist_ids": self.artist_ids, "label_ids": None, "subaccount_ids": None, "label_participant_ids": None, "feed_ids": [1, 2, 38], } def test_legacy_grass_headers(self): """Test legacy grass headers returns empty filter.""" request_context = RequestContext( CaseInsensitiveDict({GRASS_ACCOUNT_ID: 123, GRASS_ACCOUNT_TYPE: "vendor"}) ) assert permissions.get_permissions_filter(request_context) == { "artist_ids": None, "label_ids": None, "subaccount_ids": None, "label_participant_ids": None, "feed_ids": [1, 2, 38], } @pytest.mark.parametrize( ("test_description", "profile_type"), [ ("test insights profile", PROFILE_TYPE_INSIGHTS), ("test content profile", PROFILE_TYPE_CONTENT), ], ) def test_service_profile( self, mock_permissions_for_service_profile, test_description, profile_type, ): """Test service profile headers returns right filter.""" request_context = RequestContext( CaseInsensitiveDict( {ORCHARD_PROFILE_TYPE: profile_type, ORCHARD_PROFILE_ID: "1234"} ) ) assert permissions.get_permissions_filter(request_context) == { "artist_ids": [], "label_ids": [self.vendor_id], "subaccount_ids": None, "label_participant_ids": None, "feed_ids": [1, 2, 38], }