Вызвать ошибку условного разрешения в get_queryset DRF
Я хочу получить всех пользователей организации по uuid. Я следую стандартам REST, поэтому хочу, чтобы мой url выглядел как 'organizations/uuid/users/'. Если супер-администратор обратится к этому API, это должно быть разрешено, но если пользователь-администратор попытается использовать этот API, то это должно быть разрешено только в том случае, если администратор принадлежит к той же организации, для которой запрашиваются пользователи. Я использовал класс представления ListAPIView и смог получить список всех пользователей в организации от администратора другой организации, но он все еще возвращает info, когда должен возвращать 403 ошибку.
urls.py
path('organizations/<uuid:pk>/users/', OrganizationUsersView.as_view()),
views.py
class OrganizationUsersView(ListAPIView):
serializer_class = UserSerializer
permission_classes = (IsAuthenticated, IsSuperAdmin|IsAdmin,)
def get_queryset(self):
uuid = self.kwargs['pk']
if self.request.user.role == 'admin':
if self.request.user.org.id != uuid:
return IsOrganizationAdmin()
org = Organization.objects.get(id=uuid)
return User.objects.filter(org=org)
models.py
class Organization(models.Model):
name = models.CharField(max_length=255, null=False)
class User(AbstractBaseUser):
....
other fields
....
org = models.ForeignKey(Organization, on_delete=models.CASCADE, null=False, related_name='users')
Похоже, что вы на правильном пути, но в представленном вами коде есть несколько проблем. Во-первых, в методе get_queryset вы возвращаете класс разрешения IsOrganizationAdmin, когда пользователь является администратором и не принадлежит к организации. Вместо этого вы должны поднять исключение permission denied, например, так:
class OrganizationUsersView(ListAPIView):
serializer_class = UserSerializer
permission_classes = (IsAuthenticated, IsSuperAdmin|IsAdmin,)
def get_queryset(self):
uuid = self.kwargs['pk']
if self.request.user.role == 'admin':
if self.request.user.org.id != uuid:
raise PermissionDenied()
org = Organization.objects.get(id=uuid)
return User.objects.filter(org=org)
Во-вторых, не гарантируется, что у пользователя будет поле org, так как это не является требованием для модели пользователя. Вы должны проверить, есть ли у пользователя поле org, прежде чем обращаться к нему.
class OrganizationUsersView(ListAPIView):
serializer_class = UserSerializer
permission_classes = (IsAuthenticated, IsSuperAdmin|IsAdmin,)
def get_queryset(self):
uuid = self.kwargs['pk']
if self.request.user.role == 'admin':
if not hasattr(self.request.user, "org") or self.request.user.org.id != uuid:
raise PermissionDenied()
org = Organization.objects.get(id=uuid)
return User.objects.filter(org=org)
Наконец, вы можете рассмотреть возможность использования пользовательского класса разрешения IsOrganizationAdmin вместо IsSuperAdmin|IsAdmin. Это гарантирует, что только пользователи с ролью администратора и принадлежащие к указанной организации могут получить доступ к API.