[Answer]-Why does full=true breaks resources behaviour in Django Tastypie?

1đź‘Ť

What do you expect Tastypie to do in that case? I suppose you would like to see a 401 Unauthorized to your ClientUserResource GET, but in my opinion this would be rather inconsistent. You are specifying that ClientUserResource has no explicit Authorization defined (and thus free GET access) but following your logic you would like to see the response according to another resource’s authorization.

If you want to avoid security holes, it would be best indeed to not use full=True. You could overwrite the hydrate method to return the expanded object or not according to the rules you want, or use a similar Authentication class for ClientUserResource that takes into consideration the rules of UserResource (in this case full=True would be ok as you are controlling the full resource access).

EDIT: My two proposed solutions with more detail.

1. Same authorization

With this I mean that, if you want to protect your related resource while using full=True, you should use the same authorization in both resources (or a more strict authorization in ClientUserResource so your UserResource never gets leaked). In fact, I can’t think of a case in which you would like to have two complete distinct authorization logics and then include one resource inside of another.

In your example, you should add authorization = NothingAuthorization(). If you really want a different authentication behavior for the second class let’s see another option.

2. Overwrite dehydrate method or obj_create

In this case, you should delete the full=True and provide that behavior yourself, by for instance overwriting the dehydrate method. In this method you have access to your request and data so you can perform some logic.

class ClientUserResource(ModelResource):

    class meta():
        queryset = ClientUser.objects.all()
        resource_name = 'client_users'

    def dehydrate(self, bundle):
        # Do whatever you want, for instance, authorize only one user, and then add
        # to the result your desired info as full=True would do
        if bundle.request.user.username == "admin":
            bundle.data['user'] = {'username': "admin",
                                   'email': "admin@gmail.com", 
                                   ...}}
        return bundle

This can look kind of “ugly”, as you are not using any Authorization class in your resource that provides the authorization logic. I suppose you could build in the dehydrate method a UserResource along with the request and test there the authorization, but I think it gets more and more complicated for the strange behavior we are expecting here (different authentication models for two resources which are very coupled).

Leave a comment