Created
March 26, 2012 11:57
-
-
Save c4urself/2204633 to your computer and use it in GitHub Desktop.
Django email
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 enables email-based authentication for Django. The only steps required are | |
1. Add 'EmailAuthenticationBackend' to your settings' AUTHENTICATION_BACKENDS file | |
2. Add the {'authentication_form': EmailAuthenticationForm} to your login view (if using 'django.contrib.auth.views.login') | |
3. When saving a User instance, generate the username from the email using the 'generate_hash_from_email' function | |
""" | |
import hashlib | |
from django import forms | |
from django.contrib.auth.models import User, check_password | |
from django.contrib.auth import authenticate | |
from django.core.exceptions import MultipleObjectsReturned | |
from django.core.validators import email_re | |
def generate_hash_from_email(email_string): | |
""" | |
Make a hash of the email to store as a username (no longer than 30 characters) | |
This ensures that the emails stay unique as only the username field in the User model is required to be unique. | |
""" | |
m = hashlib.md5() | |
m.update(email_string.lower()) | |
return m.hexdigest()[:30] | |
class BasicBackend: | |
"""Basic backend: used by EmailAuthenticationBackend""" | |
def get_user(self, user_id): | |
try: | |
return User.objects.get(pk=user_id) | |
except User.DoesNotExist: | |
return None | |
class EmailAuthenticationBackend(BasicBackend): | |
"""Backend used by django authentication: set in base.py""" | |
def authenticate(self, email=None, password=None): | |
if email_re.search(email): | |
try: | |
user = User.objects.get(email=email) | |
except User.DoesNotExist: | |
user = None | |
except MultipleObjectsReturned: | |
user = None | |
else: | |
if not user.check_password(password): | |
user = None | |
finally: | |
return user | |
return None | |
class EmailAuthenticationForm(forms.Form): | |
"""Email login form: passed to django.contrib.auth.login""" | |
email = forms.CharField(label="Email", max_length=75) | |
password = forms.CharField(label="Password", widget=forms.PasswordInput) | |
def __init__(self, request=None, *args, **kwargs): | |
self.request = request | |
self.user_cache = None | |
super(EmailAuthenticationForm, self).__init__(*args, **kwargs) | |
def clean(self): | |
email = self.cleaned_data.get('email') | |
password = self.cleaned_data.get('password') | |
if email and password: | |
self.user_cache = authenticate(email=email, password=password) | |
if not email_re.search(email): | |
raise forms.ValidationError("Please enter a valid email") | |
if self.user_cache is None: | |
raise forms.ValidationError("Please enter a correct email and password.") | |
elif not self.user_cache.is_active: | |
raise forms.ValidationError("This account is inactive.") | |
if self.request: | |
if not self.request.session.test_cookie_worked(): | |
raise forms.ValidationError("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.") | |
return self.cleaned_data | |
def get_user_id(self): | |
if self.user_cache: | |
return self.user_cache.id | |
return None | |
def get_user(self): | |
return self.user_cache |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment