I've got an endpoint built with Django Rest Framework, to which I now want to add permissions so that only users belonging to a certain group can access an endpoint. So I'm using token based access and inspired by this example I'm trying to use the following code:
class ReadPermission(BasePermission):
def has_permission(self, request, view):
return request.user.groups.filter(name=settings.GROUP_POST_DATA).exists()
class MyEndpoint(mixins.ListModelMixin, viewsets.GenericViewSet):
permission_classes = [IsAuthenticated, ReadPermission]
http_method_names = ['get']
# etc
But unfortunately I get anAttributeError: 'User' object has no attribute 'groups'
Why doesn't the user object have groups?
With Django, you can create groups to class users and assign permissions to each group so when creating users, you can just assign the user to a group and, in turn, the user has all the permissions from that group. To create a group, you need the Group model from django. contrib. auth.
Seems like you're not using or inheriting from the default Django User
model (or the AbstractUser
) from django.contrib.auth.models
, which have the ManyToMany relationship to Groups
.
If you're using some custom User
model you can simply add the PermissionsMixin
from the aforementioned module to inheritance (see docs). And also make sure that django.contrib.auth
is in your INSTALLED_APPS
setting.
The issue must be in you authentication_classes
--(DRF doc) attribute (or DEFAULT_AUTHENTICATION_CLASSES
settings -- (DRF doc))
Behind the scenes, the DRF authentication classes fetch the auth user from the database and assign it to the request
object only after the specified request entity (like Token, JWT Token
, CSRF Token
, etc) validated against the database. This validation and assigning process is happening in the authentication classes.
Suppose, if Django or DRF failed to identify the requested user, it will assign the AnonymousUser
--(Django doc) object to the request
.
Fortunately, the AnonymousUser
object does have a groups
and user_permissions
attributes. Which means, neither request.user.groups
nor request.user.user_permissions
will not raise any AttributeError
exceptions.
Coming to your case, the request.user.groups
raised an exception, which indicates
User
object is neither settings.AUTH_USER_MODEL
nor AnonymousUser
MyEndpoint
is missing a authentication_classes
attributes, hence DRF uses the DEFAULT_AUTHENTICATION_CLASSES
, which may contain a custom class, which may not built properly
I assume you need to use the token-based auth system, so I am using the DRF's TokenAuthentication
-- (DRF doc) here.
Assigning authentication_classes = (TokenAuthentication,)
in the view class will definitely sets the request.user
to either settings.AUTH_USER_MODEL
instance or AnonymousUser
.
from rest_framework.authentication import TokenAuthentication
class MyEndpoint(
mixins.ListModelMixin,
viewsets.GenericViewSet
):
permission_classes = [IsAuthenticated, ReadPermission]
http_method_names = ['get']
authentication_classes = (TokenAuthentication,)
The issue does not belong to the permission_classes
settings, but the authentication_classes
Still not solved??
MIDDLEWARE
? Do you have any custom one?UNAUTHENTICATED_USER
?If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With