title: Django Rest Framework: Permissions based on Object Attributes/Ownership
body: <p>I'd like to allow users to create and view resources, but only if:</p>
  
  <ol>
  <li>They are staff OR</li>
  <li>They are the 'owner' of the object they're trying to create/view</li>
  </ol>
  
  <p>I've got read-only permissions worked out fine, since users only have permission to get lists of objects when their primary key is used to generate the viewset.  For example: GET /api/users/1/notes returns just the notes for the user with pk=1.</p>
  
  <p>However, in testing, I discovered that users can create an object 'owned' by another user by posting it to their own list endpoint.  For example user 1 can send a POST to /api/users/1/notes, but specify the note data as {user: "<a href="http://host.tld/users/2/" rel="noreferrer">http://host.tld/users/2/</a>", text: "Look! I created a note in another person's account!"}</p>
  
  <p>I've got a fix below that seems to work fine, though I get the feeling I'm swimming against the current.  Right now, within a custom permission, I create an instance of the object that would be created and check that its owner is the user making the request.</p>
  
  <p><strong>Is there a cleaner way of doing this?</strong></p>
  
  <p>Current Fix:</p>
  
  <pre><code>def has_permission(self, request, view):
      if request.user.is_staff:
          return True
      elif request.method in permissions.SAFE_METHODS:
          # check that the user is looking for their own list
          return request.user == User.objects.get(pk=view.kwargs['user_pk'])
      elif request.method not in permissions.SAFE_METHODS:
          # the user can create/modify the object if the new object's user == the request user
          # roundabout way of figuring this out... probably a better way
          user_path = request.POST['user'].split(request.get_host())[1]
          func = resolve(user_path).func
          kwargs = resolve(user_path).kwargs
          user_for_object = func.cls.model.objects.get(pk=kwargs['pk'])
          return user_for_object == request.user
      else:
          return False
  </code></pre>