Why does full=true breaks resources behaviour in Django Tastypie?

不想你离开。 提交于 2020-01-03 04:25:12

问题


Using full=trueon related fields is very convenient feature to prevent client from doing too many requests to get necessary information.

Nevertheless, I really don't understand why the "instructions" in Meta Class are not followed as soon as you use a related field.

Here is a simple example:

class UserResource(ModelResource):
    class meta():
        queryset = User.objects.all()
        resource_name = 'users'
        authorization = NothingAuthorization() # Returns None or [] on GET requests

class ClientUserResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user', full=True)

    class meta():
        queryset = ClientUser.objects.all()
        resource_name = 'client_users'
        # Some other required fields

Then,

  • a GET request on /users/1 returns a 401 response (just as expected, perfect!)
  • a GET request on /client_users/1 (client_user 1 is related to user 1) returns the data of client_user 1 AND the data of user 1 (I didn't expect to get user 1 information since it's unauthorised.)

Note that I got the same behaviour with allowed_methods, validation, etc. This behaviour is a burden to me since it forces me to remove full=true everywhere to avoid security holes.

What am I doing wrong?


回答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).



来源:https://stackoverflow.com/questions/22909483/why-does-full-true-breaks-resources-behaviour-in-django-tastypie

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!