Skip to content

Commit

Permalink
Only generate signed S3 link to user export when user clicks download
Browse files Browse the repository at this point in the history
  • Loading branch information
Minnozz committed Mar 24, 2024
1 parent ab7b089 commit 5bd66cb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 30 deletions.
30 changes: 9 additions & 21 deletions bookwyrm/templates/preferences/export-user.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,27 +126,15 @@ <h2 class="title">{% trans "Recent Exports" %}</h2>
<span>{{ export.size|get_file_size }}</span>
</td>
<td>
{% if export.job.complete and not export.job.status == "stopped" and not export.job.status == "failed" %}
{% if export.url%}
<p>
<a href="{{ export.url }}">
<span class="icon icon-download" aria-hidden="true"></span>
<span class="is-hidden-mobile">
{% trans "Download your export" %}
</span>
</a>
</p>
{% else %}
<p>
<a download="" href="/preferences/user-export/{{ export.job.task_id }}">
<span class="icon icon-download" aria-hidden="true"></span>
<span class="is-hidden-mobile">
{% trans "Download your export" %}
</span>
</a>
</p>
{% endif %}

{% if export.url %}
<a href="{{ export.url }}">
<span class="icon icon-download" aria-hidden="true"></span>
<span class="is-hidden-mobile">
{% trans "Download your export" %}
</span>
</a>
{% elif export.job.complete and not export.job.status == "stopped" and not export.job.status == "failed" %}
{% trans "Archive is no longer available" %}
{% endif %}
</td>
</tr>
Expand Down
29 changes: 20 additions & 9 deletions bookwyrm/views/preferences/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.template.response import TemplateResponse
from django.utils import timezone
from django.views import View
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.shortcuts import redirect
Expand Down Expand Up @@ -166,17 +167,8 @@ def get(self, request):
export = {"job": job}

if settings.USE_S3:
# make custom_domain None so we can sign the url
# see https://github.com/jschneier/django-storages/issues/944
storage = S3Boto3Storage(querystring_auth=True, custom_domain=None)

# for s3 we download directly from s3, so we need a signed url
export["url"] = S3Boto3Storage.url(
storage,
f"/exports/{job.task_id}.tar.gz",
expire=settings.S3_SIGNED_URL_EXPIRY,
)

# for s3 we create a new tar file in s3,
# so we need to check the size of _that_ file
try:
Expand All @@ -194,6 +186,9 @@ def get(self, request):
# file no longer exists
export["size"] = 0

if export["size"] > 0:
export["url"] = reverse("prefs-export-file", args=[job.task_id])

exports.append(export)

site = models.SiteSettings.objects.get()
Expand Down Expand Up @@ -235,6 +230,21 @@ class ExportArchive(View):
def get(self, request, archive_id):
"""download user export file"""
export = BookwyrmExportJob.objects.get(task_id=archive_id, user=request.user)

if isinstance(export.export_data.storage, storage_backends.ExportsS3Storage):
# make custom_domain None so we can sign the url
# see https://github.com/jschneier/django-storages/issues/944
storage = S3Boto3Storage(querystring_auth=True, custom_domain=None)
try:
url = S3Boto3Storage.url(
storage,
f"/exports/{export.task_id}.tar.gz",
expire=settings.S3_SIGNED_URL_EXPIRY,
)
except Exception:
raise Http404()
return redirect(url)

if isinstance(export.export_data.storage, storage_backends.ExportsFileStorage):
try:
return HttpResponse(
Expand All @@ -246,4 +256,5 @@ def get(self, request, archive_id):
)
except FileNotFoundError:
raise Http404()

return HttpResponseServerError()

0 comments on commit 5bd66cb

Please sign in to comment.