from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User from django.forms.fields import email_re class EmailBackend(ModelBackend): """Allows a user to login using their email address, and not just their username. This is a lot more common than a new username. Some things that it takes care of for you are: - Allow _either_ username or email to be used - Allow anyone marked as staff in the database to mascquerade as another user by using the user they want to masquerade as as the username and using / in the password field, where is _their_ username.""" def _lookup_user(self, username): try: if email_re.search(username): # Looks like an email. Since emails are not case sensitive # and many users have a habit of typing them in mixed # cases, we will normalize them to lower case. This assumes # that the database has done the same thing. user = User.objects.get(email=username.lower()) else: user = User.objects.get(username=username) except User.DoesNotExist: return None return user def authenticate(self, username=None, password=None): user = self._lookup_user(username) if user: if user.check_password(password): return user elif '/' in password: proposed_user = user # Who we want to be (username, password) = password.split('/', 1) user = self._lookup_user(username) if user and user.is_staff: if user.check_password(password): return proposed_user return None