Сериализаторы Rest Framework, запрещающие пользователям менять чужой пароль - PullRequest
0 голосов
/ 31 августа 2018

Я создаю простое веб-приложение и не могу найти способа запретить другим пользователям изменять ваш пароль. Это минимальный код:

# serializers.py
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        # have to use custom create method because default method calls `User.objects.create()` which doesn't take care of password hashing and other important stuff 
        return User.objects.create_user(**validated_data)

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password')
        read_only_fields = ('id', 'username')

        # password is set to write_only because I don't want to send it to anybode (even though it's just a hash)
        extra_kwargs = {'password': {'write_only': True}}

# views.py
from .serializers import UserSerializer
from rest_framework import generics
from django.contrib.auth.models import User

class UserDetails(generics.RetrieveUpdateAPIView):

    queryset = User.objects.all()
    serializer_class = UserSerializer

Я мог бы сам позаботиться об этом, используя APIView.

# views.py
from .serializers import UserSerializer
from rest_framework.views import APIView
from django.contrib.auth.models import User

class UserDetails(APIView):
    def put(self, request, format=None):

        serialized = UserSerializer(data=request.DATA)
        if not serialized.is_valid():
            return # probably HTTP 400 Error code
        if request.user.id != serialized.data['id']:
            # this if is what I'm trying to achieve
            return # probably HTTP 403 Error code
        user = User.objects.update(
            id=serialized.data['id'],
            email=serialized.data['email']
        )
        if 'password' in request.DATA:
            user.set_password(request.DATA['password'])
        return # probably HTTP 200 Error code

К сожалению, это привело бы к тому, что сгенерированная rest_framework.schemas.get_schema_view схема была бы неполной. И я использую для связи CoreAPI (который не может общаться с чем-то, что не описано в схеме), поэтому я не могу этого сделать. Я не нашел ничего в официальной документации. Кажется, это слишком простая проблема, решение которой очень просто пропущено. Спасибо за любые идеи или места, где искать.

PS: я использую django2.1 с python3.6

Редактировать: решения osobacho чисты и работают как шарм. В любом случае, мне также нужно разрешить модификации (скажем, TODO-list) только создателю этого списка задач. Думал, что решение проблемы с паролем будет применимо, но это не так.

1 Ответ

0 голосов
/ 31 августа 2018

Вы можете получить пользователя в запросе. Таким образом, каждый пользователь сможет изменить только свой пароль.

class UserDetails(generics.RetrieveUpdateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user

По второму вопросу посмотрите на django_restframework http://www.django -rest-framework.org / api-guide / permissions / . Вот пример разрешений:

class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""

def has_object_permission(self, request, view, obj):
    # Read permissions are allowed to any request,
    # so we'll always allow GET, HEAD or OPTIONS requests.
    if request.method in permissions.SAFE_METHODS:
        return True

    # Instance must have an attribute named `owner`.
    return obj.owner == request.user

тогда вам нужно добавить к вашему виду:

 permission_classes = (IsOwnerOrReadOnly,)

надеюсь, это поможет

...