Разрешение на основе значения поля, которое пользователь POST - PullRequest
0 голосов
/ 20 апреля 2019

Упрощенное представление моих моделей:

# models.py 

class User(models.Model):
    first_name = models.CharField()
    last_name = models.CharField()
    team = models.ForeignKey('Team')
    ...

class Team(models.Model):
    name = models.CharField()

class ToDo(models.Model):
    task = models.CharField()
    description = models.TextField()
    owner = models.ForeignKey('User')

# serializers.py

class ToDoSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = ToDo
        fields = '__all__'

Я хочу создать конечную точку POST для добавления нового объекта ToDo на основе следующей логики:

  • Пользователи могут создавать ToDo предметов для себя
  • Пользователи могут создавать ToDo предметов для других в своей команде
  • Пользователи не могут создавать ToDo предметов для других, которых нет в ихteam

Вопрос: Где написать эту логику

Я пытался сделать это с помощью классов разрешений, но не знаю, является ли это лучшим местом длясделать это

# views.py

class ToDoViewSet(viewsets.ModelViewSet):
    serializer_class = ToDoSerializer
    permission_classes = (CanAddToDo,)



# permissions.py

class CanAddToDo(BasePermission):
    def has_permission(self, request, view):
        owner_id = request.data.get('owner', None)

        # owner_id must be set
        if not owner_id:
            return False

        # User can create items if owner is themselves or someone in their team
        if User.objects.get(pk=owner_id).team == request.user.team:
            return True

        return False

    def has_object_permission(self, request, view, obj):
        """
        Checks if the user owns the todo to edit
        """
        return obj.owner == request.user

Что меня беспокоит, так это то, что я не использую сериализованные данные, а вместо этого получаю необработанный идентификатор владельца из запроса и делаю запрос в объекте полномочий, чтобы выполнить мою проверку / разрешение

Другими вариантами может быть выполнение этой проверки в функции def perform_create(self, serializer): представлений или в самом сериализаторе.

1 Ответ

1 голос
/ 21 апреля 2019

Есть другой способ взглянуть на это;проверка для владельца

В вашем сериализаторе для ToDo вы можете написать проверку для поля владельца

class ToDoSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = ToDo
        fields = '__all__'

    def validate_owner(self, val):
        owner = val
        request = self.context.get('request', None)
        # it is possible you are using serializer outside an api view 
        # in which case reqeust will not be present in the serializer context
        if request:
            if owner.team != request.user.team:
                raise serializers.ValidationError('you can only create todos for'
                                                  'yourself or your team members')
        return val

Это хорошо работает для создания.Но для обновления или удаления вам необходимо проверить текущего владельца объекта todo.Что можно сделать в классе разрешений.Вы можете использовать id из URL-адреса запроса, чтобы получить объект todo в классе разрешений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...