Source code for ox.apps.files.views

from pathlib import Path
from uuid import UUID

from django.core.exceptions import PermissionDenied
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from django.http import HttpResponse, Http404, FileResponse

from caps.views import OwnedViewSet, AccessViewSet
from caps.views.mixins import SingleOwnedMixin, OwnedPermissionMixin

from ox.core.conf import ox_settings
from ox.apps.content.views import MessageViewSet
from . import filters, serializers, tasks
from .models import Folder, File, FolderComment, FileComment


__all__ = ("FolderViewSet", "FolderAccessViewSet", "FileViewSet", "FileAccessViewSet")


class ServeFileView(SingleOwnedMixin, OwnedPermissionMixin, SingleObjectMixin, View):
    """Serve protected file to user, checking access permission."""

    model = File

    preview: bool = False
    """ Serve preview instead of file. """

    def get(self, request, uuid: str | UUID, *args, **kwargs):
        self.object = self.get_object()
        if not request.user.has_perm("ox_files.view_file", self.object):
            raise PermissionDenied("You don't have access to this file.")

        if self.preview:
            field = self.object.preview
        else:
            field = self.object.file

        if not Path(field.path).exists():
            raise Http404(f"The file {self.object.name} does not exists on the filesystem.")

        match ox_settings.HTTP_SERVER_BACKEND:
            case "nginx":
                response = HttpResponse()
                response["X-Accel-Redirect"] = ox_settings.protected_media_url(field.name)
            case "apache":
                response = HttpResponse()
                response["X-Sendfile"] = field.path

            case _:
                response = FileResponse(open(field.path, "rb"))

        response["Content-Disposition"] = f'inline; filename="{self.object.name}"'
        return response


[docs] class FolderViewSet(OwnedViewSet): queryset = Folder.objects.all().order_by("-updated") serializer_class = serializers.FolderSerializer filterset_class = filters.FolderFilterSet search_fields = ["path"]
[docs] class FolderAccessViewSet(AccessViewSet): queryset = Folder.Access.objects.all()
[docs] class FileViewSet(OwnedViewSet): # FIXME: permission to add file to a folder queryset = File.objects.all().order_by("-updated") serializer_class = serializers.FileSerializer filterset_fields = { "uuid": ["exact", "in"], "owner__uuid": ["exact"], "folder__uuid": ["exact"], "name": ["exact", "icontains"], } search_fields = ["name", "folder__path"] def perform_create(self, ser): super().perform_create(ser) ser.instance.read_mime_type() tasks.create_preview.enqueue(uuid=str(ser.instance.uuid)) def perform_update(self, ser): if ser.validated_data.get("file_data"): ser.instance.clear_files() super().perform_update(ser) tasks.create_preview.enqueue(uuid=str(ser.instance.uuid))
[docs] class FileAccessViewSet(AccessViewSet): queryset = File.Access.objects.all()
class FolderCommentViewSet(MessageViewSet): queryset = FolderComment.objects.all().order_by("-created") serializer_class = serializers.FolderCommentSerializer class FileCommentViewSet(MessageViewSet): queryset = FileComment.objects.all().order_by("-created") serializer_class = serializers.FileCommentSerializer