initial commit

This commit is contained in:
Serghei Mihai 2014-07-25 16:56:19 +02:00
commit e0c5d0989f
6 changed files with 198 additions and 0 deletions

View File

View File

View File

@ -0,0 +1,14 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from registration.forms import RegistrationForm
from .models import ldap_manager
class LDAPRegistrationForm(RegistrationForm):
def clean_username(self):
if ldap_manager.existing_user(self.cleaned_data['username']):
raise forms.ValidationError(_("A user with that username already exists."))
else:
return self.cleaned_data['username']

View File

@ -0,0 +1,103 @@
import re
import random
import hashlib
from datetime import datetime
import dateutil.parser
import logging
from django.conf import settings
from django.utils.timezone import now
from registration.models import SHA1_RE, RegistrationProfile
import ldap
import ldap.modlist
log = logging.getLogger(__name__)
registration_settings = settings.LDAP_REGISTRATION_BACKEND_SETTINGS
class LDAPUserManager(object):
def __init__(self, uri=None, dn=None, password=None):
"""
Example:
uri: ldap://localhost
dn: "cn=admin,dc=entrouvert,dc=org"
basedn: "ou=people,dc=entrouvert,dc=org"
"""
uri = uri or registration_settings['uri']
login_dn = dn or registration_settings['binddn']
login_pw = password or registration_settings['bindpw']
self.path = registration_settings['users_dn']
self.user_dn = registration_settings['user_dn']
self.activation_token_field_name = registration_settings['activation_token_field']
self.fields = registration_settings['fields']
self.ACTIVATED = RegistrationProfile.ACTIVATED
try:
self.connection = ldap.initialize(uri)
self.connection.whoami_s()
except ldap.SERVER_DOWN:
log.error('ldap server down')
try:
self.connection.simple_bind_s(login_dn, login_pw)
except ldap.INVALID_CREDENTIALS:
log.warning('invalid credentials')
def create_inactive_user(self, username, email, password, site):
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
activation_token = hashlib.sha1(salt+email).hexdigest()
user_attrs = ()
data = {'username': str(username), 'password': str(password),
'email': str(email), 'activation_token': activation_token,
'activation_token_field': self.activation_token_field_name}
for key, value in self.fields.iteritems():
if key != 'objectClass':
value = value.format(**data)
user_attrs += ((key, value),)
# data = (('givenName', str(username)),
# ('mail', str(email)),
# ('userPassword', str(password)),
# ('objectClass', ('authenticEmailValidation', 'cudPeople')),
# (self.token_field_name, activation_token),
# ('creationDate', datetime.now().isoformat())
# )
self.connection.add_s('{0},{1}'.format(self.user_dn % str(username), self.path),
user_attrs)
def activate_user(self, activation_key):
if SHA1_RE.search(activation_key):
result = self.connection.search_s(self.path, ldap.SCOPE_ONELEVEL,
'{0}={1}'.format(self.activation_token_field_name,
activation_key))
if result:
[(dn, attrs)] = result
old_data = {self.activation_token_field_name: [attrs[self.activation_token_field_name][0].encode('utf-8')]}
new_data = {self.activation_token_field_name: [self.ACTIVATED.encode('utf-8')]}
return self.connection.modify_s(dn, ldap.modlist.modifyModlist(old_data, new_data))
return False
return False
def existing_user(self, username):
return self.connection.search_s(self.path, ldap.SCOPE_ONELEVEL,
self.user_dn % str(username))
def activation_key_expired(self, user_attrs):
expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
return activation_key == self.ACTIVATED or \
(dateutil.parser.parse(user_attrs['creationDate']) + expiration_date <= now())
def delete_expired_users(self):
users = self.connection.search_s(self.path, ldap.SCOPE_ONELEVEL, 'sn=*')
if users:
[(dn, attrs)] = users
for user_attrs in attrs:
if self.activation_key_expired(user):
self.connection.delete_s(dn)
ldap_manager = LDAPUserManager()

View File

@ -0,0 +1,43 @@
"""
URLconf for registration and activation, using django-registration's
default backend.
If the default behavior of these views is acceptable to you, simply
use a line like this in your root URLconf to set up the default URLs
for registration::
(r'^accounts/', include('registration.backends.default.urls')),
This will also automatically set up the views in
``django.contrib.auth`` at sensible default locations.
If you'd like to customize registration behavior, feel free to set up
your own URL patterns for these views instead.
"""
from django.conf.urls import patterns
from django.conf.urls import include
from django.conf.urls import url
from django.views.generic.base import TemplateView
from .views import ActivationView, RegistrationView
urlpatterns = patterns('',
url(r'^activate/complete/$',
TemplateView.as_view(template_name='registration/activation_complete.html'),
name='registration_activation_complete'),
url(r'^activate/(?P<activation_key>\w+)/$',
ActivationView.as_view(),
name='registration_activate'),
url(r'^register/$',
RegistrationView.as_view(),
name='registration_register'),
url(r'^register/complete/$',
TemplateView.as_view(template_name='registration/registration_complete.html'),
name='registration_complete'),
)

View File

@ -0,0 +1,38 @@
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth import login
from django.contrib.sites.models import RequestSite
from django.contrib.sites.models import Site
from django.shortcuts import redirect
from registration.backends.default.views import RegistrationView as DefaultRegistrationView
from registration.backends.default.views import ActivationView as DefaultActivationView
from registration import signals
from .models import ldap_manager
from .forms import LDAPRegistrationForm
class RegistrationView(DefaultRegistrationView):
form_class = LDAPRegistrationForm
def register(self, request, **cleaned_data):
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
user = ldap_manager.create_inactive_user(cleaned_data['username'],
cleaned_data['email'],
cleaned_data['password1'], site)
signals.user_registered.send(sender=self.__class__,
user=user,
request=request)
return user
class ActivationView(DefaultActivationView):
def activate(self, request, activation_key):
return ldap_manager.activate_user(activation_key)