diff --git a/src/pretix/api/views/exporters.py b/src/pretix/api/views/exporters.py index 6993469002..be83f0bc84 100644 --- a/src/pretix/api/views/exporters.py +++ b/src/pretix/api/views/exporters.py @@ -81,7 +81,7 @@ class ExportersMixin: serializer = JobRunSerializer(exporter=instance, data=self.request.data, **self.get_serializer_kwargs()) serializer.is_valid(raise_exception=True) - cf = CachedFile() + cf = CachedFile(web_download=False) cf.date = now() cf.expires = now() + timedelta(days=3) cf.save() diff --git a/src/pretix/base/migrations/0170b_auto_20201218_1810.py b/src/pretix/base/migrations/0170b_auto_20201218_1810.py new file mode 100644 index 0000000000..2a5a2f2f37 --- /dev/null +++ b/src/pretix/base/migrations/0170b_auto_20201218_1810.py @@ -0,0 +1,27 @@ +# Generated by Django 3.0.11 on 2020-12-18 18:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0170_remove_hidden_urls'), + ] + replaces = [ + ('pretixbase', '0162b_auto_20201218_1810'), + ('pretixbase', '0169b_auto_20201218_1810'), + ] + + operations = [ + migrations.AddField( + model_name='cachedfile', + name='session_key', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='cachedfile', + name='web_download', + field=models.BooleanField(default=True), + ), + ] diff --git a/src/pretix/base/models/base.py b/src/pretix/base/models/base.py index ba21a3361e..9b66c0c574 100644 --- a/src/pretix/base/models/base.py +++ b/src/pretix/base/models/base.py @@ -28,6 +28,8 @@ class CachedFile(models.Model): filename = models.CharField(max_length=255) type = models.CharField(max_length=255) file = models.FileField(null=True, blank=True, upload_to=cachedfile_name, max_length=255) + web_download = models.BooleanField(default=True) # allow web download, True for backwards compatibility in plugins + session_key = models.TextField(null=True, blank=True) # only allow download in this session @receiver(post_delete, sender=CachedFile) diff --git a/src/pretix/base/services/shredder.py b/src/pretix/base/services/shredder.py index f174a0b58e..ced3851794 100644 --- a/src/pretix/base/services/shredder.py +++ b/src/pretix/base/services/shredder.py @@ -17,7 +17,7 @@ from pretix.celery_app import app @app.task(base=ProfiledEventTask) -def export(event: Event, shredders: List[str]) -> None: +def export(event: Event, shredders: List[str], session_key=None) -> None: known_shredders = event.get_data_shredders() with NamedTemporaryFile() as rawfile: @@ -55,6 +55,8 @@ def export(event: Event, shredders: List[str]) -> None: cf.date = now() cf.filename = event.slug + '.zip' cf.type = 'application/zip' + cf.session_key = session_key + cf.web_download = True cf.expires = now() + timedelta(hours=1) cf.save() cf.file.save(cachedfile_name(cf, cf.filename), rawfile) diff --git a/src/pretix/base/views/cachedfiles.py b/src/pretix/base/views/cachedfiles.py index 61b5861852..1f907f2ec5 100644 --- a/src/pretix/base/views/cachedfiles.py +++ b/src/pretix/base/views/cachedfiles.py @@ -13,7 +13,11 @@ class DownloadView(TemplateView): @cached_property def object(self) -> CachedFile: try: - return get_object_or_404(CachedFile, id=self.kwargs['id']) + o = get_object_or_404(CachedFile, id=self.kwargs['id'], web_download=True) + if o.session_key: + if o.session_key != self.request.session.session_key: + raise Http404() + return o except ValueError: # Invalid URLs raise Http404() diff --git a/src/pretix/control/forms/__init__.py b/src/pretix/control/forms/__init__.py index 3caa21d079..49ddaa4998 100644 --- a/src/pretix/control/forms/__init__.py +++ b/src/pretix/control/forms/__init__.py @@ -203,6 +203,7 @@ class CachedFileField(ExtFileField): cf = CachedFile.objects.create( expires=now() + datetime.timedelta(days=1), date=now(), + web_download=True, filename=data.name, type=data.content_type, ) @@ -218,6 +219,7 @@ class CachedFileField(ExtFileField): if isinstance(data, File): cf = CachedFile.objects.create( expires=now() + datetime.timedelta(days=1), + web_download=True, date=now(), filename=data.name, type=data.content_type, diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 929c4dce35..02d7f6fbde 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -2045,7 +2045,7 @@ class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, View) messages.error(self.request, _('There was a problem processing your input. See below for error details.')) return self.get(request, *args, **kwargs) - cf = CachedFile() + cf = CachedFile(web_download=True, session_key=request.session.session_key) cf.date = now() cf.expires = now() + timedelta(days=3) cf.save() diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index aae5327fe1..c87096fcce 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -1245,7 +1245,7 @@ class ExportDoView(OrganizerPermissionRequiredMixin, ExportMixin, AsyncAction, V messages.error(self.request, _('There was a problem processing your input. See below for error details.')) return self.get(request, *args, **kwargs) - cf = CachedFile() + cf = CachedFile(web_download=True, session_key=request.session.session_key) cf.date = now() cf.expires = now() + timedelta(days=3) cf.save() diff --git a/src/pretix/control/views/pdf.py b/src/pretix/control/views/pdf.py index c82bb4c582..cb717ea694 100644 --- a/src/pretix/control/views/pdf.py +++ b/src/pretix/control/views/pdf.py @@ -137,7 +137,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView): buffer = BytesIO() p.write(buffer) buffer.seek(0) - c = CachedFile() + c = CachedFile(web_download=True) c.expires = now() + timedelta(days=7) c.date = now() c.filename = 'background_preview.pdf' @@ -162,7 +162,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView): "status": "error", "error": error }) - c = CachedFile() + c = CachedFile(web_download=True) c.expires = now() + timedelta(days=7) c.date = now() c.filename = 'background_preview.pdf' diff --git a/src/pretix/control/views/shredder.py b/src/pretix/control/views/shredder.py index 6b511288b3..ba09d518fe 100644 --- a/src/pretix/control/views/shredder.py +++ b/src/pretix/control/views/shredder.py @@ -75,7 +75,7 @@ class ShredExportView(RecentAuthenticationRequiredMixin, EventPermissionRequired if constr: return self.error(ShredError(self.get_error_url())) - return self.do(self.request.event.id, request.POST.getlist("shredder")) + return self.do(self.request.event.id, request.POST.getlist("shredder"), self.request.session.session_key) class ShredDoView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View): diff --git a/src/pretix/plugins/badges/views.py b/src/pretix/plugins/badges/views.py index d6ceca9062..301c1d04e5 100644 --- a/src/pretix/plugins/badges/views.py +++ b/src/pretix/plugins/badges/views.py @@ -235,7 +235,7 @@ class OrderPrintDo(EventPermissionRequiredMixin, AsyncAction, View): def post(self, request, *args, **kwargs): order = get_object_or_404(self.request.event.orders, code=request.GET.get("code")) - cf = CachedFile() + cf = CachedFile(web_download=True, session_key=self.request.session.session_key) cf.date = now() cf.type = 'application/pdf' cf.expires = now() + timedelta(days=3)