diff --git a/care/users/reset_password_views.py b/care/users/reset_password_views.py index 6cec930e4c..28ab1cfe12 100644 --- a/care/users/reset_password_views.py +++ b/care/users/reset_password_views.py @@ -15,7 +15,7 @@ get_password_reset_lookup_field, get_password_reset_token_expiry_time, ) -from django_rest_passwordreset.serializers import PasswordTokenSerializer +from django_rest_passwordreset.serializers import PasswordValidateMixin from django_rest_passwordreset.signals import ( post_password_reset, pre_password_reset, @@ -38,8 +38,24 @@ ) -class ResetPasswordUserSerializer(serializers.Serializer): - username = serializers.CharField() +class ResetPasswordCheckSerializer(serializers.Serializer): + token = serializers.CharField( + write_only=True, help_text="The token that was sent to the user's email address" + ) + status = serializers.CharField(read_only=True, help_text="Request status") + + +class ResetPasswordConfirmSerializer(PasswordValidateMixin, serializers.Serializer): + token = serializers.CharField( + write_only=True, help_text="The token that was sent to the user's email address" + ) + password = serializers.CharField(write_only=True, help_text="The new password") + status = serializers.CharField(read_only=True, help_text="Request status") + + +class ResetPasswordRequestTokenSerializer(serializers.Serializer): + username = serializers.CharField(write_only=True) + status = serializers.CharField(read_only=True, help_text="Request status") class ResetPasswordCheck(GenericAPIView): @@ -47,11 +63,15 @@ class ResetPasswordCheck(GenericAPIView): An Api View which provides a method to check if a password reset token is valid """ + authentication_classes = () permission_classes = () + serializer_class = ResetPasswordCheckSerializer - @extend_schema(tags=["auth", "users"]) + @extend_schema(tags=["auth"]) def post(self, request, *args, **kwargs): - token = request.data.get("token", None) + serializer = self.serializer_class(data=request.data) + serializer.is_valid(raise_exception=True) + token = serializer.validated_data["token"] if ratelimit(request, "reset", [token], "20/h"): return Response( @@ -92,10 +112,11 @@ class ResetPasswordConfirm(GenericAPIView): An Api View which provides a method to reset a password based on a unique token """ + authentication_classes = () permission_classes = () - serializer_class = PasswordTokenSerializer + serializer_class = ResetPasswordConfirmSerializer - @extend_schema(tags=["auth", "users"]) + @extend_schema(tags=["auth"]) def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) @@ -171,10 +192,11 @@ class ResetPasswordRequestToken(GenericAPIView): """ throttle_classes = () + authentication_classes = () permission_classes = () - serializer_class = ResetPasswordUserSerializer + serializer_class = ResetPasswordRequestTokenSerializer - @extend_schema(tags=["auth", "users"]) + @extend_schema(tags=["auth"]) def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) @@ -218,9 +240,9 @@ def post(self, request, *args, **kwargs): ): raise exceptions.ValidationError( { - "email": [ + "username": [ _( - "There is no active user associated with this e-mail address or the password can not be changed" + "There is no active user associated with this username or the password can not be changed" ) ], } diff --git a/care/users/tests/test_auth.py b/care/users/tests/test_auth.py index 29e5f4168c..c03665f0b6 100644 --- a/care/users/tests/test_auth.py +++ b/care/users/tests/test_auth.py @@ -162,8 +162,8 @@ def test_verify_password_reset_token(self): def test_verify_password_reset_token_with_missing_fields(self): response = self.client.post("/api/v1/password_reset/check/") - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - self.assertEqual(response.data["detail"], "The password reset link is invalid") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(response.json()["token"], ["This field is required."]) def test_verify_password_reset_token_with_invalid_token(self): response = self.client.post(