Django REST Framework: restrict data records access to the users created them

3.8k views Asked by At

I'm trying to figure out, what is the best way to manage model access permissions with Django.

I have a table of items which belong to the users created them. All the items a managed via a RESTful API. When using this API I want to limit access to the items created by a given user.

Do I have to create several tables or is it possible to achieve the same with just one table? If I have to use multiple tables, how do I correlate API requests with a particular table?

4

There are 4 answers

1
Nikolay Derkach On BEST ANSWER

Ok, I found a way to do it via both API and admin. This basically resembles Rob's idea.

First of all, every time I create a new user via admin panel, I need to append a user to my items:

class MyAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if getattr(obj, 'user', None) is None:
            obj.user = request.user
        obj.save()

admin.site.register(MyItem, MyAdmin)

Then when accessing my model, I just filter by user (which is btw a foreign key to django.contrib.auth.models.User):

MyItem.objects.filter(user=request.user)

Finally to make it work with Django REST Framework, I need to add a couple of methods to My custom ModelViewSet:

class MyItemViewSet(viewsets.ModelViewSet):
    model = MyItem
    serializer_class = MyItemSerializer

    def get_queryset(self):
        return MyItem.objects.filter(user=self.request.user)

    def pre_save(self, obj):
        obj.user = self.request.user

I've used documentation and (lots) trial and error to figure this out.

0
krs On

if you want generic object-level permissions then you can use a permission backend like django-guardian, here is examples for integrating with django-restframework

1
Rob L On

You could have a created_by field on your objects. Then compare the django user to that. It's a little difficult help further without a concrete example.

0
Little Brain On

Using django-rest-framework and django-rest-auth, I had to perform additional steps as described in the answer by Lucas Weyne to this question.

Here's what he suggested that worked for me.

Make sure to include the authorization token in the request:

curl -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" <url>

This is key because otherwise the server doesn't know who the user is.

Add this to your viewset definition:

permission_classes = [permissions.IsAuthenticated, ]

This is important if the query is user dependent.