Aitch
Aitch

Reputation: 942

tastypie - where to restrict fields that may be updated by PATCH?

I have a working GET / tastypie (read-only) solution.

I've allowed PUT/PATCH requests and been successful in PATCHING a record.

However I want to limit PATCH capability to only certain fields, on appropriate modelresources, for (already) authenticated and authorised users. I still want users to be able to GET (see) all fields.

Where is the best place (method?) to achieve this sort of restriction?

Docs: https://django-tastypie.readthedocs.org/en/latest/interacting.html?highlight=patch#partially-updating-an-existing-resource-patch

Upvotes: 3

Views: 2332

Answers (2)

Marco Fucci
Marco Fucci

Reputation: 1854

A bit late but maybe this will help somebody.

My solution was to override update_in_place and check for the data passed.

from tastypie.resources import ModelResource
from tastypie.exceptions import BadRequest


class MyResource(ModelResource):
    class Meta:
        ...
        allowed_update_fields = ['field1', 'field2']

    def update_in_place(self, request, original_bundle, new_data):
        if set(new_data.keys()) - set(self._meta.allowed_update_fields):
            raise BadRequest(
                'Only update on %s allowed' % ', '.join(
                    self._meta.allowed_update_fields
                )
            )

        return super(MyResource, self).update_in_place(
            request, original_bundle, new_data
        )

Upvotes: 13

jordanvg
jordanvg

Reputation: 96

Since you seem to have authorization for users in place already, you should be able to implement this by adding to the Meta class in your ModelResource. For example, using the DjangoAuthorization (from tastypie docs):

from tastypie.authentication import BasicAuthentication
from tastypie.authorization import DjangoAuthorization
...

class SomeResource(ModelResource):
  ...
  class Meta:
    ...
    authentication = BasicAuthentication()
    authorization = DjangoAuthorization()

This example would give you user authorization for actions as defined in django.contrib.auth.models.Permission.

I also had this from the tastypie Google Group. It uses the dehydrate method. Here is the example provided in the Google Groups link:

def dehydrate(self, bundle): 
 bundle = super(self, MyResource).dehydrate(bundle) 

 # exclude the restricted field for users w/o the permission foo 
 if not bundle.request.user.has_perm('app.foo'): 
     del bundle.data['restricted'] 

 return bundle 

Upvotes: 1

Related Questions