diff options
| author | Claude Paroz <claude@2xlibre.net> | 2016-04-22 21:17:42 +0200 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2016-05-16 19:38:02 +0200 |
| commit | 9935f97cd203bdcc722bc3d4e96858e221d96ff8 (patch) | |
| tree | bdc45bf056fc8ab8ff8bfeadf403d215aee699fb /django/contrib/auth | |
| parent | 526575c64150e10dd8666d1ed3f86eedd00df2ed (diff) | |
Refs #21379 -- Normalized unicode username inputs
Diffstat (limited to 'django/contrib/auth')
| -rw-r--r-- | django/contrib/auth/base_user.py | 8 | ||||
| -rw-r--r-- | django/contrib/auth/forms.py | 11 | ||||
| -rw-r--r-- | django/contrib/auth/models.py | 1 |
3 files changed, 18 insertions, 2 deletions
diff --git a/django/contrib/auth/base_user.py b/django/contrib/auth/base_user.py index c8f748cf02..d168262bb0 100644 --- a/django/contrib/auth/base_user.py +++ b/django/contrib/auth/base_user.py @@ -4,6 +4,8 @@ not in INSTALLED_APPS. """ from __future__ import unicode_literals +import unicodedata + from django.contrib.auth import password_validation from django.contrib.auth.hashers import ( check_password, is_password_usable, make_password, @@ -11,7 +13,7 @@ from django.contrib.auth.hashers import ( from django.db import models from django.utils.crypto import get_random_string, salted_hmac from django.utils.deprecation import CallableFalse, CallableTrue -from django.utils.encoding import python_2_unicode_compatible +from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ @@ -31,6 +33,10 @@ class BaseUserManager(models.Manager): email = '@'.join([email_name, domain_part.lower()]) return email + @classmethod + def normalize_username(cls, username): + return unicodedata.normalize('NFKC', force_text(username)) + def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyz' 'ABCDEFGHJKLMNPQRSTUVWXYZ' diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 692cdb5dab..f279f5e893 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals +import unicodedata + from django import forms from django.contrib.auth import ( authenticate, get_user_model, password_validation, @@ -60,6 +62,11 @@ class ReadOnlyPasswordHashField(forms.Field): return False +class UsernameField(forms.CharField): + def to_python(self, value): + return unicodedata.normalize('NFKC', super(UsernameField, self).to_python(value)) + + class UserCreationForm(forms.ModelForm): """ A form that creates a user, with no privileges, from the given username and @@ -83,6 +90,7 @@ class UserCreationForm(forms.ModelForm): class Meta: model = User fields = ("username",) + field_classes = {'username': UsernameField} def __init__(self, *args, **kwargs): super(UserCreationForm, self).__init__(*args, **kwargs) @@ -121,6 +129,7 @@ class UserChangeForm(forms.ModelForm): class Meta: model = User fields = '__all__' + field_classes = {'username': UsernameField} def __init__(self, *args, **kwargs): super(UserChangeForm, self).__init__(*args, **kwargs) @@ -140,7 +149,7 @@ class AuthenticationForm(forms.Form): Base class for authenticating users. Extend this to get a form that accepts username/password logins. """ - username = forms.CharField( + username = UsernameField( max_length=254, widget=forms.TextInput(attrs={'autofocus': ''}), ) diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index 8fcdf9108c..87c3adf36b 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -145,6 +145,7 @@ class UserManager(BaseUserManager): if not username: raise ValueError('The given username must be set') email = self.normalize_email(email) + username = self.normalize_username(username) user = self.model(username=username, email=email, **extra_fields) user.set_password(password) user.save(using=self._db) |
