Skip to content

Commit

Permalink
Merge pull request #12 from StephanJarisch/SIPWU-1189
Browse files Browse the repository at this point in the history
SIPWU-1189: Fix 500 Error if file does not exist on server
  • Loading branch information
nezhar authored Sep 11, 2024
2 parents 9e20d67 + d08bba6 commit ff18bb5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
10 changes: 10 additions & 0 deletions drf_attachments/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ class AttachmentAdmin(admin.ModelAdmin, AttachmentAdminMixin):
"creation_date",
)

def get_object(self, request, object_id, from_field=None):
obj = super().get_object(request, object_id, from_field)

# handling missing file (e.g. file may have been deleted on the server)
if not obj.file.storage.exists(obj.file.name):
self.message_user(request, "File not found", level="ERROR")
obj.file = None

return obj

@staticmethod
def content_object(obj):
entity = obj.content_object
Expand Down
12 changes: 4 additions & 8 deletions drf_attachments/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,7 @@ def __str__(self):

@property
def is_image(self):
return (
"mime_type" in self.meta
and self.meta["mime_type"]
and self.meta["mime_type"].startswith("image")
)
return self.get_mime_type().startswith("image")

@property
def default_context(self):
Expand All @@ -126,13 +122,13 @@ def is_modified(self):
return self.creation_date != self.last_modification_date

def get_extension(self):
return self.meta.get("extension")
return self.meta.get("extension", "unkown")

def get_size(self):
return self.meta.get("size")
return self.meta.get("size", 0)

def get_mime_type(self):
return self.meta.get("mime_type")
return self.meta.get("mime_type", "unkown")

def save(self, *args, **kwargs):
# set computed values for direct and API access
Expand Down
27 changes: 19 additions & 8 deletions drf_attachments/rest/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from django.http import FileResponse
from django.http import FileResponse, Http404
from django_filters.rest_framework import DjangoFilterBackend
from drf_attachments.storage import AttachmentFileStorage
from drf_attachments.models.models import Attachment
from drf_attachments.rest.renderers import FileDownloadRenderer
from drf_attachments.rest.serializers import AttachmentSerializer
from rest_framework import viewsets
from rest_framework.decorators import action, parser_classes
from rest_framework.filters import SearchFilter
Expand All @@ -8,10 +12,6 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer

from drf_attachments.models.models import Attachment
from drf_attachments.rest.renderers import FileDownloadRenderer
from drf_attachments.rest.serializers import AttachmentSerializer

__all__ = [
"AttachmentViewSet",
]
Expand Down Expand Up @@ -41,10 +41,16 @@ def get_storage_path(self):
attachment = self.get_object()
meta = getattr(attachment.content_object, "AttachmentMeta", None)
storage_location = getattr(meta, "storage_location", None)
if storage_location:
return f"{storage_location}/{attachment.file.name}"

# Get custom storage location
if meta and storage_location:
storage = AttachmentFileStorage(location=meta.storage_location)
else:
return attachment.file.path
# Default storage value from FileField "file"
storage = attachment.file.storage

# Return the file path using the appropriate storage system
return storage.path(attachment.file.name)

@action(
detail=True,
Expand All @@ -62,6 +68,11 @@ def download(self, request, format=None, *args, **kwargs):
else:
download_file_name = f"attachment_{attachment.pk}{extension}"

# Check if file exists via storage due to custom storage locations
# without triggering SuspiciousFileOperation
if not attachment.file.storage.exists(attachment.file.name):
raise Http404()

return FileResponse(
open(storage_path, "rb"),
as_attachment=True,
Expand Down
5 changes: 3 additions & 2 deletions drf_attachments/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ class AttachmentFileStorage(FileSystemStorage):
Attachments are served with a dedicated API route instead
"""

def __init__(self):
super().__init__(location=settings.PRIVATE_ROOT)
def __init__(self, *args, **kwargs):
kwargs.setdefault("location", settings.PRIVATE_ROOT)
super().__init__(*args, **kwargs)

def url(self, name):
from drf_attachments.models import Attachment
Expand Down

0 comments on commit ff18bb5

Please sign in to comment.