Files
trustme/core/apps/contracts/views/owners.py

128 lines
5.0 KiB
Python

import uuid
from typing import cast
from django_core.mixins import BaseViewSetMixin # type: ignore
from django.utils.translation import gettext as _
from drf_spectacular.utils import extend_schema
from rest_framework.exceptions import PermissionDenied # type: ignore
from rest_framework.permissions import AllowAny, IsAdminUser # type: ignore
from rest_framework.viewsets import ModelViewSet # type: ignore
from rest_framework.request import HttpRequest # type: ignore
from rest_framework.response import Response # type: ignore
from rest_framework import status # type: ignore
from rest_framework.generics import GenericAPIView # type: ignore
from rest_framework.parsers import MultiPartParser, FormParser # type: ignore
from rest_framework.generics import get_object_or_404 # type: ignore
from core.utils.views import BaseApiViewMixin
from core.apps.contracts.models import (
ContractOwnerModel,
ContractAttachedFileModel,
)
from core.apps.contracts.serializers import (
CreateContractOwnerSerializer,
ListContractOwnerSerializer,
RetrieveContractOwnerSerializer,
UpdateContractOwnerSerializer,
DestroyContractOwnerSerializer,
CreateContractFileContentFromOwnerSerializer,
)
###################################################################################
# @view-set | ALL - /contract-owners
###################################################################################
@extend_schema(tags=["Contract Owners"])
class ContractOwnerViewSet(BaseViewSetMixin, ModelViewSet):
queryset = ContractOwnerModel.objects.all()
serializer_class = ListContractOwnerSerializer
permission_classes = [AllowAny]
action_permission_classes = {
"list": [IsAdminUser],
"retrieve": [IsAdminUser],
"create": [IsAdminUser],
"update": [IsAdminUser],
"destroy": [IsAdminUser],
}
action_serializer_class = { # type: ignore
"list": ListContractOwnerSerializer,
"retrieve": RetrieveContractOwnerSerializer,
"create": CreateContractOwnerSerializer,
"update": UpdateContractOwnerSerializer,
"destroy": DestroyContractOwnerSerializer,
}
###################################################################################
# @api-view | DELETE - /contract-owners/{owner_id}/files/{file_id}
###################################################################################
@extend_schema(tags=["Contract Files"])
class ContractOwnerAttachedFileApiView(BaseApiViewMixin, GenericAPIView): # type: ignore
permission_classes = [AllowAny]
serializer_class = ListContractOwnerSerializer
queryset = ContractOwnerModel.objects.all()
method_permission_classes = {"delete": [AllowAny]}
method_serializer_class = {}
@extend_schema(
summary="Delete a file from contract",
description="Deletes a contract-attached file if contract allows file deletion.",
)
def delete(
self,
request: HttpRequest,
owner_id: uuid.UUID,
file_id: uuid.UUID,
*args: object,
**kwargs: object
) -> Response:
owner = get_object_or_404(
ContractOwnerModel.objects.all().select_related("contract"), pk=owner_id
)
if not owner.contract.allow_delete_files:
raise PermissionDenied(_("Deleting attached files was restricted for this contract"))
file = get_object_or_404(
ContractAttachedFileModel.objects.all().select_related("contract"), pk=file_id
)
if owner.contract.pk != file.contract.pk:
raise PermissionDenied(_("Contract have no such file attached"))
file.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
###################################################################################
# @api-view | POST - /contract-owners/{owner_id}/files/{file_id}/upload
###################################################################################
@extend_schema(tags=["Contract File contents"])
class UploadFileContentApiView(BaseApiViewMixin, GenericAPIView): # type: ignore
permission_classes = [AllowAny]
parser_classes = [MultiPartParser, FormParser] # type: ignore
method_permission_classes = {"post": [AllowAny]}
method_serializer_class = {"post": CreateContractFileContentFromOwnerSerializer}
@extend_schema(
summary="Uploads a file for contract attached files",
description="Creates a file for contract attached files.",
)
def post(
self,
request: HttpRequest,
owner_id: uuid.UUID,
file_id: uuid.UUID,
*args: object,
**kwargs: object
) -> Response:
serializer_context = dict(file_id=file_id, contract_owner_id=owner_id)
serializer = cast(
CreateContractFileContentFromOwnerSerializer,
self.get_serializer(data=request.data, context=serializer_context) # type: ignore
)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)