1

I programmed a function where you can download a file from the media folder with the media files depending on the link. The problem is that if you change the path in the link you have access to all the media files and not just the ones you are supposed to download. Can I somehow ban the other links (with a permission or something) or is there a clever way to solve the whole thing?

FLYAX
  • 141
  • 12

2 Answers2

1

Not sure that my approach is the most clever, but I usually add a user field to the model that has the file field. And then within that function-based view that is returning the file, I perform a check to see if the request.user is the same user. Also, for files like these I make sure to store them in a directory that is not publicly accessible whatsoever, using the FileSystemStorage class, along with the FileField class.

Here's a couple snippets that illustrate my own approach:

# settings.py
MEDIA_ROOT_FOR_SENSITIVE_FILES = '/path/to/your/special/folder'

# models.py
from functools import partial

from django.db import models
from django.conf import settings
from django.core.files.storage import FileSystemStorage
from django.http import FileResponse
from django.http.response import Http404
from django.db.models import FileField

# Create a custom storage location, using a value from your settings file
sensitive_upload_storage = FileSystemStorage(location=settings.MEDIA_ROOT_FOR_SENSITIVE_FILES,
                                             base_url='/some_prefix/')
# ... and a file field that will use the custom storage
AuthenticatedFileField = partial(FileField, storage=sensitive_upload_storage)


class UserUpload(models.Model):
    user = models.ForeignKey('auth.User', on_delete=models.DO_NOTHING)
    file = AuthenticatedFileField()


# views.py / handles the url "/some_prefix/{PATH}".
def download_userupload(request, path):
    try:
        file = UserUpload.objects.get(user=request.user, file=path)
    except UserUpload.DoesNotExist:
        return Http404

    return FileResponse(file.file)

Hope that helps, and glad to follow-up if you have any further q's!

YellowShark
  • 2,169
  • 17
  • 17
1

I have now found a good solution.

I now handle my files via a function called sendfile (https://github.com/johnsensible/django-sendfile) and send them to the user.

This is used to access the media folder internally. I can simply switch off the Media Link in NGINX.

FLYAX
  • 141
  • 12
  • It would be cool to add some basic code that shows how to use the sendfile wrapper. As it stands now your answer contains only a link. If that repository would be moved in the future your answer could become useless. – sanitizedUser Jul 06 '23 at 11:52
  • Ill fix that asap. Thanks for reminding – FLYAX Aug 03 '23 at 00:11