Django hide media files link for certain people

80 views Asked by At

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?

2

There are 2 answers

2
FLYAX On BEST ANSWER

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.

0
YellowShark On

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!