Skip to content
Snippets Groups Projects
Verified Commit dd9cca43 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Disable download by default on track urls exposed over federation

parent 828f602b
Branches
Tags
No related merge requests found
......@@ -1159,7 +1159,7 @@ class UploadSerializer(jsonld.JsonLdSerializer):
"duration": instance.duration,
"url": [
{
"href": utils.full_url(instance.listen_url),
"href": utils.full_url(instance.listen_url_no_download),
"type": "Link",
"mediaType": instance.mimetype,
},
......@@ -1235,7 +1235,7 @@ class ChannelUploadSerializer(serializers.Serializer):
{
"type": "Link",
"mimeType": upload.mimetype,
"href": utils.full_url(upload.listen_url),
"href": utils.full_url(upload.listen_url_no_download),
},
{
"type": "Link",
......
......@@ -846,6 +846,11 @@ class Upload(models.Model):
def listen_url(self):
return self.track.listen_url + "?upload={}".format(self.uuid)
@property
def listen_url_no_download(self):
# Not using reverse because this is slow
return self.listen_url + "&download=false"
def get_transcoded_version(self, format, max_bitrate=None):
if format:
mimetype = utils.EXTENSION_TO_MIMETYPE[format]
......
......@@ -393,7 +393,9 @@ def get_content_disposition(filename):
return "attachment; {}".format(filename)
def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True):
def handle_serve(
upload, user, format=None, max_bitrate=None, proxy_media=True, download=True
):
f = upload
# we update the accessed_date
now = timezone.now()
......@@ -450,6 +452,7 @@ def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True):
mapping = {"nginx": "X-Accel-Redirect", "apache2": "X-Sendfile"}
file_header = mapping[settings.REVERSE_PROXY_TYPE]
response[file_header] = file_path
if download:
response["Content-Disposition"] = get_content_disposition(filename)
if mt:
response["Content-Type"] = mt
......@@ -476,6 +479,7 @@ class ListenViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"track__album__artist", "track__artist"
)
explicit_file = request.GET.get("upload")
download = request.GET.get("download", "true").lower() == "true"
if explicit_file:
queryset = queryset.filter(uuid=explicit_file)
queryset = queryset.playable_by(actor)
......@@ -499,6 +503,7 @@ class ListenViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
format=format,
max_bitrate=max_bitrate,
proxy_media=settings.PROXY_MEDIA,
download=download,
)
......
......@@ -953,7 +953,7 @@ def test_activity_pub_audio_serializer_to_ap(factories):
"attributedTo": upload.library.actor.fid,
"url": [
{
"href": utils.full_url(upload.listen_url),
"href": utils.full_url(upload.listen_url_no_download),
"type": "Link",
"mediaType": "audio/mp3",
},
......@@ -1105,7 +1105,7 @@ def test_channel_upload_serializer(factories):
{
"type": "Link",
"mimeType": upload.mimetype,
"href": utils.full_url(upload.listen_url),
"href": utils.full_url(upload.listen_url_no_download),
},
{
"type": "Link",
......
......@@ -437,6 +437,13 @@ def test_upload_listen_url(factories):
assert upload.listen_url == expected
def test_upload_listen_url_no_download(factories):
upload = factories["music.Upload"]()
expected = upload.track.listen_url + "?upload={}&download=false".format(upload.uuid)
assert upload.listen_url_no_download == expected
def test_library_schedule_scan(factories, now, mocker):
on_commit = mocker.patch("funkwhale_api.common.utils.on_commit")
library = factories["music.Library"](uploads_count=5)
......
......@@ -382,10 +382,28 @@ def test_listen_correct_access(factories, logged_in_api_client):
library__privacy_level="me",
import_status="finished",
)
expected_filename = upload.track.full_name + ".ogg"
url = reverse("api:v1:listen-detail", kwargs={"uuid": upload.track.uuid})
response = logged_in_api_client.get(url)
assert response.status_code == 200
assert response["Content-Disposition"] == "attachment; filename*=UTF-8''{}".format(
urllib.parse.quote(expected_filename)
)
def test_listen_correct_access_download_false(factories, logged_in_api_client):
logged_in_api_client.user.create_actor()
upload = factories["music.Upload"](
library__actor=logged_in_api_client.user.actor,
library__privacy_level="me",
import_status="finished",
)
url = reverse("api:v1:listen-detail", kwargs={"uuid": upload.track.uuid})
response = logged_in_api_client.get(url, {"download": "false"})
assert response.status_code == 200
assert "Content-Disposition" not in response
def test_listen_explicit_file(factories, logged_in_api_client, mocker, settings):
......@@ -406,6 +424,7 @@ def test_listen_explicit_file(factories, logged_in_api_client, mocker, settings)
format=None,
max_bitrate=None,
proxy_media=settings.PROXY_MEDIA,
download=True,
)
......@@ -500,6 +519,7 @@ def test_listen_transcode(factories, now, logged_in_api_client, mocker, settings
format="mp3",
max_bitrate=None,
proxy_media=settings.PROXY_MEDIA,
download=True,
)
......@@ -532,6 +552,7 @@ def test_listen_transcode_bitrate(
format=None,
max_bitrate=expected,
proxy_media=settings.PROXY_MEDIA,
download=True,
)
......@@ -562,6 +583,7 @@ def test_listen_transcode_in_place(
format="mp3",
max_bitrate=None,
proxy_media=settings.PROXY_MEDIA,
download=True,
)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment