lzantal avatar lzantal committed 03ecced

Imported in the full emailauth app

Comments (0)

Files changed (17)

+
+Registration and Login with Email address for Django
+=========================================================
+
+---------
+Install::
+---------
+To install run:
+pip install hg+https://bitbucket.org/lzantal/django-emailauth
+
+Add it to your INSTALLED_APPS:
+INSTALLED_APPS = (
+        'django.contrib.auth',
+        'django.contrib.sites',
+        'emailauth',
+        # ...other installed applications...
+)
+
+Add it to your project urls:
+(r'^emailauth/', include('emailauth.urls')),
+
+---------------
+Configuration::
+---------------
+
+Registration:
+-------------
+
+If you don't want free email signups set this to True,
+defaults to False
+EMAILAUTH_NO_FREE_EMAIL = True/False
+
+If you don't want users to register set this to False 
+defaults to True
+EMAILAUTH_REGISTER_OPEN = True/False
+
+Where to redirect after registering
+defaults to 'emailauth-register-complete'
+EMAILAUTH_REGISTER_REDIRECT = 'url-name'
+
+Where to redirect if the registration is closed
+defaults to 'emailauth-register-closed'
+EMAILAUTH_REGISTER_CLOSED_REDIRECT = 'url-name'
+
+Login:
+------
+
+If you don't want users to login set this to False 
+defaults to True
+EMAILAUTH_LOGIN_OPEN = True/False
+
+Where to redirect if the login is closed
+defaults to 'emailauth-login-closed'
+EMAILAUTH_LOGIN_CLOSED_REDIRECT = 'ur-name'
+
+Where to redirect after login
+defaults to 'emailauth-login-complete'
+EMAILAUTH_LOGIN_REDIRECT = 'url-name'
+
+Where to redirect after login
+defaults to 'emailauth-logout'
+EMAILAUTH_LOGOUT_REDIRECT = 'url-name'
+
+

emailauth/__init__.py

+VERSION = (0, 1, 2)

emailauth/forms.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+from django import forms
+from django.contrib.auth import authenticate
+from django.contrib.auth.models import User
+
+
+class EmailLoginForm(forms.Form):
+    email = forms.EmailField(widget=forms.TextInput(attrs={'maxlength':'150','class': 'required'}))
+    password = forms.CharField(widget=forms.PasswordInput(render_value=False), label="Password")
+    
+    def __init__(self):
+        self.user = None
+    
+    def clean(self):
+        email = self.cleaned_data.get('email')
+        password = self.cleaned_data.get('password')
+        
+        if email and password:
+            try:
+                self.user = User.objects.get(email=email)
+            except:
+                raise forms.ValidationError(_("Please enter a correct Email and Password"))
+            
+            self.user = authenticate(username=self.user.username, password=password)
+            if self.user is None:
+                raise forms.ValidationError(_("Please enter a correct Email and Password"))
+            elif not self.user.is_active:
+                raise forms.ValidationError(_("This account is inactive."))
+        
+        return self.cleaned_data
+    
+
+class EmailRegistrationForm(forms.Form):
+    """
+    Form for registering a new user account.
+    Validates that the requested email is not already in use, and
+    requires the password to be entered twice to catch typos.
+    """
+    email = forms.EmailField(widget=forms.TextInput(attrs={'maxlength':'150', 'class': 'required'}))
+    password1 = forms.CharField(widget=forms.PasswordInput(render_value=False), label="Password")
+    password2 = forms.CharField(widget=forms.PasswordInput(render_value=False), label="Password (again)")
+    
+    def clean_email(self):
+        """
+        Validate that the supplied email address is unique
+        """
+        if User.objects.filter(email__iexact=self.cleaned_data['email']):
+            raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
+        return self.cleaned_data['email']
+    
+    def clean(self):
+        """
+        Verifiy that the values entered into the two password fields match
+        """
+        if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:
+            if self.cleaned_data['password1'] != self.cleaned_data['password2']:
+                raise forms.ValidationError(_("The two password fields didn't match."))
+        return self.cleaned_data
+
+
+class EmailRegistrationFormNoFreeEmail(EmailRegistrationForm):
+    """
+    Disallows registration with email addresses from popular free webmail services.
+    Moderately useful for preventing automated spam registrations.
+    To change the list of banned domains, subclass this form and
+    override the attribute bad_domains.
+    """
+    bad_domains = ['aim.com', 'aol.com', 'email.com', 'gmail.com',
+                   'googlemail.com', 'hotmail.com', 'hushmail.com',
+                   'msn.com', 'mail.ru', 'mailinator.com', 'live.com',
+                   'yahoo.com']
+    
+    def clean_email(self):
+        """
+        Check the supplied email address against a list of known free webmail domains.
+        """
+        email_domain = self.cleaned_data['email'].split('@')[1]
+        if email_domain in self.bad_domains:
+            raise forms.ValidationError(_("Registration using free email addresses is prohibited. Please supply a different email address."))
+        if User.objects.filter(email__iexact=self.cleaned_data['email']):
+            raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
+        return self.cleaned_data['email']

emailauth/login_backend.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+from django.conf import settings
+#
+from forms import EmailLoginForm
+from uniqueid import unique_username
+
+
+class EmailAuthLoginBackend(object):
+    
+    def login_allowed(self, request):
+        return getattr(settings, 'EMAILAUTH_LOGIN_OPEN', True)
+    
+    def login_closed_redirect(self, request):
+        return getattr(settings, 'EMAILAUTH_LOGIN_CLOSED_REDIRECT', 'emailauth-login-closed')
+    
+    def form_class(self, request):
+        return EmailLoginForm
+    
+    def login_success_redirect(self, request):
+        return getattr(settings, 'EMAILAUTH_LOGIN_REDIRECT', 'emailauth-login-complete')
+    
+    def logout_redirect(self, request):
+        return getattr(settings, 'EMAILAUTH_LOGOUT_REDIRECT', 'emailauth-logout')

emailauth/register_backend.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+from django.core.urlresolvers import reverse
+#
+from uniqueid import unique_username
+
+
+class EmailAuthRegisterBackend(object):
+    
+    def register(self, request, **kwargs):
+        email, password = kwargs['email'], kwargs['password1']
+        # pass in 'e' for the fname and lname so it will use random
+        # string if it can't generate it from email
+        username = unique_username(email, 'e', 'e')
+        User.objects.create_user(username, email, password)
+        newuser = authenticate(username=username, password=password)
+        login(request, new_user)
+        
+        return newuser
+    
+    def registration_allowed(self, request):
+        return getattr(settings, 'EMAILAUTH_REGISTER_OPEN', True)
+    
+    def registration_closed_redirect(self, request):
+        return getattr(settings, 'EMAILAUTH_REGISTER_CLOSED_REDIRECT', 'emailauth-register-closed')
+    
+    def no_free_email(self, request):
+        return getattr(settings, 'EMAILAUTH_NO_FREE_EMAIL', False)
+    
+    def form_class(self, request):
+        if self.no_free_email(request):
+            return EmailRegistrationFormNoFreeEmail
+        else:
+            return EmailRegistrationForm
+    
+    def registration_success_redirect(self, request):
+        return getattr(settings, 'EMAILAUTH_REGISTER_REDIRECT', 'emailauth-register-complete')

emailauth/templates/emailauth/base.html

+{% extends "base.html" %}

emailauth/templates/emailauth/login.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<form method="post" action=".">
+{% csrf_token %}
+  {{ form.as_p }}
+  <input type="submit" value="Login" />
+  <input type="hidden" name="next" value="{{ next }}" />
+</form>
+{% endblock %}

emailauth/templates/emailauth/login_closed.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<h2>Login Closed.</h2>
+{% endblock %}

emailauth/templates/emailauth/login_complete.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<h2>You are now logged in</h2>
+{% endblock %}

emailauth/templates/emailauth/logout.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<h2>Logged out</h2>
+{% endblock %}

emailauth/templates/emailauth/register.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<form method="post" action=".">
+{% csrf_token %}
+  {{ form.as_p }}
+  <input type="submit" value="Register">
+</form>
+{% endblock %}

emailauth/templates/emailauth/register_closed.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<h2>Registration Closed.</h2>
+{% endblock %}

emailauth/templates/emailauth/register_complete.html

+{% extends "emailauth/base.html" %}
+
+{% block content %}
+<h2>Thank you for registering.</h2>
+{% endblock %}

emailauth/uniqueid.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+
+import string
+import random
+#
+from django.contrib.auth.models import User
+
+MAX_USERNAME = 30
+MIN_USERNAME = 6
+# util func to use it in filter
+alnum = lambda x: x.isalnum()
+
+def _uniqueid(salt):
+    return ''.join(filter(alnum, salt)).lower()
+
+def _randstring(length=6):
+    return ''.join([random.choice(string.letters) for x in range(length)])
+
+def _gen_username(email, otherstr1, otherstr2):
+    '''
+    generator returns usernames
+    1: tries just the email address before the @
+    2: tries the entire email removing none alpha chars
+    3: tries with the otherstr1 + otherstr2 which could be firstname and lastname
+    4: generates random string
+    '''
+    uid = _uniqueid(email.split('@')[0])
+    if len(uid) >= MIN_USERNAME:
+        yield uid[:MAX_USERNAME]
+    uid = _uniqueid(email)
+    if len(uid) >= MIN_USERNAME:
+        yield uid[:MAX_USERNAME]
+    uid = _uniqueid(otherstr1+otherstr2)
+    if len(uid) >= MIN_USERNAME:
+        yield uid[:MAX_USERNAME]
+    # no cookie lets run an infinite loop
+    while True:
+        yield _randstring(MAX_USERNAME)
+
+def unique_username(email, fname, lname):
+    '''
+    calls _gen_username until it finds a unique username
+    and then returns it
+    '''
+    gen = _gen_username(email, fname, lname)
+    uname = gen.next()
+    while 1:
+        try:
+            User.objects.get(username=uname)
+        except User.DoesNotExist:
+            break
+        else:
+            uname = gen.next()
+    return uname

emailauth/urls.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+#
+from views import emailauth_register, emailauth_login, emailauth_logout
+
+urlpatterns = patterns('',
+                       url(r'^register/$', emailauth_register, name='emailauth-register'),
+                       url(r'^register/complete/$', direct_to_template, {'template': 'emailauth/register_complete.html'}, name='emailauth-register-complete'),
+                       url(r'^register/closed/$', direct_to_template, {'template': 'emailauth/register_closed.html'}, name='emailauth-register-closed'),
+                       url(r'^login/$', emailauth_login, name='emailauth-login'),
+                       url(r'^login/complete/$', direct_to_template, {'template': 'emailauth/login_complete.html'}, name='emailauth-login-complete'),
+                       url(r'^login/closed/$', direct_to_template, {'template': 'emailauth/login_closed.html'}, name='emailauth-login-closed'),
+                       url(r'^logout/$', emailauth_logout, name='emailauth-logout'),
+                       )

emailauth/views.py

+'''
+Copyright (c) All rights reserved.
+
+@author: lzantal >> http://twitter.com/lzantal
+
+'''
+from django.conf import settings
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.models import User
+from django.shortcuts import render, redirect
+#
+from uniqueid import unique_username
+from register_backend import EmailAuthRegisterBackend
+from login_backend import EmailAuthLoginBackend
+
+
+def emailauth_register(request, template="emailauth/register.html"):
+    ctx = {}
+    backend = EmailAuthRegisterBackend()
+    if not backend.registration_allowed(request):
+        return redirect(backend.registration_closed_redirect())
+    form_class = backend.form_class()
+    if request.method == 'POST':
+        form = form_class(request.POST)
+        if form.is_valid():
+            new_user = backend.register(request, **form.cleaned_data)
+            return redirect(registration_success_redirect)
+    else:
+        form = form_class()
+    ctx['form'] = form
+    return render(request, template, ctx)
+
+
+def emailauth_login(request, template="emailauth/login.html"):
+    ctx = {}
+    backend = EmailAuthLoginBackend()
+    if not backend.login_allowed(request):
+        return redirect(backend.login_closed_redirect(request))
+    form_class = backend.form_class()
+    if request.method == 'POST':
+        form = form_class(request.POST)
+        if form.is_valid():
+            login(request, form.user)
+            redirect(backend.login_success_redirect(request))
+    else:
+        form = form_class()
+    ctx['form'] = form
+    
+    return render(request, template, ctx)
+
+
+def emailauth_logout(request, template="emailauth/logout.html"):
+    backend = EmailAuthLoginBackend()
+    logout(request)
+    return redirect(backend.logout_redirect(request))
+
+from setuptools import setup, find_packages
+from emailauth import VERSION
+
+
+# Dynamically calculate the version based on VERSION tuple
+if len(VERSION)>2 and VERSION[2] is not None:
+    str_version = "%d.%d_%s" % VERSION[:3]
+else:
+    str_version = "%d.%d" % VERSION[:2]
+
+version= str_version
+
+setup(
+    name = 'django-emailauth',
+    version = version,
+    description = "Django authentication and registration using email address.",
+    long_description = "Django authentication and registration using email address.",
+    author = 'lzantal',
+    author_email = 'lzantal@gmail.com',
+    url = 'https://bitbucket.org/lzantal/django-emailauth/',
+    license = '',
+    package_dir={'emailauth': 'emailauth'},
+    platforms = ['any'],
+    packages = find_packages(),
+    include_package_data = True,
+)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.