"""Access and data visibility tests.""" import pytest from owsrequest.constants import headers as owsrequest_headers from sound_recordings import config from tests.integration.request import request_get_cache class BaseAccessControls: """Base class for access and data visibility tests.""" @staticmethod def top_sound_recordings_response(label): """Return /top-sound-recordings response.""" return request_get_cache( config.TOP_SOUND_RECORDINGS_URL, headers=label["headers"] ).json() @staticmethod def streams_response(label, isrc): """Return /sound-recording/{isrc}/streams response (for top s-r).""" return request_get_cache( config.STREAMS_URL.replace("", isrc), headers=label["headers"] ).json() @staticmethod def downloads_response(label, isrc): """Return /sound-recording/{isrc}/downloads response (for top s-r).""" return request_get_cache( config.DOWNLOADS_URL.replace("", isrc) + "?start_date=2019-12-01&end_date=2019-12-28", headers=label["headers"], ).json() @staticmethod def playlists_response(label, isrc): """Return /sound-recording/{isrc}/playlists response.""" return request_get_cache( config.PLAYLISTS_URL.replace("", isrc), headers=label["headers"] ).json() @staticmethod def top_countries_streams_response(label, isrc): """Return /sound-recording/{isrc}/top-countries-streams response.""" return request_get_cache( config.TOP_COUNTRIES_STREAMS_URL.replace("", isrc), headers=label["headers"], ).json() @staticmethod def top_countries_downloads_response(label, isrc): """Return /sound-recording/{isrc}/top-countries-downloads response.""" return request_get_cache( config.TOP_COUNTRIES_DOWNLOADS_URL.replace("", isrc), headers=label["headers"], ).json() @staticmethod def sound_recording_metadata_response(label, isrc): """Return /sound-recording/{isrc}/metadata response (for top s-r).""" return request_get_cache( config.SOUND_RECORDING_METADATA_URL.replace("", isrc), headers=label["headers"], ).json() @staticmethod def sound_recording_metadata_response_code(label, isrc): """Return /sound-recording/{isrc}/metadata response (for top s-r).""" return request_get_cache( config.SOUND_RECORDING_METADATA_URL.replace("", isrc), headers=label["headers"], ).status_code class TestAccessRegularLabels(BaseAccessControls): """Test data access and data visibility for a regular label.""" regular_label_1 = { "labelid": "19510", "headers": { owsrequest_headers.GRASS_ACCOUNT_ID: "19510", owsrequest_headers.GRASS_ACCOUNT_TYPE: "vendor", owsrequest_headers.ORCHARD_USER_ID: "alw:52827", }, } @pytest.fixture def owned_isrc(self): """Return an isrc that regular_label_1 owns.""" return "US3Z40407399" @pytest.fixture def not_owned_isrc(self): """Return an isrc that regular_label_1 doesn't own.""" return "GBUM71105426" @pytest.fixture def owned_product_id(self): """Return a product id that regular_label_1 owns.""" return "2857032" @pytest.fixture def not_owned_product_id(self): """Return a product id that regular_label_1 doesn't own.""" return "320039" def test_streams(self, owned_isrc): """Check if /sound-recording/{isrc}/streams is accessible.""" streams_response = self.streams_response(self.regular_label_1, owned_isrc) assert len(streams_response["aggregate"]["items"]) > 0 def test_downloads(self, owned_isrc): """Check if /sound-recording/{isrc}/downloads is accessible.""" downloads_response = self.downloads_response(self.regular_label_1, owned_isrc) assert len(downloads_response["aggregate"]["items"]) > 0 def test_playlists(self, owned_isrc): """Check if /sound-recording/{isrc}/playlists is accessible.""" playlists_response = self.playlists_response(self.regular_label_1, owned_isrc) assert len(playlists_response["playlists"]) > 0 def test_top_countries_streams(self, owned_isrc): """Test /sound-recording/{isrc}/top-countries-streams is accessible.""" top_countries_response = self.top_countries_streams_response( self.regular_label_1, owned_isrc ) assert len(top_countries_response["top_countries"]) > 0 def test_top_countries_downloads(self, owned_isrc): """Test /sound-recording/{isrc}/top-countries-downloads available.""" top_countries_response = self.top_countries_downloads_response( self.regular_label_1, owned_isrc ) assert len(top_countries_response["top_countries"]) > 0 def test_sound_recording_metadata(self, owned_isrc): """Check if /sound-recording/{isrc}/metadata is accessible.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.regular_label_1, owned_isrc ) assert sound_recording_metadata_response["isrc"] == owned_isrc def test_sound_recording_metadata_endpoint_for_not_owned_sound_recoding( self, not_owned_isrc ): """Test /sound-recording/{isrc}/metadata returns 404.""" response_code = self.sound_recording_metadata_response_code( self.regular_label_1, not_owned_isrc ) assert response_code == 404 class TestAccessD3andSubaccounts(BaseAccessControls): """Test data visibility of products for D3 label and its subaccounts. One D3 own two subaccounts, each sub has a product, there is an ISRC that appears on both products. """ d3_label = { "labelid": "21989", "headers": { owsrequest_headers.GRASS_ACCOUNT_ID: "21989", owsrequest_headers.GRASS_ACCOUNT_TYPE: "vendor", owsrequest_headers.ORCHARD_USER_ID: "alw:44827", }, } subaccount_label_1 = { "labelid": "21989", "subaccountid": "11777", "headers": { owsrequest_headers.GRASS_ACCOUNT_ID: "11777", owsrequest_headers.GRASS_ACCOUNT_TYPE: "subaccount", owsrequest_headers.ORCHARD_USER_ID: "alw:55776", }, } owned_isrc = "QMYLU1500005" not_owned_isrc = "ATN261983908" owned_product_id = "1868966" not_owned_product_id = "2595212" def test_sound_recording(self): """Check if /sound-recording/{isrc}/streams is accessible.""" streams_response = self.streams_response( self.subaccount_label_1, self.owned_isrc ) assert len(streams_response["aggregate"]["items"]) > 0 def test_d3_can_access_subaccount_sound_recording(self): """Check if /sound-recording/{isrc}/streams is accessible.""" streams_response = self.streams_response(self.d3_label, self.owned_isrc) assert len(streams_response["aggregate"]["items"]) > 0 def test_sound_recording_metadata(self): """Check if /sound-recording/{isrc}/metadata is accessible.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.subaccount_label_1, self.owned_isrc ) assert sound_recording_metadata_response["isrc"] == self.owned_isrc def test_d3_can_access_subaccount_sound_recording_metadata(self): """Check if /sound-recording/{isrc}/metadata is accessible.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.d3_label, self.owned_isrc ) assert sound_recording_metadata_response["isrc"] == self.owned_isrc def test_sound_recording_metadata_endpoint_for_not_owned_sound_recoding(self): """Test /sound-recording/{isrc}/metadata returns 404-not owned s-r.""" response_code = self.sound_recording_metadata_response_code( self.subaccount_label_1, self.not_owned_isrc ) assert response_code == 404 @pytest.mark.skip(reason="This is too brittle for now due to QA neo4j issues") class TestAccessArtists(BaseAccessControls): """Test data access and data visibility for regular labels. There are two labels (not D3, not subaccounts) that have the same ISRC on different Foducts. """ artist_profile_1 = { "labelid": None, "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "1346777", owsrequest_headers.ORCHARD_PROFILE_TYPE: "ArtistProfile", }, } artist_profile_2 = { "labelid": None, "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "12134", owsrequest_headers.ORCHARD_PROFILE_TYPE: "ArtistProfile", }, } @pytest.fixture def owned_isrc(self): """Return an isrc this labels owns.""" top_sound_recordings = self.top_sound_recordings_response(self.artist_profile_1) return top_sound_recordings["items"][0]["isrc"] @pytest.fixture def not_owned_isrc(self): """Return an isrc this labels owns.""" return "QM4TX2030965" @pytest.fixture def owned_product_id(self, owned_isrc): """Return a product id this label owns.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.artist_profile_1, owned_isrc ) return sound_recording_metadata_response["products"][0]["product_id"] @pytest.fixture def not_owned_product_id(self, not_owned_isrc): """Return a product id this label owns.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.artist_profile_2, not_owned_isrc ) return sound_recording_metadata_response["products"][0]["product_id"] def test_sound_recording(self, owned_isrc): """Check if /sound-recording/{isrc} is accessible.""" streams_response = self.streams_response(self.artist_profile_1, owned_isrc) assert len(streams_response["aggregate"]["items"]) > 0 def test_sound_recording_metadata(self, owned_isrc): """Check if /sound-recording/{isrc}/metadata is accessible.""" sound_recording_metadata_response = self.sound_recording_metadata_response( self.artist_profile_1, owned_isrc ) assert sound_recording_metadata_response["isrc"] == owned_isrc def test_sound_recording_metadata_endpoint_for_not_owned_sound_recoding( self, not_owned_isrc ): """Check if /sound-recording/{isrc}/metadata returns 404.""" response_code = self.sound_recording_metadata_response_code( self.artist_profile_1, not_owned_isrc ) assert response_code == 404 class TestAccessInsights(BaseAccessControls): """Test data access and data visibility for Insights Profiles. Testing employee, D3, vendor & subaccount profiles. N.B. THIS D3 DOES NOT OWN THIS SUBACCOUNT. """ # Profile has access to all Orchard labels employee_profile = { "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "1040", owsrequest_headers.ORCHARD_PROFILE_TYPE: "InsightsProfile", } } # Profile has access to Thirty Tigers d3_profile = { "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "26517", owsrequest_headers.ORCHARD_PROFILE_TYPE: "InsightsProfile", } } # Profile has access to Frenchkiss Records vendor_profile = { "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "26426", owsrequest_headers.ORCHARD_PROFILE_TYPE: "InsightsProfile", } } # Profile has access to City of Dreams LLC subaccount_profile = { "headers": { owsrequest_headers.ORCHARD_PROFILE_ID: "6617", owsrequest_headers.ORCHARD_PROFILE_TYPE: "InsightsProfile", } } d3_owned_isrc = "QZ84K1700002" d3_owned_product_id = "2047561" vendor_owned_isrc = "GBUM71105426" vendor_owned_product_id = "320039" subaccount_owned_isrc = "TCADD1729833" subaccount_owned_product_id = "2615324" @pytest.mark.parametrize( ("insights_profile", "profile_owned_isrc"), [ (d3_profile, d3_owned_isrc), (vendor_profile, vendor_owned_isrc), (subaccount_profile, subaccount_owned_isrc), (employee_profile, d3_owned_isrc), (employee_profile, vendor_owned_isrc), (employee_profile, subaccount_owned_isrc), ], ) def test_profile_has_streams_for_profile_owned_isrc( self, insights_profile, profile_owned_isrc ): """Check /sound-recording/{isrc}/streams is accessible.""" streams_response = self.streams_response(insights_profile, profile_owned_isrc) assert len(streams_response["aggregate"]["items"]) > 0 @pytest.mark.parametrize( ("isrc_not_owned_by_subaccount"), [d3_owned_isrc, vendor_owned_isrc] ) def test_subaccount_profile_does_not_see_streams_for_not_owned_isrcs( self, isrc_not_owned_by_subaccount ): """Check /sound-recording/{isrc}/streams is not accessible.""" streams_response = self.streams_response( self.subaccount_profile, isrc_not_owned_by_subaccount ) assert len(streams_response["aggregate"]["items"]) == 0 @pytest.mark.parametrize( ("isrc_not_owned_by_vendor"), [d3_owned_isrc, subaccount_owned_isrc] ) def test_vendor_profile_does_not_see_streams_for_not_owned_isrcs( self, isrc_not_owned_by_vendor ): """Check /sound-recording/{isrc}/streams is not accessible.""" streams_response = self.streams_response( self.vendor_profile, isrc_not_owned_by_vendor ) assert len(streams_response["aggregate"]["items"]) == 0 @pytest.mark.parametrize( ("isrc_not_owned_by_d3"), [vendor_owned_isrc, subaccount_owned_isrc] ) def test_d3_profile_does_not_see_streams_for_not_owned_isrcs( self, isrc_not_owned_by_d3 ): """Check /sound-recording/{isrc}/streams is not accessible.""" streams_response = self.streams_response(self.d3_profile, isrc_not_owned_by_d3) assert len(streams_response["aggregate"]["items"]) == 0 @pytest.mark.parametrize( ("insights_profile, profile_owned_isrc"), [ (d3_profile, d3_owned_isrc), (vendor_profile, vendor_owned_isrc), (subaccount_profile, subaccount_owned_isrc), (employee_profile, d3_owned_isrc), (employee_profile, vendor_owned_isrc), (employee_profile, subaccount_owned_isrc), ], ) def test_profile_has_sound_recording_metadata_for_profile_owned_isrc( self, insights_profile, profile_owned_isrc ): """Check if /sound-recording/{isrc}/metadata is accessible.""" response = self.sound_recording_metadata_response( insights_profile, profile_owned_isrc ) assert response["isrc"] == profile_owned_isrc @pytest.mark.parametrize( ("isrc_not_owned_by_subaccount"), [d3_owned_isrc, vendor_owned_isrc] ) def test_subaccount_profile_does_not_see_sr_metadata_for_not_owned_isrcs( self, isrc_not_owned_by_subaccount ): """Check if /sound-recording/{isrc}/metadata returns 404.""" response_code = self.sound_recording_metadata_response_code( self.subaccount_profile, isrc_not_owned_by_subaccount ) assert response_code == 404 @pytest.mark.parametrize( ("isrc_not_owned_by_vendor"), [d3_owned_isrc, subaccount_owned_isrc] ) def test_vendor_profile_does_not_see_sr_metadata_for_not_owned_isrcs( self, isrc_not_owned_by_vendor ): """Check if /sound-recording/{isrc}/metadata returns 404.""" response_code = self.sound_recording_metadata_response_code( self.vendor_profile, isrc_not_owned_by_vendor ) assert response_code == 404 @pytest.mark.parametrize( ("isrc_not_owned_by_d3"), [vendor_owned_isrc, subaccount_owned_isrc] ) def test_d3_profile_does_not_see_sr_metadata_for_not_owned_isrcs( self, isrc_not_owned_by_d3 ): """Check if /sound-recording/{isrc}/metadata returns 404.""" response_code = self.sound_recording_metadata_response_code( self.d3_profile, isrc_not_owned_by_d3 ) assert response_code == 404