Hi All.

I figure this must be a usage thing rather than a bug, though it does seem 
related to https://github.com/encode/django-rest-framework/pull/2933. For 
the record I'm using DRF 3.6.2.

I have a view set for a model that has object level permissions. I want 
authenticated users to be able to read details for a specified model, but 
otherwise want object level permissions enforced.

I've tried a three ways of doing this:
1) overriding get_permissions,
2) implementing a custom permission object, and,
3) overriding check_permissions and check_object_permissions.

The result in each case is the same. With the appropriate code in place the 
authenticated user sees a 404 error rather than a serialization of the 
object.

The problem seems to be changes that are made to the view and request in 
the method override_method called after rendering of the response is called 
(Up till this point the response is determined correctly). These changes 
make the code below return the wrong responses for object permissions when 
they are checked during render in show_form_for_method. 

In all three cases I've been relying on view.action to determine if a 
retrieve has been requested. This action is changed in override_method. I 
could probably use request.method, but override_method seems to change this 
from GET to POST.

What is the correct way to provide different permissions for a get as 
opposed to a post in a view set? So that the effects of override_method are 
ignored? Is there someway to check for the cached request or view?


Examples:
Case 2:
The view set uses the following custom permissions
class CustomObjectPermissions(permissions.DjangoObjectPermissions):         
                                                                            
       
    perms_map = {                                                           
                                                                       
        'GET': ['%(app_label)s.view_%(model_name)s'],                       
            
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],                   
            
        'HEAD': ['%(app_label)s.view_%(model_name)s'],                     
             
        'POST': ['%(app_label)s.add_%(model_name)s'],                       
                                                                            
      
        'PUT': ['%(app_label)s.change_%(model_name)s'],                     
                                                                            
      
        'PATCH': ['%(app_label)s.change_%(model_name)s'],                   
                                                                            
      
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],                 
                                                                            
        
    }

class CustomTransactionObjectPermissions(CustomObjectPermissions):         
          
                                                                            
         
    def has_permission(self, request, view):          
        if view.action == "retrieve":                                       
         
            return permissions.DjangoModelPermissions().has_permission(
request, view)
        return super().has_permission(request, view)                       
          
                                                                            
         
    def has_object_permission(self, request, view, obj):                   
          
        if view.action == "retrieve":                                       
         
            return permissions.DjangoModelPermissions().
has_object_permission(request, view, obj)
        return super().has_object_permission(request, view, obj)

For case 3:
The view set implements the following methods 
   def check_permissions(self, request):                                   
            
        if self.action != "retrieve":      
            if not permissions.CustomObjectPermissions().has_permission(   
             
                request,                                                   
             
                self                                                       
             
            ):                                                             
             
                return self.permission_denied(request)                     
             
        if not rest_framework.permissions.DjangoModelPermissions().
has_permission(   
            request,                                                       
             
            self                                                           
             
        ):                                                                 
             
            return self.permission_denied(request)                         
             
                                                                            
            
    def check_object_permissions(self, request, obj):                       
            
        if self.action == "retrieve":
            if not permissions.CustomObjectPermissions().
has_object_permission(         
                request,                                                   
             
                self,                                                       
            
                obj                                                         
            
            ):                                                             
             
                return self.permission_denied(request)


-- 
You received this message because you are subscribed to the Google Groups 
"Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to