Search code examples
pythondjangotastypie

How do I limit the user API response to the current user with Django Tastypie?


I'm trying to use Django Tastypie to create a simple API. I have custom auth (not really that custom since it's copied directly from their example) that exposes only entries from the current user. It returns all users though, and I only want it to expose the one that's logged on. Right now I'm using this as my api.py:

class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        excludes = ['password', 'is_superuser']
        resource_name = 'user'
       authentication=MultiAuthentication(SessionAuthentication(),ApiKeyAuthentication())
        authorization=DjangoAuthorization()
        allow_methods=['get']

class EntryResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user')
    class Meta:
        queryset = Entry.objects.all()
        resource_name = 'entry'
        authentication=MultiAuthentication(SessionAuthentication(),ApiKeyAuthentication())
        authorization=UserObjectsOnlyAuthorization()

And this for the UserObjectsOnlyAuthorization

from tastypie.authorization import Authorization
from tastypie.exceptions import Unauthorized


class UserObjectsOnlyAuthorization(Authorization):
    def read_list(self, object_list, bundle):
        # This assumes a ``QuerySet`` from ``ModelResource``.
        return object_list.filter(user=bundle.request.user)

    def read_detail(self, object_list, bundle):
        # Is the requested object owned by the user?
        return bundle.obj.user == bundle.request.user

    def create_list(self, object_list, bundle):
        # Assuming they're auto-assigned to ``user``.
        return object_list

    def create_detail(self, object_list, bundle):
        return bundle.obj.user == bundle.request.user

    def update_list(self, object_list, bundle):
        allowed = []

        # Since they may not all be saved, iterate over them.
        for obj in object_list:
             if obj.user == bundle.request.user:
                allowed.append(obj)

        return allowed

    def update_detail(self, object_list, bundle):
        return bundle.obj.user == bundle.request.user

    def delete_list(self, object_list, bundle):
        # Sorry user, no deletes for you!
        raise Unauthorized("Sorry, no deletes.")

    def delete_detail(self, object_list, bundle):
        raise Unauthorized("Sorry, no deletes.")

If I apply that Authentication to the UserResource in api.py, like I am for the EntryResource it gives me errors. I can provide more detail if necessary.


Solution

  • You should define your filter in a new CustomUserAuthorization, check the details of this implementation and check the Tastypie documentation about Authorization.

    from tastypie.authorization import Authorization
    from tastypie.exceptions import Unauthorized
    
    
    class CustomUserAuthorization(Authorization):
        def read_list(self, object_list, bundle):
            # This you put your filter
            return object_list.filter(id=bundle.request.user.id)
    
        def read_detail(self, object_list, bundle):
            # This is to check the current user
            return bundle.obj.id == bundle.request.user.id
    
        def create_list(self, object_list, bundle):
            raise Unauthorized("Sorry, not allowed.")
    
        def create_detail(self, object_list, bundle):
            raise Unauthorized("Sorry, not allowed.")
    
        def update_list(self, object_list, bundle):
            raise Unauthorized("Sorry, not allowed.")
    
        def update_detail(self, object_list, bundle):
            # Only update your details
            return bundle.obj.id== bundle.request.user.id
    
        def delete_list(self, object_list, bundle):
            raise Unauthorized("Sorry, no deletes.")
    
        def delete_detail(self, object_list, bundle):
            raise Unauthorized("Sorry, no deletes.")