Cleaning up unicode waffle flag
This commit is contained in:
@@ -35,7 +35,6 @@ from lms.djangoapps.verify_student.utils import is_verification_expiring_soon, v
|
||||
from openedx.core.djangoapps.certificates.api import certificates_viewable_for_course
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.theming import helpers as theming_helpers
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PASSWORD_UNICODE_NORMALIZE_FLAG
|
||||
from openedx.core.djangoapps.theming.helpers import get_themes
|
||||
from openedx.core.djangoapps.user_authn.utils import is_safe_login_or_logout_redirect
|
||||
from student.models import (
|
||||
@@ -414,8 +413,7 @@ def authenticate_new_user(request, username, password):
|
||||
logged in until they close the browser. They can't log in again until they click
|
||||
the activation link from the email.
|
||||
"""
|
||||
if PASSWORD_UNICODE_NORMALIZE_FLAG.is_enabled():
|
||||
password = normalize_password(password)
|
||||
password = normalize_password(password)
|
||||
backend = load_backend(NEW_USER_AUTH_BACKEND)
|
||||
user = backend.authenticate(request=request, username=username, password=password)
|
||||
user.backend = NEW_USER_AUTH_BACKEND
|
||||
@@ -614,9 +612,7 @@ def do_create_account(form, custom_form=None):
|
||||
email=form.cleaned_data["email"],
|
||||
is_active=False
|
||||
)
|
||||
password = form.cleaned_data["password"]
|
||||
if PASSWORD_UNICODE_NORMALIZE_FLAG.is_enabled():
|
||||
password = normalize_password(password)
|
||||
password = normalize_password(form.cleaned_data["password"])
|
||||
user.set_password(password)
|
||||
registration = Registration()
|
||||
|
||||
|
||||
@@ -144,7 +144,8 @@ class TestPasswordPolicy(TestCase):
|
||||
create_validator_config('util.password_policy_validators.NumericValidator', {'min_numeric': 3})
|
||||
])
|
||||
def test_not_enough_numeric_characters(self):
|
||||
self.url_params['password'] = u'thishouldfail½2'
|
||||
# The unicode ២ is the number 2 in Khmer and the ٧ is the Arabic-Indic number 7
|
||||
self.url_params['password'] = u'thisShouldFail២٧'
|
||||
response = self.client.post(self.url, self.url_params)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
obj = json.loads(response.content)
|
||||
@@ -157,8 +158,8 @@ class TestPasswordPolicy(TestCase):
|
||||
create_validator_config('util.password_policy_validators.NumericValidator', {'min_numeric': 3})
|
||||
])
|
||||
def test_enough_numeric_characters(self):
|
||||
# This unicode 1/2 should count as a numeric value here
|
||||
self.url_params['password'] = u'thisShouldPass½33'
|
||||
# The unicode ២ is the number 2 in Khmer
|
||||
self.url_params['password'] = u'thisShouldPass២33'
|
||||
response = self.client.post(self.url, self.url_params)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
obj = json.loads(response.content)
|
||||
@@ -260,7 +261,7 @@ class TestPasswordPolicy(TestCase):
|
||||
"""
|
||||
Tests that even if password policy is enforced, ext_auth registrations aren't subject to it
|
||||
"""
|
||||
self.url_params['password'] = 'aaa' # shouldn't pass validation
|
||||
self.url_params['password'] = u'aaa' # shouldn't pass validation
|
||||
request = self.request_factory.post(self.url, self.url_params)
|
||||
request.site = SiteFactory.create()
|
||||
# now indicate we are doing ext_auth by setting 'ExternalAuthMap' in the session.
|
||||
|
||||
@@ -25,9 +25,7 @@ from provider.oauth2 import models as dop_models
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.user_api.models import UserRetirementRequest
|
||||
from openedx.core.djangoapps.user_api.config.waffle import (
|
||||
PASSWORD_UNICODE_NORMALIZE_FLAG, PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle
|
||||
)
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from student.tests.factories import UserFactory
|
||||
from student.tests.test_email import mock_render_to_string
|
||||
@@ -360,21 +358,20 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
method of NFKC.
|
||||
In this test, the input password is u'p\u212bssword'. It should be normalized to u'p\xc5ssword'
|
||||
"""
|
||||
with PASSWORD_UNICODE_NORMALIZE_FLAG.override(active=True):
|
||||
url = reverse(
|
||||
"password_reset_confirm",
|
||||
kwargs={"uidb36": self.uidb36, "token": self.token}
|
||||
)
|
||||
url = reverse(
|
||||
"password_reset_confirm",
|
||||
kwargs={"uidb36": self.uidb36, "token": self.token}
|
||||
)
|
||||
|
||||
password = u'p\u212bssword'
|
||||
request_params = {'new_password1': password, 'new_password2': password}
|
||||
confirm_request = self.request_factory.post(url, data=request_params)
|
||||
response = password_reset_confirm_wrapper(confirm_request, self.uidb36, self.token)
|
||||
password = u'p\u212bssword'
|
||||
request_params = {'new_password1': password, 'new_password2': password}
|
||||
confirm_request = self.request_factory.post(url, data=request_params)
|
||||
response = password_reset_confirm_wrapper(confirm_request, self.uidb36, self.token)
|
||||
|
||||
user = User.objects.get(pk=self.user.pk)
|
||||
salt_val = user.password.split('$')[1]
|
||||
expected_user_password = make_password(unicodedata.normalize('NFKC', u'p\u212bssword'), salt_val)
|
||||
self.assertEqual(expected_user_password, user.password)
|
||||
user = User.objects.get(pk=self.user.pk)
|
||||
salt_val = user.password.split('$')[1]
|
||||
expected_user_password = make_password(unicodedata.normalize('NFKC', u'p\u212bssword'), salt_val)
|
||||
self.assertEqual(expected_user_password, user.password)
|
||||
|
||||
@override_settings(AUTH_PASSWORD_VALIDATORS=[
|
||||
create_validator_config('util.password_policy_validators.MinimumLengthValidator', {'min_length': 2}),
|
||||
|
||||
@@ -57,9 +57,7 @@ from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.theming import helpers as theming_helpers
|
||||
from openedx.core.djangoapps.theming.helpers import get_current_site
|
||||
from openedx.core.djangoapps.user_api.config.waffle import (
|
||||
PASSWORD_UNICODE_NORMALIZE_FLAG, PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle
|
||||
)
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PREVENT_AUTH_USER_WRITES, SYSTEM_MAINTENANCE_MSG, waffle
|
||||
from openedx.core.djangoapps.user_api.errors import UserNotFound, UserAPIInternalError
|
||||
from openedx.core.djangoapps.user_api.models import UserRetirementRequest
|
||||
from openedx.core.djangoapps.user_api.preferences import api as preferences_api
|
||||
@@ -829,16 +827,15 @@ def password_reset_confirm_wrapper(request, uidb36=None, token=None):
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
if PASSWORD_UNICODE_NORMALIZE_FLAG.is_enabled():
|
||||
# We have to make a copy of request.POST because it is a QueryDict object which is immutable until copied.
|
||||
# We have to use request.POST because the password_reset_confirm method takes in the request and a user's
|
||||
# password is set to the request.POST['new_password1'] field. We have to also normalize the new_password2
|
||||
# field so it passes the equivalence check that new_password1 == new_password2
|
||||
# In order to switch out of having to do this copy, we would want to move the normalize_password code into
|
||||
# a custom User model's set_password method to ensure it is always happening upon calling set_password.
|
||||
request.POST = request.POST.copy()
|
||||
request.POST['new_password1'] = normalize_password(request.POST['new_password1'])
|
||||
request.POST['new_password2'] = normalize_password(request.POST['new_password2'])
|
||||
# We have to make a copy of request.POST because it is a QueryDict object which is immutable until copied.
|
||||
# We have to use request.POST because the password_reset_confirm method takes in the request and a user's
|
||||
# password is set to the request.POST['new_password1'] field. We have to also normalize the new_password2
|
||||
# field so it passes the equivalence check that new_password1 == new_password2
|
||||
# In order to switch out of having to do this copy, we would want to move the normalize_password code into
|
||||
# a custom User model's set_password method to ensure it is always happening upon calling set_password.
|
||||
request.POST = request.POST.copy()
|
||||
request.POST['new_password1'] = normalize_password(request.POST['new_password1'])
|
||||
request.POST['new_password2'] = normalize_password(request.POST['new_password2'])
|
||||
|
||||
password = request.POST['new_password1']
|
||||
|
||||
|
||||
@@ -759,11 +759,11 @@ class IntegrationTest(testutil.TestCase, test.TestCase, HelperMixin):
|
||||
|
||||
def test_first_party_auth_trumps_third_party_auth_and_fails_when_credentials_bad(self):
|
||||
self.assert_first_party_auth_trumps_third_party_auth(
|
||||
email='user@example.com', password='password', success=False)
|
||||
email='user@example.com', password=u'password', success=False)
|
||||
|
||||
def test_first_party_auth_trumps_third_party_auth_and_succeeds_when_credentials_good(self):
|
||||
self.assert_first_party_auth_trumps_third_party_auth(
|
||||
email='user@example.com', password='password', success=True)
|
||||
email='user@example.com', password=u'password', success=True)
|
||||
|
||||
def test_full_pipeline_succeeds_registering_new_account(self):
|
||||
# First, create, the request and strategy that store pipeline state.
|
||||
|
||||
@@ -14,7 +14,6 @@ from django.contrib.auth.password_validation import (
|
||||
)
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PASSWORD_UNICODE_NORMALIZE_FLAG
|
||||
from six import text_type
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -124,16 +123,7 @@ def validate_password(password, user=None):
|
||||
Raises:
|
||||
ValidationError if any of the password validators fail.
|
||||
"""
|
||||
if not isinstance(password, text_type):
|
||||
try:
|
||||
# some checks rely on unicode semantics (e.g. length)
|
||||
password = text_type(password, encoding='utf8')
|
||||
except UnicodeDecodeError:
|
||||
# no reason to get into weeds
|
||||
raise ValidationError([_('Invalid password.')])
|
||||
|
||||
if PASSWORD_UNICODE_NORMALIZE_FLAG.is_enabled():
|
||||
password = normalize_password(password)
|
||||
password = normalize_password(password)
|
||||
django_validate_password(password, user)
|
||||
|
||||
|
||||
|
||||
@@ -9,15 +9,13 @@ from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from openedx.core.djangoapps.user_api.config.waffle import PASSWORD_UNICODE_NORMALIZE_FLAG
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from util.password_policy_validators import (
|
||||
create_validator_config, validate_password, password_validators_instruction_texts,
|
||||
)
|
||||
|
||||
|
||||
@ddt
|
||||
class PasswordPolicyValidatorsTestCase(CacheIsolationTestCase):
|
||||
class PasswordPolicyValidatorsTestCase(unittest.TestCase):
|
||||
"""
|
||||
Tests for password validator utility functions
|
||||
|
||||
@@ -66,14 +64,11 @@ class PasswordPolicyValidatorsTestCase(CacheIsolationTestCase):
|
||||
# s ̣ ̇ (s with combining dot below and combining dot above)
|
||||
not_normalized_password = u'\u0073\u0323\u0307'
|
||||
self.assertEqual(len(not_normalized_password), 3)
|
||||
# When the flag is not set, the validation should succeed since len > 2
|
||||
self.validation_errors_checker(not_normalized_password, None)
|
||||
|
||||
# When we normalize we expect the not_normalized password to fail
|
||||
# because it should be normalized to u'\u1E69' -> ṩ
|
||||
with PASSWORD_UNICODE_NORMALIZE_FLAG.override(active=True):
|
||||
self.validation_errors_checker(not_normalized_password,
|
||||
'This password is too short. It must contain at least 2 characters.')
|
||||
self.validation_errors_checker(not_normalized_password,
|
||||
'This password is too short. It must contain at least 2 characters.')
|
||||
|
||||
@data(
|
||||
([create_validator_config('util.password_policy_validators.MinimumLengthValidator', {'min_length': 2})],
|
||||
|
||||
Reference in New Issue
Block a user