Django-rest-framework: Los permisos de objetos no se verifican en rutas de conjuntos de vistas personalizadas

Creado en 23 may. 2016  ·  4Comentarios  ·  Fuente: encode/django-rest-framework

pasos para reproducir

class MyViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MySerializer
    authentication_classes = (MyAuth, )
    permission_classes = (MyPermissions, )

    @detail_route(methods=["GET", ])
    def custom(self, request, pk=None):
        return Response('whatever')

from rest_framework import routers
router = routers.SimpleRouter() 
router.register('mymodel', MyViewSet)
urlpatterns = [
    url(r'^api/', include(router.urls)),
]

hacer una solicitud GET a / api / mymodel / 123 / custom /

Comportamiento esperado

has_object_permission () debe llamarse con MyModel.objects.get(pk=123) como objeto.

Comportamiento real

la solicitud a la ruta personalizada en forma de / api / mymodel / 123 / custom / llamará a has_permission () en MyPermissions, pero no a has_object_permission () aunque es una ruta detallada.

Documentation

Comentario más útil

Necesitamos documentar el hecho de que solo recibirá la llamada has_object_permission solo si llama a get_object .

Todos 4 comentarios

Necesitamos documentar el hecho de que solo recibirá la llamada has_object_permission solo si llama a get_object .

Esto parece contrario a la intuición. Las llamadas como / api / object / 123 / method / generalmente se usan para llamar a algún método en la instancia del objeto con ID 123 y parece que verificar el permiso del objeto sería un comportamiento esperado. De lo contrario, cada vez que alguien haga rutas detalladas personalizadas, tendría que recuperar el objeto, verificar manualmente los permisos y continuar. En ese punto, llamar a has_object_permission () no tiene sentido de todos modos. Entonces, en cada escenario donde se usan permisos a nivel de objeto, se tendría que usar un texto repetitivo como este

class CustomPermission(BasePermission):
    def has_permission(self, request, view):
        """we need to do all permission checking here, since has_object_permission() is not guaranteed to be called"""
        if 'pk' in view.kwargs and view.kwargs['pk']:
            obj = view.get_queryset()[0]
            # check object permissions here
        else:
            # check model permissions here

    def has_object_permission(self, request, view, obj):
        """ nothing to do here, we already checked everything, so ignore """
        return True

Creo que lo entiendo ahora. Si llamo a get_object () en mis rutas personalizadas, se llamará a has_object_permission (). Todavía parece contrario a la intuición, pero al menos hay una solución clara.

Me complacería considerar una solicitud de extracción concreta para la documentación, pero tal como está, creo que lo que tenemos es adecuado en http://www.django-rest-framework.org/api-guide/permissions/ #object -level -permissions

Cerrando esto, pero como se señaló, se podría considerar una reformulación / adiciones específicas.

¿Fue útil esta página
0 / 5 - 0 calificaciones