Django Rest Framework Custom Permission не вступает в силу

У меня есть файл permissions.py, который содержит пользовательское разрешение под названием CanViewUserRecord. Я назначил его на набор представлений под названием UserRecordView. Однако разрешение не работает, всякий раз, когда я вызываю конечную точку, прикрепленную к набору представлений, все данные из базы данных возвращаются. Вот код пользовательского разрешения:

from accounts.models import Staff

class CanViewUserRecord(permissions.BasePermission):

    edit_methods = ("PUT", "PATCH")

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            if obj.account_type == "staff":
                # If user is the manager of staff
                if obj.staff.manager == request.user.id:
                    return True
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow admins to access
                if request.user.account_type == "admin":
                    return True
                return False

            elif obj.account_type == "manager":
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow Admins to access
                if request.user.account_type == "admin":
                    return True
                return False

            elif obj.account_type == "admin":
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow Admins to access
                if request.user.account_type == "admin":
                    return True
                return False
            else:
                return False
        elif request.method in self.edit_methods:
            if obj.account_type == "staff":
                if (
                    request.user.account_type == "manager"
                    or request.user.account_type == "admin"
                ):
                    return True

                else:
                    return False
            elif obj.account_type == "manager":
                return True
            else:
                return False

        return False

Идея заключается в том, чтобы ограничить то, что пользователи могут видеть, в зависимости от типа_аккаунта пользователя, назначенного токену, переданному в конечную точку API. Вот мой код набора представлений:

class UserRecordView(views.APIView):
    """
    API View to create or get a list of all the registered
    users. GET request returns the registered users whereas
    a POST request allows to create a new user.
    """

    permission_classes = [CanViewUserRecord, permissions.IsAuthenticated]

    def get(self, format=None):
        users = Account.objects.all()
        serializer = AccountSerializer(users, many=True)
        return response.Response(serializer.data)

    def post(self, request):
        serializer = AccountSerializer(data=request.data)
        if serializer.is_valid(raise_exception=ValueError):
            serializer.save()
            return response.Response(serializer.data, status=status.HTTP_201_CREATED)
        return response.Response(
            {
                "error": True,
                "error_msg": serializer.error_messages,
            },
            status=status.HTTP_400_BAD_REQUEST,
        )

Итак, если я делаю запрос с токеном, который назначен пользователю, имеющему статус "manager", я не хочу, чтобы он мог видеть записи для пользователя, имеющего тип учетной записи "admin". Однако я провел тест, в котором разрешение просто вернуло False и ничего больше, и запрос API все равно возвращает данные, даже когда разрешение установлено на False. Есть идеи, что я делаю не так? Вот модель для справки о полях:

class Account(auth_models.AbstractBaseUser):

    username = models.CharField(max_length=40, unique=True, primary_key=True)

    ACCOUNT_TYPE_CHOICES = (
        ("manager", "Manager"),
        ("staff", "Staff"),
        ("admin", "Admin"),
    )

    account_type = models.CharField(
        choices=ACCOUNT_TYPE_CHOICES,
        default="staff",
        blank=False,
        null=False,
        max_length=10,
    )
    date_joined = models.DateTimeField(verbose_name="Date Joined", 
              auto_now_add=True)
    is_active = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=False)

    USERNAME_FIELD = "username"
    REQUIRED_FIELDS = ["account_type"]

    objects = AccountManager()

    def __str__(self):
        return self.username

    def has_module_perms(self, app_label):
        return True

class Staff(models.Model):
    user = models.OneToOneField(Account, on_delete=models.CASCADE, primary_key=True)
    first_name = models.CharField(max_length=50, null=False, blank=False)
    last_name = models.CharField(max_length=50, null=False, blank=False)
    date_of_birth = models.DateField(null=False, blank=False)
    manager = models.ForeignKey(Manager, on_delete=models.CASCADE)
    employment_start_date = models.DateField(null=False, blank=True)
    employment_end_date = models.DateField(blank=True)
    role = models.ForeignKey(
        Role, on_delete=models.CASCADE, related_name="assigned_staff"
    )

    REQUIRED_FIELDS = [
        "user",
        "first_name",
        "last_name",
        "date_of_birth",
        "manager",
        "employment_start_date",
        "role",
    ]

EDIT: Я добавил функцию has_permission в разрешение, как предложил JPG в комментариях. Данные, которые возвращаются, все еще неверны и дают мне доступ к ресурсу, на который у него не должно быть разрешения. Вот обновленный код:

class CanViewUserRecord(permissions.BasePermission):

    edit_methods = ("PUT", "PATCH")
    message = None

    def has_permission(self, request, view):
        if request.user.is_authenticated:
            return True

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            if obj.account_type == "employee":
                # If user is the employer
                if obj.employee.employer == request.user.id:
                    return True
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow Jool Admins to access
                if request.user.account_type == "jool-admin":
                    return True
                self.message = "Requestor does not have access to this employee record"
                return False

            elif obj.account_type == "provider":
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow Jool Admins to access
                if request.user.account_type == "jool-admin":
                    return True
                self.message = "Requestor cannot view provider records"

                return False

            elif obj.account_type == "jool-admin":
                # If the user is the owner
                if obj == request.user:
                    return True
                # Allow Jool Admins to access
                if request.user.account_type == "jool-admin":
                    return True
                self.message = "Requestor cannot view admin records"
                return False
            else:
                return False
        elif request.method in self.edit_methods:
            if obj.account_type == "employee":
                if (
                    request.user.account_type == "provider"
                    or request.user.account_type == "jool-admin"
                ):
                    return True

                else:
                    return False
            elif obj.account_type == "provider":
                return True
            else:
                return False

        return False

Я думаю, это то, что вы ищете whats-the-differences-between-has-object-permission-and-has-permission

has_object_permission(...)

вызывается, когда вы вызываете get_object(), поэтому вам нужно переопределить has_permission(...) вместо этого. Как я вижу:

def has_permission(self, request, view):
    if request.user.is_authenticated:
        return True

это всегда позволяет пользователю, уже вошедшему в систему, пройти CanViewUserRecord

Вернуться на верх