1

I have view for authentfication:

class UserViewSet(viewsets.ViewSet):
    @method_decorator(sensitive_variables("password"))
    @action(url_path="sign-in", detail=False, methods=["POST"])
    def sign_in(self, request: HttpRequest) -> Response:
        if not request.user.is_anonymous:
            return Response({"status": "forbidden"}, status=403)

        form = AuthenticationForm(data=request.data)
        print(form.data)
        if form.is_valid():
            user = authenticate(request, **form.cleaned_data)
            login(request, user)
            return Response({"status": "ok"}, status=200)
        print(form.error_messages)
        raise ValidationError(form.errors)

I write the test:

class UserTest(TestCase):
    @classmethod
    def setUpClass(cls):
        User.objects.create(username="admin", password="Qwerty1234", is_active=True)
        super().setUpClass()
        cls.client = Client()

    @classmethod
    def tearDownClass(cls):
        return super().tearDownClass()

    def test_sign_in(self):
        url = "/api/sign-in/"
        print(User.objects.get(username="admin").is_active)
        response = self.client.post(
            url,
            data={"username": "admin", "password": "Qwerty1234"},
            content_type="application/json",
        )

But, I receive the errors from form form_validator:

{'invalid_login': 'Please enter a correct %(username)s and password. Note that both fields may be case-sensitive.', 'inactive': 'This account is inactive.'} 

What can be a problem?

P.S. At that case, is there any sense to use sensitive_variables?

1 Answer 1

0

it seems to me that the problem is with password hashing, when you create a user directly using the User.objects.create(username="admin", password="Qwerty1234", is_active=True) method the password is not hashed, django stores passwords in hashed format so the password needs to be set using set_password method so we need to use set_password to hash the password properly then save the user after setting the password

so your viwe code should looks like this:

class UserViewSet(viewsets.ViewSet):
    @method_decorator(sensitive_variables("password"))
    @action(url_path="sign-in", detail=False, methods=["POST"])
    def sign_in(self, request: HttpRequest) -> Response:
        if not request.user.is_anonymous:
            return Response({"status": "forbidden"}, status=403)

        form = AuthenticationForm(data=request.data)
        print(form.data)
        if form.is_valid():
            user = authenticate(request, **form.cleaned_data)
            if user is not None:
                login(request, user)
                return Response({"status": "ok"}, status=200)
        print(form.error_messages)
        raise ValidationError(form.errors)

and your test code should looks like this:

class UserTest(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        user = User.objects.create(username="admin", is_active=True)
        user.set_password("Qwerty1234")
        user.save()
        cls.client = Client()

    @classmethod
    def tearDownClass(cls):
        return super().tearDownClass()

    def test_sign_in(self):
        url = "/api/sign-in/"
        print(User.objects.get(username="admin").is_active)
        response = self.client.post(
            url,
            data={"username": "admin", "password": "Qwerty1234"},
            content_type="application/json",
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json(), {"status": "ok"})

sensitive_variables is used to mark certain variables as sensitive so that their values are not included in error reports so it can be useful in production to avoid logging sensitive information like passwords.

I hope this helps you.

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.