class UserViewSet(viewsets.ModelViewSet):
def list(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def create(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
pass
def retrieve(self, request, pk):
user = get_object_or_404(User, pk=pk)
self.check_object_permissions(request, user)
serializer = UserSerializer(user)
return Response(serializer.data, status=status.HTTP_200_OK)
def get_permissions(self):
if self.action == "list":
permission_classes = [
IsAdminUser,
]
elif self.action == "create":
permission_classes = [AllowAny]
else:
permission_classes = [AccountOwnerPermission | IsAdminUser ]
return [permission() for permission in permission_classes]
and custom permission is:
class AccountOwnerPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
print(object)
print(request.user)
return obj == request.user
first i dont get object permission but with help of @brian-destura at this question i fixed that part the previous question now the problem is when i chain 2 permission together it behave like AllowAny i check them one by one and both permissions work fine, one of them allow admin and one of them allow owner but when they are or together it mess everything up
When chaining permissions like
permission_classes = [AccountOwnerPermission, IsAdminUser]
it behaves like an AND operator between the permission classes
The best option is to create a new permission that allows either the permission logic.
class AdminOrAccountOwnerPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj == request.user or request.user.id_admin
or this when the permissions used have long complex code to keep code DRY:
class AdminOrAccountOwnerPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return AccountOwnerPermission().has_object_permission(request, view, obj) or IsAdminUser().has_object_permission(request, view, obj)
EDIT:
Address the question from the comments, the reason why it behaves like AllowAny
.
AccountOwnerPermission
has has_object_permission
but no has_permission
. On the other hand, IsAdminUser
has has_permission
but no has_object_permission
implemented.
When those functions are not implemented, the functions return True
by default(from BasePermission
). As a result, when running has_permission
, AccountOwnerPermission
always returns True
When running has_object_permission
, IsAdminUser
is always returning True
.
Implementing AccountOwnerPermission.has_permission
would give the expected behavior.