Как правильно изменить пароль пользовательского пользователя?

Я работаю над своим приложением Django (DRF). Есть CustomUser модель

class CustomAccountManager(BaseUserManager):
    def create_superuser(self, email, user_name, password, **other_fields):
        ...
        
    def create_user(self, email, user_name, password, **other_fields):

        if not email:
            raise ValueError(_('You must provide an email address'))

        email = self.normalize_email(email)
        user = self.model(email=email, user_name=user_name, **other_fields)
        user.set_password(password)
        user.save()
        return user

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), unique=True)
    user_name = models.CharField(max_length=150, unique=True) # Full name
    phone_number = models.CharField(max_length=20, unique=True)
    ...

Я создал пользовательский способ смены пароля. Я посылаю current_password, new_password_verify и new_password_verify в параметре body.

Каким образом правильно реализовать смену пароля в Django?

class CustomUserViewSet(viewsets.ModelViewSet):
    def update(self, request: Request, *args, **kwargs):
        instance: CustomUser = self.get_object()

        serializer = self.get_serializer(
            instance, data=request.data, partial=True
        )
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, "_prefetched_objects_cache", None):
            instance._prefetched_objects_cache = {}
        return Response({
            "is_password_updated": self.update_password(request, instance), # <-------UPDATE
            "result": serializer.data
        }) 


    def update_password(self, request, instance):
        """update password if 'new_password_verify' and 'new_password' are in request"""
        if  "current_password" in request.data and instance.check_password(request.data["current_password"]) and \
            "new_password" in request.data and "new_password_verify" in request.data and \
            request.data["new_password"] == request.data["new_password_verify"]:

            instance.set_password(request.data["new_password"])
            instance.save()
            return True
        return False

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

class ChangePasswordSerializer(serializers.Serializer):
    current_password = serializers.CharField(trim_whitespace = False, validators=[validate_password]),
    new_password = serializers.CharField(trim_whitespace = False, validators=[validate_password])
    new_password_verify = serializers.CharField(trim_whitespace = False)

    def validate(self, attrs):
        if attrs.get('new_password') != attrs.get('new_password_verify'):
            serializers.ValidationError('Password and confirm password do not match')
        return attrs


def validate_password(value):
    # you can set your own validating logic here if you want to
    # for example, like validations for length or regex 
    pass

Конечно, вам не нужно загружать new_password_verify данные, а проверять эту часть во фронтенде, тогда поле new_password_verify и метод validate не нужны и код будет проще.

class CustomUserViewSet(viewsets.ModelViewSet):
    def update(self, request: Request, *args, **kwargs):
        ...
        return Response({
            "is_password_updated": self.update_password(request, instance)
            "result": serializer.data
        }) 


    def update_password(self, request, instance):
        serializer = ChangePasswordSerializer(data = request.data)
        if serializer.is_valid():
            input_data = serializer.validated_data
            cur_password = input_data.get('current_password')
            new_password = input_data.get('new_password')
            if instance.check_password(cur_password):
                instance.set_password(new_password)
                instance.save()
                return True
        return False
Вернуться на верх