Search code examples
djangonginxgunicorndjango-file-uploaddjango-deployment

Django - media files - security


I created a Django app with Video files. I'm using Gunicorn & Nginx. A user (not root) that runs the django server.

I restricted the views so only the users with correct permissions can view these. This works fine.

But when watching a video, I can get the url. (../media/videos/video.mp4) enter image description here

And now everyone with this file-location can see the video.

I'm a little lost now. Do I need to use a package like django-sendfile2’s ? Or do I need to change my server settings and limit access to the media folders ?


Solution

  • I did manage to secure my files using the django-private-storage package. django-sendfile2’s might also work, but I did find the documentation less explanatory. Following the instructions I installed the packages:

    pip install django-private-storage
    

    And added following lines to the Settings.py file:

    INSTALLED_APPS += (
        'private_storage',
    )
    PRIVATE_STORAGE_ROOT = os.path.join(BASE_DIR, 'private-media')
    

    in the model I added the field:

    video = PrivateFileField(upload_to='videos/%Y/%m/%d', null=True)
    

    In the view I added:

    from private_storage.views import PrivateStorageDetailView
    
    class PlayJobVideo(PrivateStorageDetailView):
        model = Video
        model_file_field = "video"
        template_name = "index/play_video.html"
    
        def get_object(self):
            return Video.objects.get(id=self.kwargs['video_id'])
        
        def can_access_file(self, private_file):
            return True
    

    And then I wrote a decorator owner_only()

    def owner-only():
        def decorators(view_func, *args, **kwargs):
            def wrapper_function(request, *args, **kwargs):
    
            try:
                if request.user:
                    if video.user == request.user:
                        return view_func(request, *args, **kwargs)
                    else:
                        return redirect('index:home')
            except:
                return redirect('index:home')
        return wrapper_function
    return decorators
    

    And the I added this decorator to the view.

    @method_decorator(owner_only(), name='dispatch')
    class PlayVideo(PrivateStorageDetailView):
                   ...