diff --git a/program/utils.py b/program/utils.py index 53b6420d1b95bc99e98df51ac8e905e0d073eeff..305f657cc6212fa77eae3bf34a215b2a6cf88139 100644 --- a/program/utils.py +++ b/program/utils.py @@ -109,14 +109,20 @@ def get_values( return int_if_digit(values[0]) -def get_pk_and_slug(kwargs: Dict[str, str]) -> Tuple[Optional[int], Optional[str]]: - """Get the pk and the slug from the kwargs.""" +class DisabledObjectPermissionCheckMixin: + """ + At the time of writing permission checks were entirely circumvented by manual + queries in viewsets. To make code refactoring easier and allow + the paced introduction of .get_object() in viewsets, object permission checks + need to be disabled until permission checks have been refactored as well. - pk, slug = None, None + Object permissions checks should become mandatory once proper permission_classes + are assigned to viewsets. This mixin should be removed afterwards. + """ - try: - pk = int(kwargs["pk"]) - except ValueError: - slug = kwargs["pk"] + # The text above becomes the viewset’s doc string otherwise and is displayed in + # the generated OpenAPI schema. + __doc__ = None - return pk, slug + def check_object_permissions(self, request, obj): + pass diff --git a/program/views.py b/program/views.py index f28c0c3ef6303449a86993ff71247a0d19acfc01..0f4503be1a89452076b6225ebaa17f517a009c86 100644 --- a/program/views.py +++ b/program/views.py @@ -59,7 +59,7 @@ from program.serializers import ( TypeSerializer, UserSerializer, ) -from program.utils import get_pk_and_slug, get_values, parse_date +from program.utils import DisabledObjectPermissionCheckMixin, get_values, parse_date logger = logging.getLogger(__name__) @@ -270,7 +270,7 @@ class APIUserViewSet( return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) -class APIShowViewSet(viewsets.ModelViewSet): +class APIShowViewSet(DisabledObjectPermissionCheckMixin, viewsets.ModelViewSet): """ Returns a list of available shows. @@ -283,6 +283,19 @@ class APIShowViewSet(viewsets.ModelViewSet): pagination_class = LimitOffsetPagination filterset_class = filters.ShowFilterSet + def get_object(self): + queryset = self.filter_queryset(self.get_queryset()) + lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field + lookup_arg = self.kwargs[lookup_url_kwarg] + # allow object retrieval through id or slug + try: + filter_kwargs = {self.lookup_field: int(lookup_arg)} + except ValueError: + filter_kwargs = {"slug": lookup_arg} + obj = get_object_or_404(queryset, **filter_kwargs) + self.check_object_permissions(self.request, obj) + return obj + def create(self, request, *args, **kwargs): """ Create a show. @@ -301,23 +314,6 @@ class APIShowViewSet(viewsets.ModelViewSet): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - def retrieve(self, request, *args, **kwargs): - """Returns a single show""" - - pk, slug = get_pk_and_slug(self.kwargs) - - show = ( - get_object_or_404(Show, pk=pk) - if pk - else get_object_or_404(Show, slug=slug) - if slug - else None - ) - - serializer = ShowSerializer(show) - - return Response(serializer.data) - def update(self, request, *args, **kwargs): """ Update a show. @@ -332,7 +328,7 @@ class APIShowViewSet(viewsets.ModelViewSet): ): return Response(status=status.HTTP_401_UNAUTHORIZED) - show = get_object_or_404(Show, pk=pk) + show = self.get_object() serializer = ShowSerializer( show, data=request.data, context={"user": request.user} ) @@ -356,9 +352,7 @@ class APIShowViewSet(viewsets.ModelViewSet): if not request.user.is_superuser: return Response(status=status.HTTP_401_UNAUTHORIZED) - pk = get_values(self.kwargs, "pk") - - Show.objects.get(pk=pk).delete() + self.get_object().delete() return Response(status=status.HTTP_204_NO_CONTENT)