diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py index 41de30f10..db6298a9e 100644 --- a/api/funkwhale_api/music/serializers.py +++ b/api/funkwhale_api/music/serializers.py @@ -125,5 +125,5 @@ class ImportBatchSerializer(serializers.ModelSerializer): jobs = ImportJobSerializer(many=True, read_only=True) class Meta: model = models.ImportBatch - fields = ('id', 'jobs', 'status', 'creation_date') + fields = ('id', 'jobs', 'status', 'creation_date', 'import_request') read_only_fields = ('creation_date',) diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 8e46cbd71..bf9d39b1d 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -19,6 +19,7 @@ from musicbrainzngs import ResponseError from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator +from funkwhale_api.requests.models import ImportRequest from funkwhale_api.musicbrainz import api from funkwhale_api.common.permissions import ( ConditionalAuthentication, HasModelPermission) @@ -314,14 +315,28 @@ class SubmitViewSet(viewsets.ViewSet): serializer = serializers.ImportBatchSerializer(batch) return Response(serializer.data) + def get_import_request(self, data): + try: + raw = data['importRequest'] + except KeyError: + return + + pk = int(raw) + try: + return ImportRequest.objects.get(pk=pk) + except ImportRequest.DoesNotExist: + pass + @list_route(methods=['post']) @transaction.non_atomic_requests def album(self, request, *args, **kwargs): data = json.loads(request.body.decode('utf-8')) - import_data, batch = self._import_album(data, request, batch=None) + import_request = self.get_import_request(data) + import_data, batch = self._import_album( + data, request, batch=None, import_request=import_request) return Response(import_data) - def _import_album(self, data, request, batch=None): + def _import_album(self, data, request, batch=None, import_request=None): # we import the whole album here to prevent race conditions that occurs # when using get_or_create_from_api in tasks album_data = api.releases.get(id=data['releaseId'], includes=models.Album.api_includes)['release'] @@ -332,7 +347,9 @@ class SubmitViewSet(viewsets.ViewSet): except ResponseError: pass if not batch: - batch = models.ImportBatch.objects.create(submitted_by=request.user) + batch = models.ImportBatch.objects.create( + submitted_by=request.user, + import_request=import_request) for row in data['tracks']: try: models.TrackFile.objects.get(track__mbid=row['mbid']) @@ -346,6 +363,7 @@ class SubmitViewSet(viewsets.ViewSet): @transaction.non_atomic_requests def artist(self, request, *args, **kwargs): data = json.loads(request.body.decode('utf-8')) + import_request = self.get_import_request(data) artist_data = api.artists.get(id=data['artistId'])['artist'] cleaned_data = models.Artist.clean_musicbrainz_data(artist_data) artist = importers.load(models.Artist, cleaned_data, artist_data, import_hooks=[]) @@ -353,7 +371,8 @@ class SubmitViewSet(viewsets.ViewSet): import_data = [] batch = None for row in data['albums']: - row_data, batch = self._import_album(row, request, batch=batch) + row_data, batch = self._import_album( + row, request, batch=batch, import_request=import_request) import_data.append(row_data) return Response(import_data[0]) diff --git a/api/tests/conftest.py b/api/tests/conftest.py index 82fd2655a..10d7c3235 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -65,6 +65,15 @@ def logged_in_api_client(db, factories, api_client): delattr(api_client, 'user') +@pytest.fixture +def superuser_api_client(db, factories, api_client): + user = factories['users.SuperUser']() + assert api_client.login(username=user.username, password='test') + setattr(api_client, 'user', user) + yield api_client + delattr(api_client, 'user') + + @pytest.fixture def superuser_client(db, factories, client): user = factories['users.SuperUser']() diff --git a/api/tests/music/test_import.py b/api/tests/music/test_import.py new file mode 100644 index 000000000..f2ca1abbd --- /dev/null +++ b/api/tests/music/test_import.py @@ -0,0 +1,37 @@ +import json + +from django.urls import reverse + +from . import data as api_data + + +def test_create_import_can_bind_to_request( + mocker, factories, superuser_api_client): + request = factories['requests.ImportRequest']() + + mocker.patch('funkwhale_api.music.tasks.import_job_run') + mocker.patch( + 'funkwhale_api.musicbrainz.api.artists.get', + return_value=api_data.artists['get']['soad']) + mocker.patch( + 'funkwhale_api.musicbrainz.api.images.get_front', + return_value=b'') + mocker.patch( + 'funkwhale_api.musicbrainz.api.releases.get', + return_value=api_data.albums['get_with_includes']['hypnotize']) + payload = { + 'releaseId': '47ae093f-1607-49a3-be11-a15d335ccc94', + 'importRequest': request.pk, + 'tracks': [ + { + 'mbid': '1968a9d6-8d92-4051-8f76-674e157b6eed', + 'source': 'https://www.youtube.com/watch?v=1111111111', + } + ] + } + url = reverse('api:v1:submit-album') + response = superuser_api_client.post( + url, json.dumps(payload), content_type='application/json') + batch = request.import_batches.latest('id') + + assert batch.import_request == request