You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

auth_backends.py 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import warnings
  2. from django.contrib.auth.backends import ModelBackend
  3. from django.core.exceptions import ImproperlyConfigured
  4. from oscar.apps.customer.utils import normalise_email
  5. from oscar.core.compat import get_user_model
  6. User = get_user_model()
  7. if hasattr(User, 'REQUIRED_FIELDS'):
  8. if not (User.USERNAME_FIELD == 'email' or 'email' in User.REQUIRED_FIELDS):
  9. raise ImproperlyConfigured(
  10. "EmailBackend: Your User model must have an email"
  11. " field with blank=False")
  12. class EmailBackend(ModelBackend):
  13. """
  14. Custom auth backend that uses an email address and password
  15. For this to work, the User model must have an 'email' field
  16. """
  17. def authenticate(self, email=None, password=None, *args, **kwargs):
  18. if email is None:
  19. if 'username' not in kwargs or kwargs['username'] is None:
  20. return None
  21. clean_email = normalise_email(kwargs['username'])
  22. else:
  23. clean_email = normalise_email(email)
  24. # Check if we're dealing with an email address
  25. if '@' not in clean_email:
  26. return None
  27. # Since Django doesn't enforce emails to be unique, we look for all
  28. # matching users and try to authenticate them all. Note that we
  29. # intentionally allow multiple users with the same email address
  30. # (has been a requirement in larger system deployments),
  31. # we just enforce that they don't share the same password.
  32. # We make a case-insensitive match when looking for emails.
  33. matching_users = User.objects.filter(email__iexact=clean_email)
  34. authenticated_users = [
  35. user for user in matching_users if user.check_password(password)]
  36. if len(authenticated_users) == 1:
  37. # Happy path
  38. return authenticated_users[0]
  39. elif len(authenticated_users) > 1:
  40. # This is the problem scenario where we have multiple users with
  41. # the same email address AND password. We can't safely authenticate
  42. # either.
  43. raise User.MultipleObjectsReturned(
  44. "There are multiple users with the given email address and "
  45. "password")
  46. return None
  47. # Deprecated since Oscar 0.8 because of the spelling.
  48. class Emailbackend(EmailBackend):
  49. def __init__(self):
  50. warnings.warn(
  51. "Oscar's auth backend EmailBackend has been renamed in Oscar 0.8 "
  52. " and you're using the old name of Emailbackend. Please rename "
  53. " all references; most likely in the AUTH_BACKENDS setting.",
  54. DeprecationWarning)
  55. super(Emailbackend, self).__init__()