diff --git a/helios_auth/auth_systems/__init__.py b/helios_auth/auth_systems/__init__.py index aaaddb56b6b5a29d4a414b4c34b2ba4a11278085..5a0e9233ba4df89067688283e90649aef4f1ae70 100644 --- a/helios_auth/auth_systems/__init__.py +++ b/helios_auth/auth_systems/__init__.py @@ -2,9 +2,6 @@ AUTH_SYSTEMS = {} import twitter, password, cas, facebook, google, yahoo, linkedin, clever -import ldapauth - - AUTH_SYSTEMS['twitter'] = twitter AUTH_SYSTEMS['linkedin'] = linkedin AUTH_SYSTEMS['password'] = password @@ -13,7 +10,6 @@ AUTH_SYSTEMS['facebook'] = facebook AUTH_SYSTEMS['google'] = google AUTH_SYSTEMS['yahoo'] = yahoo AUTH_SYSTEMS['clever'] = clever -AUTH_SYSTEMS['ldap'] = ldapauth # not ready #import live diff --git a/helios_auth/auth_systems/ldapauth.py b/helios_auth/auth_systems/ldapauth.py deleted file mode 100644 index 4e201f94ce2fef763c8891ea3ca57240fac76fb9..0000000000000000000000000000000000000000 --- a/helios_auth/auth_systems/ldapauth.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- -""" -LDAP Authentication -Author : shirlei@gmail.com -Version: 1.0 -Requires libldap2-dev -django-auth-ldap 1.2.7 -LDAP authentication relies on django-auth-ldap (http://pythonhosted.org/django-auth-ldap/), -which considers that "Authenticating against an external source is swell, but Django’s -auth module is tightly bound to a user model. When a user logs in, we have to create a model -object to represent them in the database." -Helios, originally, does not rely on default django user model. Discussion about that can be -found in: -https://groups.google.com/forum/#!topic/helios-voting/nRHFAbAHTNA -That considered, using a django plugin for ldap authentication, in order to not reinvent the -wheel seems ok, since it does not alter anything on original helios user model, it is just -for authentication purposes. -However, two installed_apps that are added when you first create a django project, which were -commented out in helios settings, need to be made available now: -django.contrib.auth -django.contrib.contenttypes' -This will enable the native django authentication support on what django-auth-ldap is build upon. -Further reference on -https://docs.djangoproject.com/en/1.8/topics/auth/ -""" - -from django import forms -from django.conf import settings -from django.core.mail import send_mail -from django.core.urlresolvers import reverse -from django.http import HttpResponseRedirect - - -from helios_auth.auth_systems.ldapbackend import backend - - -# some parameters to indicate that status updating is possible -STATUS_UPDATES = False - - -LOGIN_MESSAGE = "Log in with my LDAP Account" - -class LoginForm(forms.Form): - username = forms.CharField(max_length=250) - password = forms.CharField(widget=forms.PasswordInput(), max_length=100) - - -def ldap_login_view(request): - from helios_auth.view_utils import render_template - from helios_auth.views import after - - error = None - - if request.method == "GET": - form = LoginForm() - else: - form = LoginForm(request.POST) - - request.session['auth_system_name'] = 'ldap' - - if request.POST.has_key('return_url'): - request.session['auth_return_url'] = request.POST.get('return_url') - - if form.is_valid(): - username = form.cleaned_data['username'].strip() - password = form.cleaned_data['password'].strip() - - auth = backend.CustomLDAPBackend() - user = auth.authenticate(username, password) - - if user: - request.session['ldap_user'] = { - 'user_id': user.email, - 'name': user.first_name + ' ' + user.last_name, - } - return HttpResponseRedirect(reverse(after)) - else: - error = 'Bad Username or Password' - - return render_template(request, 'password/login', { - 'form': form, - 'error': error, - 'enabled_auth_systems': settings.AUTH_ENABLED_AUTH_SYSTEMS, - }) - - -def get_user_info_after_auth(request): - return { - 'type': 'ldap', - 'user_id' : request.session['ldap_user']['user_id'], - 'name': request.session['ldap_user']['name'], - 'info': {'email': request.session['ldap_user']['user_id']}, - 'token': None - } - - -def get_auth_url(request, redirect_url = None): - return reverse(ldap_login_view) - - -def send_message(user_id, name, user_info, subject, body): - send_mail(subject, body, settings.SERVER_EMAIL, ["%s <%s>" % (name, user_id)], fail_silently=False) - - -def check_constraint(constraint, user_info): - """ - for eligibility - """ - pass - -def can_create_election(user_id, user_info): - return True - diff --git a/helios_auth/auth_systems/ldapbackend/__init__.py b/helios_auth/auth_systems/ldapbackend/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/helios_auth/auth_systems/ldapbackend/backend.py b/helios_auth/auth_systems/ldapbackend/backend.py deleted file mode 100644 index 5d3060120b0dc860e61d942a2a29715fa11ca999..0000000000000000000000000000000000000000 --- a/helios_auth/auth_systems/ldapbackend/backend.py +++ /dev/null @@ -1,28 +0,0 @@ -from django.core.exceptions import ImproperlyConfigured - -from django_auth_ldap.backend import LDAPBackend -from django_auth_ldap.config import LDAPSearch -from django_auth_ldap.backend import populate_user - - -class CustomLDAPBackend(LDAPBackend): - def authenticate(self, username, password): - """ - Some ldap servers allow anonymous search, returning just a subset - of user attributes. So here we re-perform search after user is authenticated, - in order to populate other user attributes. - For now, just in cases where AUTH_LDAP_BIND_PASSWORD is empty - """ - user = super(CustomLDAPBackend, self).authenticate(username, password) - - if user and self.settings.BIND_PASSWORD == '' : - search = self.settings.USER_SEARCH - if search is None: - raise ImproperlyConfigured('AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance.') - results = search.execute(user.ldap_user.connection, {'user': user.username}) - if results is not None and len(results) == 1: - (user.ldap_user._user_dn, user.ldap_user.user_attrs) = results[0] - user.ldap_user._load_user_attrs() - user.ldap_user._populate_user_from_attributes() - user.save() - return user diff --git a/helios_auth/media/login-icons/ldap.png b/helios_auth/media/login-icons/ldap.png deleted file mode 100644 index 86f7807cbcf9f8d5add2c9450a1cf74b30ff1cb6..0000000000000000000000000000000000000000 Binary files a/helios_auth/media/login-icons/ldap.png and /dev/null differ diff --git a/helios_auth/tests.py b/helios_auth/tests.py index b6cb5ddd6ceb77ba0e13dfdac783fa16dcb08e99..f07f309fb5176007ca67a25ce14c712efc33af35 100644 --- a/helios_auth/tests.py +++ b/helios_auth/tests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Unit Tests for Auth Systems """ @@ -14,7 +13,6 @@ from django.test import TestCase from django.core import mail from auth_systems import AUTH_SYSTEMS -from helios_auth import ENABLED_AUTH_SYSTEMS class UserModelTests(unittest.TestCase): @@ -27,10 +25,10 @@ class UserModelTests(unittest.TestCase): """ for auth_system, auth_system_module in AUTH_SYSTEMS.iteritems(): models.User.objects.create(user_type = auth_system, user_id = 'foobar', info={'name':'Foo Bar'}) - + def double_insert(): models.User.objects.create(user_type = auth_system, user_id = 'foobar', info={'name': 'Foo2 Bar'}) - + self.assertRaises(IntegrityError, double_insert) transaction.rollback() @@ -57,7 +55,7 @@ class UserModelTests(unittest.TestCase): assert(hasattr(auth_system_module, 'can_create_election')) if auth_system != 'clever': assert(auth_system_module.can_create_election('foobar', {})) - + def test_status_update(self): """ @@ -119,7 +117,7 @@ class UserBlackboxTests(TestCase): def test_logout(self): response = self.client.post(reverse(views.logout), follow=True) - + self.assertContains(response, "not logged in") self.assertNotContains(response, "Foobar User") @@ -130,197 +128,3 @@ class UserBlackboxTests(TestCase): self.assertEquals(len(mail.outbox), 1) self.assertEquals(mail.outbox[0].subject, "testing subject") self.assertEquals(mail.outbox[0].to[0], "\"Foobar User\" <foobar-test@adida.net>") - - -''' - tests for LDAP auth module. - Much of the code below was get or inspired on django-auth-ldap package. - See site-packages/django_ldap_auth/tests.py -''' -import ldap - -import auth_systems.ldapauth as ldap_views -from mockldap import MockLdap -from django_auth_ldap.backend import LDAPSettings -from django_auth_ldap.config import LDAPSearch -from helios_auth.auth_systems.ldapbackend.backend import CustomLDAPBackend -try: - from django.test.utils import override_settings -except ImportError: - override_settings = lambda *args, **kwargs: (lambda v: v) - - -class TestSettings(LDAPSettings): - """ - A replacement for backend.LDAPSettings that does not load settings - from django.conf. - """ - def __init__(self, **kwargs): - for name, default in self.defaults.items(): - value = kwargs.get(name, default) - setattr(self, name, value) - - -class LDAPAuthTests(TestCase): - """ - These tests uses mockldap 0.2.7 https://pypi.python.org/pypi/mockldap/ - """ - - top = ("o=test", {"o": "test"}) - people = ("ou=people,o=test", {"ou": "people"}) - groups = ("ou=groups,o=test", {"ou": "groups"}) - - alice = ("uid=alice,ou=people,o=test", { - "uid": ["alice"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1000"], - "gidNumber": ["1000"], - "givenName": ["Alice"], - "sn": ["Adams"], - "mail": ["alice@example.com"] - }) - bob = ("uid=bob,ou=people,o=test", { - "uid": ["bob"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1001"], - "gidNumber": ["50"], - "givenName": ["Robert"], - "sn": ["Barker"], - "mail": ["bob@example.com"] - }) - john = ("uid=john,ou=people,o=test", { - "uid": ["john"], - "objectClass": ["person", "organizationalPerson", "inetOrgPerson", "posixAccount"], - "userPassword": ["password"], - "uidNumber": ["1002"], - "gidNumber": ["60"], - "givenName": ["Robert"], - "sn": ["Doe"] - }) - - directory = dict([top, people, groups, alice, bob, john]) - - def _init_settings(self, **kwargs): - self.backend.settings = TestSettings(**kwargs) - - @classmethod - def setUpClass(cls): - cls.mockldap = MockLdap(cls.directory) - - @classmethod - def tearDownClass(cls): - del cls.mockldap - - def setUp(self): - self.mockldap.start() - self.ldapobj = self.mockldap['ldap://localhost'] - - self.backend = CustomLDAPBackend() - self.backend.ldap # Force global configuration - - def tearDown(self): - self.mockldap.stop() - del self.ldapobj - - def test_backend_login(self): - """ Test authentication usign correct username/password """ - if 'ldap' in ENABLED_AUTH_SYSTEMS: - self._init_settings( - BIND_DN='uid=bob,ou=people,o=test', - BIND_PASSWORD='password', - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - user = self.backend.authenticate(username='alice', password='password') - self.assertTrue(user is not None) - - def test_backend_bad_login(self): - """ Test authentication using incorrect username/password""" - if 'ldap' in ENABLED_AUTH_SYSTEMS: - self._init_settings( - BIND_DN='uid=bob,ou=people,o=test', - BIND_PASSWORD='password', - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - user = self.backend.authenticate(username='maria', password='password') - self.assertTrue(user is None) - - @override_settings(AUTH_LDAP_BIND_DN='uid=bob,ou=people,o=test', - AUTH_LDAP_BIND_PASSWORD='password',AUTH_LDAP_USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - def test_ldap_view_login_with_bind_credentials(self): - """ Test if authenticates using the auth system login view """ - if 'ldap' in ENABLED_AUTH_SYSTEMS: - response = self.client.post(reverse(ldap_views.ldap_login_view), { - 'username' : 'bob', - 'password': 'password' - }, follow=True) - self.assertEqual(self.client.session['user']['name'], 'Robert Barker') - self.assertEqual(self.client.session['user']['type'], 'ldap') - self.assertEqual(self.client.session['user']['info']['email'],'bob@example.com') - - @override_settings(AUTH_LDAP_BIND_DN='uid=bob,ou=people,o=test', - AUTH_LDAP_BIND_PASSWORD='password',AUTH_LDAP_USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - def test_ldap_view_login_with_bad_password(self): - """ Test if given a wrong password the user can't login """ - if 'ldap' in ENABLED_AUTH_SYSTEMS: - response = self.client.post(reverse(ldap_views.ldap_login_view), { - 'username' : 'john', - 'password': 'passworddd' - }, follow=True) - self.assertEqual(response.status_code, 200) - self.assertFalse(self.client.session.has_key('user')) - - def test_ldap_view_login_anonymous_bind(self): - """ - Test anonymous search/bind - See https://pythonhosted.org/django-auth-ldap/authentication.html#search-bind - """ - self._init_settings( - BIND_PASSWORD='', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn','email':'mail'}, - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - user = self.backend.authenticate(username='alice', password='password') - self.assertEqual(user.username, 'alice') - self.assertEqual(user.first_name, 'Alice') - self.assertEqual(user.last_name, 'Adams') - self.assertEqual(user.email,'alice@example.com') - - def test_ldap_bind_as_user(self): - """ - Test direct bind - See https://pythonhosted.org/django-auth-ldap/authentication.html#direct-bind - """ - self._init_settings( - USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', - USER_ATTR_MAP={'first_name': 'givenName', 'last_name': 'sn','email':'mail'}, - BIND_AS_AUTHENTICATING_USER=True, - USER_SEARCH=LDAPSearch( - "ou=people,o=test", ldap.SCOPE_SUBTREE, '(uid=%(user)s)' - ) - ) - user = self.backend.authenticate(username='alice', password='password') - self.assertEqual(user.username, 'alice') - self.assertEqual(user.first_name, 'Alice') - self.assertEqual(user.last_name, 'Adams') - self.assertEqual(user.email,'alice@example.com') - - def test_logout(self): - """ test logging out using the auth system logout view """ - if 'ldap' in ENABLED_AUTH_SYSTEMS: - response = self.client.post(reverse(views.logout), follow=True) - self.assertContains(response, "not logged in") - self.assertNotContains(response, "alice") diff --git a/helios_auth/urls.py b/helios_auth/urls.py index 810d4f8f9e054bd413687e1cbde6af05c34f9bf7..e4dca398503d1e2f802fd4811330b66b9020a1a9 100644 --- a/helios_auth/urls.py +++ b/helios_auth/urls.py @@ -9,8 +9,6 @@ from django.conf.urls import * from views import * from auth_systems.password import password_login_view, password_forgotten_view from auth_systems.twitter import follow_view -from auth_systems.ldapauth import ldap_login_view - urlpatterns = patterns('', # basic static stuff @@ -30,7 +28,4 @@ urlpatterns = patterns('', # twitter (r'^twitter/follow', follow_view), - - #ldap - (r'^ldap/login', ldap_login_view), ) diff --git a/requirements.txt b/requirements.txt index 3d493a5ad09c5e9870ff631ff1f5ad48956cc60a..2cc4eb872cc1522a3d333dceee03caf92aa9d8d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,5 +22,3 @@ boto==2.27.0 django-ses==0.6.0 validate_email==1.2 oauth2client==1.2 -django-auth-ldap==1.2.7 -mockldap==0.2.7 diff --git a/settings.py b/settings.py index 1a04cce9ad3ef66d87051b64723181439dc9f9bc..1e20e2ffde7d3a297097d5b2c4f4e9d3b2ad73e7 100644 --- a/settings.py +++ b/settings.py @@ -1,7 +1,6 @@ -import ldap + import os, json -from django_auth_ldap.config import LDAPSearch, GroupOfNamesType # a massive hack to see if we're testing, in which case we use different settings import sys TESTING = 'test' in sys.argv @@ -135,8 +134,8 @@ TEMPLATE_DIRS = ( ) INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', +# 'django.contrib.auth', +# 'django.contrib.contenttypes', 'djangosecure', 'django.contrib.sessions', #'django.contrib.sites', @@ -202,7 +201,7 @@ HELIOS_VOTERS_EMAIL = True HELIOS_PRIVATE_DEFAULT = False # authentication systems enabled -#AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo','ldap'] +#AUTH_ENABLED_AUTH_SYSTEMS = ['password','facebook','twitter', 'google', 'yahoo'] AUTH_ENABLED_AUTH_SYSTEMS = get_from_env('AUTH_ENABLED_AUTH_SYSTEMS', 'google').split(",") AUTH_DEFAULT_AUTH_SYSTEM = get_from_env('AUTH_DEFAULT_AUTH_SYSTEM', None) @@ -238,25 +237,6 @@ CAS_ELIGIBILITY_REALM = get_from_env('CAS_ELIGIBILITY_REALM', "") CLEVER_CLIENT_ID = get_from_env('CLEVER_CLIENT_ID', "") CLEVER_CLIENT_SECRET = get_from_env('CLEVER_CLIENT_SECRET', "") -# ldap -# see configuration example at https://pythonhosted.org/django-auth-ldap/example.html -AUTH_LDAP_SERVER_URI = "ldap://localhost" # replace by your Ldap URI -AUTH_LDAP_BIND_DN = "cn=read-only-admin,dc=example,dc=com" -AUTH_LDAP_BIND_PASSWORD = "password" -AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=example,dc=com", - ldap.SCOPE_SUBTREE, "(uid=%(user)s)" -) -# Populate the Django user from the LDAP directory. -AUTH_LDAP_USER_ATTR_MAP = { - "first_name": "givenName", - "last_name": "sn", - "email": "mail", -} - -AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True - -AUTH_LDAP_ALWAYS_UPDATE_USER = False - # email server EMAIL_HOST = get_from_env('EMAIL_HOST', 'localhost') EMAIL_PORT = int(get_from_env('EMAIL_PORT', "2525"))