Объединение 2 пользовательских разрешений в django остальные рамки - PullRequest
1 голос
/ 13 февраля 2020

У меня есть модель под названием Showcase, которую пользователи используют для демонстрации проектов, а также модель сотрудничества, в которой пользователи могут добавлять соавторов в витрину. Я пытаюсь реализовать случай, когда администраторы в витрине и пользователь в сотрудничестве могут удалить это сотрудничество.

Чтобы объяснить лучше, в модели витрины есть список администраторов, которые управляют витриной. они также могут добавлять соавторов (через модель Collaborator) в витрину. У Collaborator есть поле пользователя, которое является пользователем, внесенным в витрину.

Я хочу, чтобы после добавления соавтора этот пользователь мог либо удалить себя (в случае, если он не хочет быть частью витрина) или администраторы могут удалить этого соавтора (в случае, если он добавил не того пользователя и хочет удалить его из этой витрины)

models.py

class Showcase(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField(null=True)
    skill_type = models.ForeignKey(Skill, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="Showcases")
    content = models.TextField(null=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    voters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="upvotes")
    slug = models.SlugField(max_length=255, unique=True)
    administrator = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="administrators", blank=True)


class Collaborator(models.Model):
    post = models.ForeignKey(Showcase, on_delete=models.CASCADE, related_name="collaborated_showcases")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, 
                            on_delete=models.CASCADE, related_name="collaborators")
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE, null=True, related_name="creative_type")
    role = models.TextField(null=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)

allow.py

class IsUser(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return False
        return obj.user == request.user


class IsAdmin(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return False
        return request.user.administrators.filter(pk=obj.pk).exists()

view.py

class CollaboratorDeleteView(APIView):
    '''
    Allow Administrators to delete a collaborator to a showcase 
    or allow the collaborator user to be able to delete himself 
    '''
    permission_classes = [IsAdmin]

    def delete(self, request, pk):
        collaborator = get_object_or_404(Collaborator, pk=pk)
        showcase = collaborator.post

        try:
            self.check_object_permissions(request, showcase)
            collaborator.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
        except APIException:
            return Response(status=status.HTTP_403_FORBIDDEN)

URLs

path("collaborator/<int:pk>/delete/", qv.CollaboratorDeleteView.as_view(), name="collaborator-delete-view"),

Прямо сейчас я смог реализовать, что администраторы могут удалять соавтора, но как я могу добавить другое разрешение для пользователя в модели Collaborator, чтобы он мог удалить себя как соавтора через то же представление?

Ответы [ 2 ]

2 голосов
/ 13 февраля 2020

На самом деле оба разрешения могут быть объединены в одно. Например, обновляем разрешение таким образом:

class CanDeleteUser(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return False
        return obj.user == request.user or ob.post.administrator.filter(pk=request.user.pk).exists()

Здесь я проверяю либо request.user is obj.user, либо проверяю администраторов объекта showcase, присоединенного к переменной obj.

Теперь я собираюсь проверить только разрешение на collaborator.

class CollaboratorDeleteView(APIView):
    '''
    Allow Administrators to delete a collaborator to a showcase 
    or allow the collaborator user to be able to delete himself 
    '''
    permission_classes = [CanDeleteUser]

    def delete(self, request, pk):
        collaborator = get_object_or_404(Collaborator, pk=pk)

        try:
            self.check_object_permissions(request, collaborator)
2 голосов
/ 13 февраля 2020

Вы можете добавить столько разрешений, сколько вам нужно, к атрибуту permission_classses, используя & (и), | Знаки (или) и ~ (не) ( do c):

class CollaboratorDeleteView(APIView):
    '''
    Allow Administrators to delete a collaborator to a showcase 
    or allow the collaborator user to be able to delete himself 
    '''
    permission_classes = [IsAdmin|IsUser]

Оба эти разрешения теперь будут работать с OR logi c.

...