Added new setting, widget, form and auth backend to allow login via user email address

To enable:
AUTHENTICATION_BACKENDS = ('common.auth.email_auth_backend.EmailAuthBackend',)
COMMON_LOGIN_METHOD = 'email'
This commit is contained in:
Roberto Rosario
2011-08-05 23:36:00 -04:00
parent acd6348dd7
commit 36c7beca84
7 changed files with 92 additions and 5 deletions

View File

View File

@@ -0,0 +1,23 @@
# From: http://www.micahcarrick.com/django-email-authentication.html
from django.contrib.auth.models import User, check_password
from django.contrib.auth.backends import ModelBackend
class EmailAuthBackend(ModelBackend):
"""
Email Authentication Backend
Allows a user to sign in using an email/password pair rather than
a username/password pair.
"""
def authenticate(self, email=None, password=None):
"""
Authenticate a user based on email address as the user name.
"""
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None

View File

@@ -55,3 +55,12 @@ register_setting(
global_name=u'COMMON_AUTO_ADMIN_PASSWORD',
default=u'admin',
)
register_setting(
namespace=u'common',
module=u'common.conf.settings',
name=u'LOGIN_METHOD',
global_name=u'COMMON_LOGIN_METHOD',
default=u'username',
description=_(u'Controls the mechanism used to authenticated user. Options are: username, email'),
)

View File

@@ -2,9 +2,12 @@ from django import forms
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate
from common.utils import return_attrib
from common.widgets import DetailSelectMultiple, PlainWidget, TextAreaDiv
from common.widgets import DetailSelectMultiple, PlainWidget, \
TextAreaDiv, EmailInput
class DetailForm(forms.ModelForm):
@@ -115,3 +118,29 @@ class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name')
class EmailAuthenticationForm(AuthenticationForm):
"""
Override the default authentication form to use email address
authentication
"""
email = forms.CharField(label=_(u'Email'), max_length=75,
widget=EmailInput()
)
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 self.user_cache is None:
raise forms.ValidationError(_('Please enter a correct email and password. Note that the password fields is case-sensitive.'))
elif not self.user_cache.is_active:
raise forms.ValidationError(_('This account is inactive.'))
self.check_for_test_cookie()
return self.cleaned_data
# Remove the inherited username field
EmailAuthenticationForm.base_fields.keyOrder = ['email', 'password']

View File

@@ -2,23 +2,22 @@ from django.conf.urls.defaults import patterns, url
from django.views.generic.simple import direct_to_template
from django.conf import settings
urlpatterns = patterns('common.views',
url(r'^about/$', direct_to_template, {'template': 'about.html'}, 'about'),
#url(r'^password/change/done/$', 'django.contrib.auth.views.password_change_done', {'template_name': 'password_change_done.html'}),
url(r'^password/change/done/$', 'password_change_done', (), name='password_change_done'),
url(r'^object/multiple/action/$', 'multi_object_action_view', (), name='multi_object_action_view'),
url(r'^user/$', 'current_user_details', (), 'current_user_details'),
url(r'^user/edit/$', 'current_user_edit', (), 'current_user_edit'),
url(r'^login/$', 'login_view', (), name='login_view'),
)
urlpatterns += patterns('',
url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='login_view'),
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name='logout_view'),
url(r'^password/change/$', 'django.contrib.auth.views.password_change', {'template_name': 'password_change_form.html', 'post_change_redirect': '/password/change/done/'}, name='password_change_view'),
#url(r'^password/change/done/$', 'django.contrib.auth.views.password_change_done', {'template_name': 'password_change_done.html'}),
url(r'^password/reset/$', 'django.contrib.auth.views.password_reset', {'email_template_name': 'password_reset_email.html', 'template_name': 'password_reset_form.html', 'post_reset_redirect': '/password/reset/done'}, name='password_reset_view'),
url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 'django.contrib.auth.views.password_reset_confirm', {'template_name': 'password_reset_confirm.html', 'post_reset_redirect': '/password/reset/complete/'}, name='password_reset_confirm_view'),
url(r'^password/reset/complete/$', 'django.contrib.auth.views.password_reset_complete', {'template_name': 'password_reset_complete.html'}, name='password_reset_complete_view'),

View File

@@ -7,8 +7,11 @@ from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.utils.http import urlencode
from django.contrib.auth.views import login
from common.forms import ChoiceForm, UserForm, UserForm_view
from common.forms import EmailAuthenticationForm
from common.conf.settings import LOGIN_METHOD
def password_change_done(request):
@@ -167,3 +170,14 @@ def current_user_edit(request):
'title': _(u'edit current user details'),
},
context_instance=RequestContext(request))
def login_view(request):
#url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}, name='login_view'),
#url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html', 'authentication_form': EmailAuthenticationForm}, name='login_view'),
kwargs = {'template_name': 'login.html'}
if LOGIN_METHOD == 'email':
kwargs['authentication_form'] = EmailAuthenticationForm
return login(request, **kwargs)

View File

@@ -83,3 +83,16 @@ class TextAreaDiv(forms.widgets.Widget):
conditional_escape(force_unicode(value))))
return mark_safe(result.replace('\n', '<br>'))
# From: http://www.peterbe.com/plog/emailinput-html5-django
class EmailInput(forms.widgets.Input):
input_type = 'email'
def render(self, name, value, attrs=None):
if attrs is None:
attrs = {}
attrs.update(dict(autocorrect='off',
autocapitalize='off',
spellcheck='false'))
return super(EmailInput, self).render(name, value, attrs=attrs)