8

I'm using Django 2.0 and Django RESET Framework to write REST API for my application.

I have configured following authentication methods

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
}

As of now, It allows all authenticated users to access web api view.

What I want is to allow few users (probably superadmin users) to be able to access API from Session Authentication or from web browser by logging in.

Edit 2: contacts/views.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated,)

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)
Anuj TBE
  • 9,198
  • 27
  • 136
  • 285

3 Answers3

12

For Django 2 (Added in views.py)

from rest_framework.permissions import IsAdminUser

class IsSuperUser(IsAdminUser):
    def has_permission(self, request, view):
        return bool(request.user and request.user.is_superuser)

class ListSmth(ListCreateAPIView):
    permission_classes = (IsSuperUser,)
    ... Your code...
Igor Tischenko
  • 620
  • 9
  • 20
  • It would be better to inherit from `rest_framework.permissions.BasePermission` rather than `rest_framework.permissions.IsAdminUser` – Mukesh Sai Kumar Aug 02 '20 at 07:50
4

There is already inbuilt class called IsAdminUser, specify it as values to permission_classes property

from rest_framework.permissions import  IsAdminUser
     class A:
       permission_classes = (IsAdminUser,)

this checks for the value

reques.user.isStaff == True
niran
  • 1,920
  • 8
  • 34
  • 60
3

So you can leverage permission_classes to do this. DRF's Request object remembers the authentication method that was used in an attribute called _authenticator. You can use this; and use the permission_classes to determine if the pair of (user, authenticator) has permission

class AdminAuthenticationPermission(permissions.BasePermission):
    ADMIN_ONLY_AUTH_CLASSES = [rest_framework.authentication.BasicAuthentication, rest_framework.authentication.SessionAuthentication]

    def has_permission(self, request, view):
        user = request.user
        if user and user.is_authenticated():
            return user.is_superuser or \
                not any(isinstance(request._authenticator, x) for x in self.ADMIN_ONLY_AUTH_CLASSES) 
        return False

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

Untested: but should work

rtindru
  • 5,107
  • 9
  • 41
  • 59
  • 1
    great it's working. only little modification is required. remove `()` from `is_authenticated()`. rest is good – Anuj TBE May 14 '18 at 15:36
  • Great to hear! That's a change in Django 1.10 I think; I am more used to 1.9 *Old habits* https://docs.djangoproject.com/en/2.0/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods – rtindru May 14 '18 at 15:38
  • 1
    Yes, I had used the same thing in version earlier to 1.10. But it will return `TypeError: 'bool' object is not callable` on `2.0` – Anuj TBE May 14 '18 at 15:40
  • I'd recommend updating your question to reflect the real underlying question and the corresponding answer for better future reference. – rtindru May 14 '18 at 15:41
  • Remove `()` from end of `user.is_authenticated()` to fix TypeError @AnujTBE – Mojtaba Arvin Jan 13 '19 at 10:14