initial commit
This commit is contained in:
commit
e0c5d0989f
|
@ -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']
|
|
@ -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()
|
|
@ -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'),
|
||||
)
|
||||
|
|
@ -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)
|
Reference in New Issue