OpenSlides/openslides/mediafiles/views.py
Oskar Hahn dd4754d045 Disable the future-lock when updating the restircted data cache
Before this commit, there where two different locks when updating the restricted
data cache. A future lock, what is faster but only works in the same thread. The
other lock is in redis, it is not so fast, but also works in many threads.

The future lock was buggy, because on a second call of update_restricted_data
the same future was reused. So on the second run, the future was already done.

I don't see any way to delete. The last client would have to delete it, but there
is no way to find out which client the last one is.
2019-03-04 21:37:00 +01:00

105 lines
4.0 KiB
Python

from django.http import HttpResponseForbidden, HttpResponseNotFound
from django.views.static import serve
from .access_permissions import MediafileAccessPermissions
from .models import Mediafile
from ..core.config import config
from ..utils.auth import has_perm
from ..utils.rest_api import ModelViewSet, ValidationError
# Viewsets for the REST API
class MediafileViewSet(ModelViewSet):
"""
API endpoint for mediafile objects.
There are the following views: metadata, list, retrieve, create,
partial_update, update and destroy.
"""
access_permissions = MediafileAccessPermissions()
queryset = Mediafile.objects.all()
def check_view_permissions(self):
"""
Returns True if the user has required permissions.
"""
if self.action in ("list", "retrieve"):
result = self.get_access_permissions().check_permissions(self.request.user)
elif self.action == "metadata":
result = has_perm(self.request.user, "mediafiles.can_see")
elif self.action == "create":
result = has_perm(self.request.user, "mediafiles.can_see") and has_perm(
self.request.user, "mediafiles.can_upload"
)
elif self.action in ("partial_update", "update"):
result = (
has_perm(self.request.user, "mediafiles.can_see")
and has_perm(self.request.user, "mediafiles.can_upload")
and has_perm(self.request.user, "mediafiles.can_manage")
)
elif self.action == "destroy":
result = has_perm(self.request.user, "mediafiles.can_see") and has_perm(
self.request.user, "mediafiles.can_manage"
)
else:
result = False
return result
def create(self, request, *args, **kwargs):
"""
Customized view endpoint to upload a new file.
"""
# Check permission to check if the uploader has to be changed.
uploader_id = self.request.data.get("uploader_id")
if (
uploader_id
and not has_perm(request.user, "mediafiles.can_manage")
and str(self.request.user.pk) != str(uploader_id)
):
self.permission_denied(request)
if not self.request.data.get("mediafile"):
raise ValidationError({"detail": "You forgot to provide a file."})
return super().create(request, *args, **kwargs)
def destroy(self, request, *args, **kwargs):
"""
Customized view endpoint to delete uploaded files.
Does also delete the file from filesystem.
"""
# To avoid Django calling save() and triggering autoupdate we do not
# use the builtin method mediafile.mediafile.delete() but call
# mediafile.mediafile.storage.delete(...) directly. This may have
# unattended side effects so be careful especially when accessing files
# on server via Django methods (file, open(), save(), ...).
mediafile = self.get_object()
mediafile.mediafile.storage.delete(mediafile.mediafile.name)
for logo in config["logos_available"]:
if config[logo]["path"] == mediafile.mediafile.url:
config[logo] = {
"display_name": config[logo]["display_name"],
"path": "",
}
return super().destroy(request, *args, **kwargs)
def protected_serve(request, path, document_root=None, show_indexes=False):
try:
mediafile = Mediafile.objects.get(mediafile=path)
except Mediafile.DoesNotExist:
return HttpResponseNotFound(content="Not found.")
can_see = has_perm(request.user, "mediafiles.can_see")
is_special_file = mediafile.is_logo() or mediafile.is_font()
is_hidden_but_no_perms = mediafile.hidden and not has_perm(
request.user, "mediafiles.can_see_hidden"
)
if not is_special_file and (not can_see or is_hidden_but_no_perms):
return HttpResponseForbidden(content="Forbidden.")
else:
return serve(request, path, document_root, show_indexes)