9

I am using the Django REST framework with the nested router extension. One of my routes looks like: companies/$company/locations/$location where $company and $location are slug variables.

I want to allow users to POST to this URL: companies/$company/locations/ to add new locations. I want to make sure that the user doing the POST has the correction permissions for the company he is POSTing to. I currently use django-guardian for my object level permissions. The POST message contains only the name of the new location it does not contain the name of the company as that can be inferred from the URL. I am having a hard time correctly enforcing the permissions in this case. I had been setting the company field of the new Location object from the viewset's pre_save method but this is too late for the permission check to be applied.

What is the best way to enforce this?

In the case there the user does include the company in the POST, I can validate the company by adding the following to the viewset:

def get_queryset(self):
    parent = super(LocationViewSet, self).get_queryset()    
    return parent.filter(company__slug=self.kwargs['company_slug'])
Alex Rothberg
  • 10,243
  • 13
  • 60
  • 120

1 Answers1

0

Well, I actually found a rather ugly way to do this, retrieving the parent object and checking it's belonging against request's user.

def create(self, request, *args, **kwargs):
    request.data['catspad'] = kwargs['catspad_pk']
    if not Catspad.objects.get(id=kwargs['catspad_pk']).owner == request.user:
        return Response(status=HTTP_401_UNAUTHORIZED)
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=HTTP_201_CREATED, headers=headers)
Maxime B
  • 966
  • 1
  • 9
  • 30