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:
0
apps/common/auth/__init__.py
Normal file
0
apps/common/auth/__init__.py
Normal file
23
apps/common/auth/email_auth_backend.py
Normal file
23
apps/common/auth/email_auth_backend.py
Normal 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
|
||||||
@@ -55,3 +55,12 @@ register_setting(
|
|||||||
global_name=u'COMMON_AUTO_ADMIN_PASSWORD',
|
global_name=u'COMMON_AUTO_ADMIN_PASSWORD',
|
||||||
default=u'admin',
|
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'),
|
||||||
|
)
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ from django import forms
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import User
|
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.utils import return_attrib
|
||||||
from common.widgets import DetailSelectMultiple, PlainWidget, TextAreaDiv
|
from common.widgets import DetailSelectMultiple, PlainWidget, \
|
||||||
|
TextAreaDiv, EmailInput
|
||||||
|
|
||||||
|
|
||||||
class DetailForm(forms.ModelForm):
|
class DetailForm(forms.ModelForm):
|
||||||
@@ -115,3 +118,29 @@ class UserForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ('first_name', 'last_name')
|
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']
|
||||||
|
|||||||
@@ -2,23 +2,22 @@ from django.conf.urls.defaults import patterns, url
|
|||||||
from django.views.generic.simple import direct_to_template
|
from django.views.generic.simple import direct_to_template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns('common.views',
|
urlpatterns = patterns('common.views',
|
||||||
url(r'^about/$', direct_to_template, {'template': 'about.html'}, 'about'),
|
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'^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'^object/multiple/action/$', 'multi_object_action_view', (), name='multi_object_action_view'),
|
||||||
|
|
||||||
url(r'^user/$', 'current_user_details', (), 'current_user_details'),
|
url(r'^user/$', 'current_user_details', (), 'current_user_details'),
|
||||||
url(r'^user/edit/$', 'current_user_edit', (), 'current_user_edit'),
|
url(r'^user/edit/$', 'current_user_edit', (), 'current_user_edit'),
|
||||||
|
|
||||||
|
url(r'^login/$', 'login_view', (), name='login_view'),
|
||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns += patterns('',
|
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'^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/$', '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/$', '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/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'),
|
url(r'^password/reset/complete/$', 'django.contrib.auth.views.password_reset_complete', {'template_name': 'password_reset_complete.html'}, name='password_reset_complete_view'),
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ from django.contrib import messages
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.utils.http import urlencode
|
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 ChoiceForm, UserForm, UserForm_view
|
||||||
|
from common.forms import EmailAuthenticationForm
|
||||||
|
from common.conf.settings import LOGIN_METHOD
|
||||||
|
|
||||||
|
|
||||||
def password_change_done(request):
|
def password_change_done(request):
|
||||||
@@ -167,3 +170,14 @@ def current_user_edit(request):
|
|||||||
'title': _(u'edit current user details'),
|
'title': _(u'edit current user details'),
|
||||||
},
|
},
|
||||||
context_instance=RequestContext(request))
|
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)
|
||||||
|
|||||||
@@ -83,3 +83,16 @@ class TextAreaDiv(forms.widgets.Widget):
|
|||||||
conditional_escape(force_unicode(value))))
|
conditional_escape(force_unicode(value))))
|
||||||
|
|
||||||
return mark_safe(result.replace('\n', '<br>'))
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user