-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed #24564 -- Moved AbstractBaseUser and BaseUserManager so they ca…
…n be used without auth in INSTALLED_APPS
- Loading branch information
Showing
4 changed files
with
131 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
""" | ||
This module allows importing AbstractBaseUser even when django.contrib.auth is | ||
not in INSTALLED_APPS. | ||
""" | ||
from __future__ import unicode_literals | ||
|
||
from django.contrib.auth.hashers import ( | ||
check_password, is_password_usable, make_password, | ||
) | ||
from django.db import models | ||
from django.utils.crypto import get_random_string, salted_hmac | ||
from django.utils.encoding import python_2_unicode_compatible | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
|
||
class BaseUserManager(models.Manager): | ||
|
||
@classmethod | ||
def normalize_email(cls, email): | ||
""" | ||
Normalize the email address by lowercasing the domain part of the it. | ||
""" | ||
email = email or '' | ||
try: | ||
email_name, domain_part = email.strip().rsplit('@', 1) | ||
except ValueError: | ||
pass | ||
else: | ||
email = '@'.join([email_name, domain_part.lower()]) | ||
return email | ||
|
||
def make_random_password(self, length=10, | ||
allowed_chars='abcdefghjkmnpqrstuvwxyz' | ||
'ABCDEFGHJKLMNPQRSTUVWXYZ' | ||
'23456789'): | ||
""" | ||
Generate a random password with the given length and given | ||
allowed_chars. The default value of allowed_chars does not have "I" or | ||
"O" or letters and digits that look similar -- just to avoid confusion. | ||
""" | ||
return get_random_string(length, allowed_chars) | ||
|
||
def get_by_natural_key(self, username): | ||
return self.get(**{self.model.USERNAME_FIELD: username}) | ||
|
||
|
||
@python_2_unicode_compatible | ||
class AbstractBaseUser(models.Model): | ||
password = models.CharField(_('password'), max_length=128) | ||
last_login = models.DateTimeField(_('last login'), blank=True, null=True) | ||
|
||
is_active = True | ||
|
||
REQUIRED_FIELDS = [] | ||
|
||
class Meta: | ||
abstract = True | ||
|
||
def get_username(self): | ||
"Return the identifying username for this User" | ||
return getattr(self, self.USERNAME_FIELD) | ||
|
||
def __str__(self): | ||
return self.get_username() | ||
|
||
def natural_key(self): | ||
return (self.get_username(),) | ||
|
||
def is_anonymous(self): | ||
""" | ||
Always return False. This is a way of comparing User objects to | ||
anonymous users. | ||
""" | ||
return False | ||
|
||
def is_authenticated(self): | ||
""" | ||
Always return True. This is a way to tell if the user has been | ||
authenticated in templates. | ||
""" | ||
return True | ||
|
||
def set_password(self, raw_password): | ||
self.password = make_password(raw_password) | ||
|
||
def check_password(self, raw_password): | ||
""" | ||
Return a boolean of whether the raw_password was correct. Handles | ||
hashing formats behind the scenes. | ||
""" | ||
def setter(raw_password): | ||
self.set_password(raw_password) | ||
self.save(update_fields=["password"]) | ||
return check_password(raw_password, self.password, setter) | ||
|
||
def set_unusable_password(self): | ||
# Set a value that will never be a valid hash | ||
self.password = make_password(None) | ||
|
||
def has_usable_password(self): | ||
return is_password_usable(self.password) | ||
|
||
def get_full_name(self): | ||
raise NotImplementedError('subclasses of AbstractBaseUser must provide a get_full_name() method') | ||
|
||
def get_short_name(self): | ||
raise NotImplementedError('subclasses of AbstractBaseUser must provide a get_short_name() method.') | ||
|
||
def get_session_auth_hash(self): | ||
""" | ||
Return an HMAC of the password field. | ||
""" | ||
key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash" | ||
return salted_hmac(key_salt, self.password).hexdigest() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters