3

I'm trying to check permissions for some API requests. I've already set auth users and auth_user_user_permissions and auth_permissions tables like view_company add_company bla bla, but the problem is not that. The problem is when I'm trying yo use decorator which

@permission_required('API.view_company', raise_exception=True)

it said to me

AttributeError: 'CompanyDetailView' object has no attribute 'user'

Most probably it's looking for the user because its gonna check user_permission is it available to view companies or not but my view which I declared in urls.py (path('companies//', CompanyDetailView.as_view()),) has not have user object that's why error message returned attribute error, how can I solve this, thanks a lot

I tried to set example user in view class, in the beginning, it worked because view was looking for user object, i can not use that way because every request has different user

import rest_framework
from rest_framework import status
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.auth.decorators import permission_required

class CompanyDetailView(APIView):
    @permission_required('api.view_company', raise_exception=True)
    def get(self, request, id):
        try:
            request_data = {}
            request_data['request_method'] = request.method
            request_data['id'] = id
            companies = Company.objects.get(id=id)
            status = rest_framework.status.HTTP_200_OK
            return Response(companies, status)

bla bla bla

url line was =

path('companies/<int:id>/', CompanyDetailView.as_view()),

my error message was : AttributeError: 'CompanyDetailView' object has no attribute 'user'

when i debug and i see request.user.has_perm('view_company')returned false but still api give responses, it suppose to say you are not allow to view companies

kaanozbudak
  • 53
  • 1
  • 6
  • share the model of `Company` – Usman Maqbool Sep 25 '19 at 13:03
  • from django.db import models from api.models.base import BaseModel class Company(BaseModel): name = models.CharField(max_length=50, null=True) code = models.CharField(max_length=5, null=True, unique=True) is_active = models.BooleanField(default=True) – kaanozbudak Sep 25 '19 at 13:04
  • if you say add user relational to your company model, i can not. It suppose to check request user, because the main purpose is, x person request that api with get method, is this x person is able to see or not, the important thing is x person's user permissions – kaanozbudak Sep 25 '19 at 13:06

3 Answers3

3

You can't easily use django permissions with django rest framework.

there is a tutorial about django-rest-framework permissions at:

https://www.django-rest-framework.org/api-guide/permissions/

Bastian
  • 10,403
  • 1
  • 31
  • 40
  • Thank you, still should i set my decorator before my def get – kaanozbudak Sep 25 '19 at 13:27
  • no .. the decorator is not longer necessary then. but I think my answer is not correct because it is about plain django views, not about django rest framework – Bastian Sep 25 '19 at 13:29
  • im sorry, still does not work for me as ``` permission_classes = [IsAuthenticated] raise_exception = True permission_required = ('api.view_company', 'api.add_company') ``` and also i used CompanyDetailView(APIView, PermissionRequiredMixin) – kaanozbudak Sep 25 '19 at 13:39
  • when i debug and i see request.user.has_perm('view_company') returned false but still api give responses, it suppose to say you are not allow to view companies – kaanozbudak Sep 25 '19 at 13:43
3

The mechanism of Django Views and Django Rest Framework Views are a bit different, that's why you've got that error message. permission_required will try to access user field of your view to check user permission using has_perm method. But APIView didn't have user field inside of it.

To get rid of this, you might want to use permissions which provided by Django Rest Framework to restrict the access.

But if you still want to use built-in permission of Django to restrict the access to your view, you could create a Permission class which will use has_perm to check user permission. Like so:

from rest_framework import permissions
from rest_framework import exceptions

class ViewCompanyPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        if not request.user.has_perm('api.view_company'):
            raise exceptions.PermissionDenied("Don't have permission")
        return True

and use it on your view via permission_classes field:

class CompanyDetailView(APIView):
    permission_classes = (ViewCompanyPermission, )
    def get(self, request, id):
        try:
            request_data = {}
            request_data['request_method'] = request.method
            request_data['id'] = id
            companies = Company.objects.get(id=id)
            status = rest_framework.status.HTTP_200_OK
            return Response(companies, status)

In case you want to replicas the permission_required behavior, you could do something like this:

from rest_framework import permissions
from rest_framework import exceptions

def permission_required(permission_name, raise_exception=False):
    class PermissionRequired(permissions.BasePermission):
        def has_permission(self, request, view):
            if not request.user.has_perm(permission_name):
                if raise_exception:
                    raise exceptions.PermissionDenied("Don't have permission")
                return False
            return True
    return PermissionRequired

Then you can use it like:

class CompanyDetailView(APIView):
    permission_classes = (permission_required("api.view_company", raise_exception=True), )
    # ...
Toan Quoc Ho
  • 3,266
  • 1
  • 14
  • 22
1

Based on the description permission_required this decorator should be used for a function view, where first argument is request and you try to apply it for the class method where the first argument is self in your case instanse of the CompanyDetailView so you get the error. And you should use another way to check the permissions.

You can read some examples in here: decorators-on-django-class-based-views

Brown Bear
  • 19,655
  • 10
  • 58
  • 76
  • First, thanks a lot, actually i saw that questions and answers but i guess my situation different from login required things. I'm already checked is logged in or not with token control system, every request has to came with spesific token and they can get token when they post their credentials to /auth_token url. My problem with using @permission_required decorator – kaanozbudak Sep 25 '19 at 13:24