dj-rest-auth
dj-rest-auth copied to clipboard
Blank, short, not match and common password validation errors for change password are all 'password required' rather than the appropriate error
Title. If needed more information can be provided upon request.
Can you show me an example HTTP requests that would reproduce the error? We have tests for this and they're passing. The code itself looks right too.
It sounds like you're not sending a valid request or you're missing headers.
This currently passes with the expected failure decorators. I am going to switch from using force_authenticate to credentials which may be causing the unexpected behaviour.
Edit1: I tried switching from force_authenticate to passing the access token from the login route using credentials and there was no change.
def setUp(self):
response = client.post(reverse('rest_login'),
{'username': self.USER['username'],
'password': self.USER['password1']})
client.credentials(
HTTP_AUTHORIZATION=f"Bearer {response.data['access_token']}")
def tearDown(self):
client.credentials()
import re
from unittest import expectedFailure
from django.contrib.auth.models import User
from django.core import mail
from rest_framework import exceptions, status
from rest_framework.reverse import reverse
from rest_framework.test import APIClient, APITestCase
client = APIClient()
class PasswordTestCase(APITestCase):
@classmethod
def setUpTestData(cls):
cls.PATTERN = re.compile(r'^.*email/(.*)/.*$',
re.DOTALL)
cls.USER = {'username': 'user',
'email': '[email protected]',
'password1': 'complex_password',
'password2': 'complex_password'}
cls.URL = reverse('rest_password_change')
client.post(reverse('rest_register'),
cls.USER)
key = re.match(cls.PATTERN, mail.outbox[0].body).group(1)
client.post(reverse('account_email_verification_sent'),
{'key': key})
def setUp(self):
user = User.objects.get(username=self.USER['username'])
client.force_authenticate(user) # This may be the cause of the behaviour.
def tearDown(self):
client.force_authenticate(None)
def test_missing_password(self):
payload = {}
response = client.post(self.URL,
payload)
self.assertEqual(response.status_code,
status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
response.data,
{'new_password1': [exceptions.ErrorDetail('This field is required.',
'required')],
'new_password2': [exceptions.ErrorDetail('This field is required.',
'required')]})
@expectedFailure
def test_blank_password(self):
payload = {'password1': '',
'password2': ''}
response = client.post(self.URL,
payload)
self.assertEqual(response.status_code,
status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
response.data,
{
'password1': [exceptions.ErrorDetail('This field may not be '
'blank.',
'blank')],
'password2': [exceptions.ErrorDetail('This field may not be '
'blank.',
'blank')]})
@expectedFailure
def test_short_password(self):
payload = {'password1': 'pass',
'password2': 'pass'}
response = client.post(self.URL,
payload)
self.assertEqual(response.status_code,
status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
response.data,
{'new_password1': [exceptions.ErrorDetail('This password is too '
'short. It must contain '
'at least 8 characters.',
'password_too_short')],
'new_password2': [exceptions.ErrorDetail('This password is too '
'short. It must contain '
'at least 8 characters.',
'password_too_short')]})
@expectedFailure
def test_password_not_match(self):
payload = {'password1': 'pass',
'password2': 'word'}
response = client.post(self.URL,
payload)
self.assertEqual(response.status_code,
status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
response.data,
{'non_field_errors': [exceptions.ErrorDetail("The two password "
"fields didn't match.",
'invalid')]})
@expectedFailure
def test_common_password(self):
payload = {'password1': 'password',
'password2': 'password'}
response = client.post(self.URL,
payload)
self.assertEqual(response.status_code,
status.HTTP_400_BAD_REQUEST)
self.assertDictEqual(
response.data,
{'password1': [exceptions.ErrorDetail('This password is too '
'common.',
'password_too_common')]})
@brian-e-haley This is because of the force authentication technique.
I have made another piece of test which seems passing.
from django.test import TestCase
from rest_framework.exceptions import ErrorDetail
from dj_rest_auth.registration.serializers import RegisterSerializer
class TestRegisterSerializerSerializer(TestCase):
def test_short_password(self):
serializer = RegisterSerializer(
data={
"username": "test",
"email": "[email protected]",
"password1": "pass",
"password2": "pass"
}
)
self.assertEqual(serializer.is_valid(), False)
self.assertEqual(
serializer.errors,
{
'password1': [
ErrorDetail(
string='Password must be a minimum of 6 characters.',
code='invalid'
)
]
}
)
@iMerica I hope this issue can be closed now
@jerinpetergeorge As I mentioned in my Edit1: which I left here in August using client.credentials() in place of client.force_authenticate() does not change anything so I don't think it is fair to say that client.force_authenticate() is the cause.
I posted this months ago though so my memory is a bit fuzzy so I doubt I will be of much help.