diff options
27 files changed, 708 insertions, 541 deletions
diff --git a/.coveragerc b/.coveragerc index 2828da0..e83bec0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,3 +1,3 @@ [run] source = . -omit = okupy/settings/*,setup.py,okupy/wsgi.py,okupy/tests/__init__.py,okupy/common/test_helpers.py,okupy/common/log.py,.virtualenv/* +omit = okupy/settings/*,setup.py,okupy/wsgi.py,okupy/common/test_helpers.py,okupy/common/log.py,.virtualenv/* diff --git a/okupy/accounts/forms.py b/okupy/accounts/forms.py index a82bba9..ae235f1 100644 --- a/okupy/accounts/forms.py +++ b/okupy/accounts/forms.py @@ -41,6 +41,14 @@ class SignupForm(forms.Form): password_verify = forms.CharField( max_length=30, widget=forms.PasswordInput(), label='Verify Password:') + def clean_password_verify(self): + cleaned_data = super(SignupForm, self).clean() + password_origin = cleaned_data.get('password_origin') + password_verify = cleaned_data.get('password_verify') + if password_origin != password_verify: + raise forms.ValidationError("Passwords don't match") + return password_verify + # OpenID forms. diff --git a/okupy/accounts/views.py b/okupy/accounts/views.py index e245d43..d3b0793 100644 --- a/okupy/accounts/views.py +++ b/okupy/accounts/views.py @@ -36,7 +36,7 @@ from ..common.ldap_helpers import (get_bound_ldapuser, set_secondary_password, remove_secondary_password) from ..common.crypto import cipher -from ..common.decorators import strong_auth_required +from ..common.decorators import strong_auth_required, anonymous_required from ..common.exceptions import OkupyError from ..common.log import log_extra_data from ..otp import init_otp @@ -157,12 +157,7 @@ def login(request): _login(request, user) # prepare devices, and see if OTP is enabled init_otp(request) - try: - set_secondary_password(request=request, password=password) - except Exception as error: - logger.critical(error, extra=log_extra_data(request)) - logger_mail.exception(error) - raise OkupyError("Can't contact LDAP server") + set_secondary_password(request=request, password=password) if request.user.is_authenticated(): if (strong_auth_req and not 'secondary_password' in request.session): @@ -268,6 +263,7 @@ def logout(request): return redirect(login) +@anonymous_required def signup(request): """ The signup page """ signup_form = None @@ -275,14 +271,10 @@ def signup(request): signup_form = SignupForm(request.POST) if signup_form.is_valid(): try: - if signup_form.cleaned_data['password_origin'] != \ - signup_form.cleaned_data['password_verify']: - raise OkupyError("Passwords don't match") - user = LDAPUser() try: - user.objects.get( + user = LDAPUser.objects.get( username=signup_form.cleaned_data['username']) - except user.DoesNotExist: + except LDAPUser.DoesNotExist: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) @@ -291,9 +283,9 @@ def signup(request): else: raise OkupyError('Username already exists') try: - user.objects.get( - username=signup_form.cleaned_data['email']) - except user.DoesNotExist: + user = LDAPUser.objects.get( + email__contains=signup_form.cleaned_data['email']) + except LDAPUser.DoesNotExist: pass else: raise OkupyError('Email already exists') @@ -331,6 +323,7 @@ def signup(request): }) +@anonymous_required def activate(request, token): """ The page that users get to activate their accounts @@ -345,19 +338,29 @@ def activate(request, token): logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact the database") + # get max uidNumber + try: + uidnumber = LDAPUser.objects.latest('uid').uid + 1 + except LDAPUser.DoesNotExist: + uidnumber = 1 + except Exception as error: + logger.critical(error, extra=log_extra_data(request)) + logger_mail.exception(error) + raise OkupyError("Can't contact LDAP server") # add account to ldap new_user = LDAPUser( - username=queued_user.username, - password=ldap_md5_crypt.encrypt(queued_user.password), - email=[queued_user.email], - first_name=queued_user.first_name, + object_class=settings.AUTH_LDAP_USER_OBJECTCLASS, last_name=queued_user.last_name, + full_name='%s %s' % (queued_user.first_name, queued_user.last_name), + password=[ldap_md5_crypt.encrypt(queued_user.password)], + first_name=queued_user.first_name, + email=[queued_user.email], + username=queued_user.username, + uid=uidnumber, + gid=100, gecos='%s %s' % (queued_user.first_name, queued_user.last_name), - objectClass=settings.AUTH_LDAP_USER_OBJECTCLASS, - cn='%s %s' % (queued_user.first_name, queued_user.last_name), - uidnumber=LDAPUser.objects.latest('uid') + 1, - gidNumber=100, - homeDirectory='/home/%s' % str(queued_user.username), + home_directory='/home/%s' % queued_user.username, + ACL=['user.group'], ) new_user.save() # remove queued account from DB diff --git a/okupy/common/decorators.py b/okupy/common/decorators.py index f6065e9..e69c02d 100644 --- a/okupy/common/decorators.py +++ b/okupy/common/decorators.py @@ -3,6 +3,7 @@ from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth.views import redirect_to_login +from django.http import HttpResponseRedirect from django.shortcuts import resolve_url from django.utils.decorators import available_attrs from django.utils.encoding import force_str @@ -51,3 +52,24 @@ def strong_auth_required(function=None, if function: return decorator(function) return decorator + + +def anonymous_required(view_function, redirect_to=None): + """ + Decorator that implements the opposite functionality of login_required + http://blog.motane.lu/2010/01/06/django-anonymous_required-decorator/ + """ + return AnonymousRequired(view_function, redirect_to) + + +class AnonymousRequired(object): + def __init__(self, view_function, redirect_to): + if redirect_to is None: + redirect_to = settings.LOGIN_REDIRECT_URL + self.view_function = view_function + self.redirect_to = redirect_to + + def __call__(self, request, *args, **kwargs): + if request.user is not None and request.user.is_authenticated(): + return HttpResponseRedirect(self.redirect_to) + return self.view_function(request, *args, **kwargs) diff --git a/okupy/common/ldap_helpers.py b/okupy/common/ldap_helpers.py index ad1ef2f..1bcfa69 100644 --- a/okupy/common/ldap_helpers.py +++ b/okupy/common/ldap_helpers.py @@ -38,7 +38,7 @@ def set_secondary_password(request, password): request.session['secondary_password'] = cipher.encrypt(secondary_password) # Clean up possible leftover secondary passwords from the LDAP account if len(user.password) > 1: - for hash in user.password: + for hash in list(user.password): try: if not ldap_md5_crypt.verify(password, hash): user.password.remove(hash) @@ -60,10 +60,11 @@ def remove_secondary_password(request): user = get_bound_ldapuser(request, password) if len(user.password) > 1: - for hash in user.password: + for hash in list(user.password): try: if ldap_md5_crypt.verify(password, hash): user.password.remove(hash) + break except ValueError: # ignore unknown hashes pass diff --git a/okupy/common/test_helpers.py b/okupy/common/test_helpers.py index 46fc316..81581c2 100644 --- a/okupy/common/test_helpers.py +++ b/okupy/common/test_helpers.py @@ -9,6 +9,8 @@ from django.db import DatabaseError from django.test import TestCase, RequestFactory from django.utils.functional import curry +from okupy.tests import vars + import mock @@ -22,30 +24,41 @@ no_database = curry( mock.Mock(side_effect=DatabaseError)) -def get_ldap_user(username, directory=settings.DIRECTORY): - """ Retrieve LDAP user from the fake LDAP directory """ - dn = settings.AUTH_LDAP_USER_DN_TEMPLATE % {'user': username} - return (dn, directory[dn]) - - -def get_all_ldap_users(directory=settings.DIRECTORY): - """ Retrieve all LDAP users from the fake LDAP directory """ - all_users = [] - for dn, attrs in directory.items(): - if dn.endswith(settings.AUTH_LDAP_USER_BASE_DN) and \ - dn is not settings.AUTH_LDAP_USER_BASE_DN: - all_users.append((dn, attrs)) - return all_users - +def ldap_users(username=None, all=False, clean=False, + directory=vars.DIRECTORY): + """ + Retrieve either a single LDAP user from the fake LDAP directory, + or all the users, or clean up the users from the directory + """ + if (username and all) or (username and clean) or (all and clean): + raise TypeError('Please specify one of username, all or clean') -def set_search_seed(username=None): + if username: + dn = settings.AUTH_LDAP_USER_DN_TEMPLATE % {'user': username} + result = (dn, directory[dn]) + elif all: + result = [] + for dn, attrs in directory.items(): + if dn.endswith(settings.AUTH_LDAP_USER_BASE_DN) and \ + dn is not settings.AUTH_LDAP_USER_BASE_DN: + result.append((dn, attrs)) + elif clean: + result = directory.copy() + for dn in directory.keys(): + if dn.endswith(settings.AUTH_LDAP_USER_BASE_DN) and \ + dn is not settings.AUTH_LDAP_USER_BASE_DN: + del result[dn] + return result + + +def set_search_seed(value=None, attr='uid'): """ Create the filterstr of the search_s seed part of the mocked ldap object """ search_item = '(&' for item in settings.AUTH_LDAP_USER_OBJECTCLASS: search_item += '(objectClass=%s)' % item - if username: - search_item += '(uid=%s)' % username + if value: + search_item += '(%s=%s)' % (attr, value) return search_item + ')' diff --git a/okupy/tests/acceptance/__init__.py b/okupy/tests/acceptance/__init__.py index 3d916e2..e69de29 100644 --- a/okupy/tests/acceptance/__init__.py +++ b/okupy/tests/acceptance/__init__.py @@ -1 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python diff --git a/okupy/tests/fixtures/queued_account.json b/okupy/tests/fixtures/queued_account.json deleted file mode 100644 index 40b52bf..0000000 --- a/okupy/tests/fixtures/queued_account.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "pk": 1, - "model": "accounts.queue", - "fields": { - "username": "queueduser", - "first_name": "queued_first_name", - "last_name": "queued_last_name", - "password": "queuedpass", - "email": "queueduser@test.com" - } - } -] diff --git a/okupy/tests/integration/__init__.py b/okupy/tests/integration/__init__.py index 3defde1..8b13789 100644 --- a/okupy/tests/integration/__init__.py +++ b/okupy/tests/integration/__init__.py @@ -1,5 +1 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python -from .index import * -from .login import * -from .signup import * diff --git a/okupy/tests/integration/signup.py b/okupy/tests/integration/signup.py deleted file mode 100644 index 3daabf2..0000000 --- a/okupy/tests/integration/signup.py +++ /dev/null @@ -1,206 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python - -from django.conf import settings -from django.contrib.auth.models import User -from django.core import mail -from django.db import DatabaseError -from django.test.client import Client -from mockldap import MockLdap - -from ...accounts.models import Queue -from ...common.test_helpers import OkupyTestCase - -import mock - -class SignupTestsEmptyDB(OkupyTestCase): - form_data = { - 'username': 'testusername', - 'first_name': 'testfirstname', - 'last_name': 'testlastname', - 'email': 'test@test.com', - 'password_origin': 'testpassword', - 'password_verify': 'testpassword', - } - - def setUp(self): - self.client = Client() - - def test_template(self): - response = self.client.get('/signup/') - self.assertIn('signup_form', response.context) - self.assertIn('messages', response.context) - - def test_empty_form(self): - response = self.client.post('/signup/') - self.assertFormError(response, 'signup_form', 'username', [u'This field is required.']) - self.assertFormError(response, 'signup_form', 'first_name', [u'This field is required.']) - self.assertFormError(response, 'signup_form', 'last_name', [u'This field is required.']) - self.assertFormError(response, 'signup_form', 'email', [u'This field is required.']) - self.assertFormError(response, 'signup_form', 'password_origin', [u'This field is required.']) - self.assertFormError(response, 'signup_form', 'password_verify', [u'This field is required.']) - self.assertEqual(Queue.objects.count(), 0) - - def test_passwords_dont_match(self): - form_data = self.form_data.copy() - form_data['password_verify'] = 'testpassword2' - response = self.client.post('/signup/', form_data) - self.assertMessage(response, "Passwords don't match", 40) - self.assertEqual(Queue.objects.count(), 0) - - def test_invalid_email(self): - form_data = self.form_data.copy() - form_data['email'] = 'test' - response = self.client.post('/signup/', form_data) - self.assertFormError(response, 'signup_form', 'email', [u'Enter a valid email address.']) - self.assertEqual(Queue.objects.count(), 0) - -class SignupTestsOneAccountInQueue(OkupyTestCase): - fixtures = ['queued_account.json'] - - cursor_wrapper = mock.Mock() - cursor_wrapper.side_effect = DatabaseError - - form_data = { - 'username': 'testusername', - 'first_name': 'testfirstname', - 'last_name': 'testlastname', - 'email': 'test@test.com', - 'password_origin': 'testpassword', - 'password_verify': 'testpassword', - } - - @classmethod - def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) - - def setUp(self): - self.client = Client() - self.queued_account = Queue.objects.get(pk=1) - self.activate_url = '/activate/%s/' % self.queued_account.encrypted_id - self.mockldap.start() - self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI] - - def tearDown(self): - self.mockldap.stop() - - def test_add_queued_account_to_ldap(self): - response = self.client.get(self.activate_url) - self.assertRedirects(response, '/login/') - self.assertMessage(response, 'Your account has been activated successfully', 25) - self.assertEqual(Queue.objects.count(), 0) - ldap_account = self.ldapobject.directory['uid=%s,ou=people,o=test' % self.queued_account.username] - self.assertEqual(ldap_account['uid'][0], self.queued_account.username) - self.assertEqual(ldap_account['givenName'][0], self.queued_account.first_name) - self.assertEqual(ldap_account['sn'][0], self.queued_account.last_name) - self.assertEqual(ldap_account['objectClass'], settings.AUTH_LDAP_USER_OBJECTCLASS) - self.assertEqual(ldap_account['uidNumber'][0], '1002') - self.assertEqual(ldap_account['mail'][0], self.queued_account.email) - data = {'username': self.queued_account.username, 'password': 'queuedpass'} - response = self.client.post('/login/', data) - self.assertRedirects(response, '/') - self.assertEqual(User.objects.count(), 1) - response = self.client.get(self.activate_url) - self.assertMessage(response, 'Invalid URL', 40) - - def test_signup_no_ldap(self): - self.mockldap.stop() - response = self.client.post('/signup/', self.form_data) - self.assertMessage(response, "Can't contact LDAP server", 40) - self.assertEqual(Queue.objects.count(), 1) - self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].subject, '%sERROR: {\'desc\': "Can\'t contact LDAP server"}' % settings.EMAIL_SUBJECT_PREFIX) - self.mockldap.start() - - def test_activate_no_ldap(self): - self.mockldap.stop() - response = self.client.get(self.activate_url) - self.assertRedirects(response, '/login/') - self.assertMessage(response, "Can't contact LDAP server", 40) - self.assertEqual(Queue.objects.count(), 1) - self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].subject, '%sERROR: {\'desc\': "Can\'t contact LDAP server"}' % settings.EMAIL_SUBJECT_PREFIX) - self.mockldap.start() - - def test_wrong_activation_link(self): - response = self.client.get('/activate/invalidurl/') - self.assertRedirects(response, '/login/') - self.assertMessage(response, 'Invalid URL', 40) - self.assertEqual(Queue.objects.count(), 1) - - def test_username_already_exists_in_ldap(self): - form_data = self.form_data.copy() - form_data['username'] = 'alice' - response = self.client.post('/signup/', form_data) - self.assertMessage(response, 'Username already exists', 40) - - def test_email_already_exists_in_ldap(self): - form_data = self.form_data.copy() - form_data['email'] = 'alice@test.com' - response = self.client.post('/signup/', form_data) - self.assertMessage(response, 'Email already exists', 40) - - def test_username_already_pending_activation(self): - form_data = self.form_data.copy() - form_data['username'] = 'queueduser' - response = self.client.post('/signup/', form_data) - self.assertMessage(response, 'Account is already pending activation', 40) - self.assertEqual(Queue.objects.count(), 1) - - def test_email_already_pending_activation(self): - form_data = self.form_data.copy() - form_data['email'] = 'queueduser@test.com' - response = self.client.post('/signup/', form_data) - self.assertMessage(response, 'Account is already pending activation', 40) - self.assertEqual(Queue.objects.count(), 1) - - def test_valid_data_to_form(self): - response = self.client.post('/signup/', self.form_data) - self.assertRedirects(response, '/login/') - self.assertMessage(response, 'You will shortly receive an activation mail', 20) - self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].subject, '%sAccount Activation' % settings.EMAIL_SUBJECT_PREFIX) - self.assertEqual(Queue.objects.count(), 2) - queued_account = Queue.objects.get(pk=2) - self.assertEqual(queued_account.username, self.form_data['username']) - self.assertEqual(queued_account.first_name, self.form_data['first_name']) - self.assertEqual(queued_account.last_name, self.form_data['last_name']) - self.assertEqual(queued_account.email, self.form_data['email']) - self.assertEqual(queued_account.password, self.form_data['password_origin']) - # note: this needs to be kept in line with used cipher - self.assertRegexpMatches(queued_account.encrypted_id, '^[a-f0-9]{16}$') - - @mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper) - def test_signup_no_database(self): - response = self.client.post('/signup/', self.form_data) - self.assertMessage(response, "Can't contact the database", 40) - self.assertEqual(len(mail.outbox), 1) - self.assertTrue(mail.outbox[0].subject.startswith('%sERROR:' % settings.EMAIL_SUBJECT_PREFIX)) - - @mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper) - def test_activate_no_database(self): - response = self.client.post(self.activate_url) - self.assertMessage(response, "Can't contact the database", 40) - self.assertEqual(len(mail.outbox), 1) - self.assertTrue(mail.outbox[0].subject.startswith('%sERROR:' % settings.EMAIL_SUBJECT_PREFIX)) - - def test_add_first_user_empty_ldap_directory(self): - for key in self.ldapobject.directory.keys(): - if key.startswith(settings.AUTH_LDAP_USER_ATTR) and key.endswith(settings.AUTH_LDAP_USER_BASE_DN): - del self.ldapobject.directory[key] - response = self.client.post(self.activate_url) - self.assertRedirects(response, '/login/') - self.assertMessage(response, 'Your account has been activated successfully', 25) - self.assertEqual(Queue.objects.count(), 0) - ldap_account = self.ldapobject.directory['uid=%s,ou=people,o=test' % self.queued_account.username] - self.assertEqual(ldap_account['uid'][0], self.queued_account.username) - self.assertEqual(ldap_account['givenName'][0], self.queued_account.first_name) - self.assertEqual(ldap_account['sn'][0], self.queued_account.last_name) - self.assertEqual(ldap_account['objectClass'], settings.AUTH_LDAP_USER_OBJECTCLASS) - self.assertEqual(ldap_account['uidNumber'][0], '1') - self.assertEqual(ldap_account['mail'][0], self.queued_account.email) - data={'username': self.queued_account.username, 'password': 'queuedpass'} - response = self.client.post('/login/', data) - self.assertRedirects(response, '/') - self.assertEqual(User.objects.count(), 1) - response = self.client.get(self.activate_url) - self.assertMessage(response, 'Invalid URL', 40) diff --git a/okupy/tests/integration/index.py b/okupy/tests/integration/test_index.py index 9e667e3..af6cb3a 100644 --- a/okupy/tests/integration/index.py +++ b/okupy/tests/integration/test_index.py @@ -4,13 +4,14 @@ from django.conf import settings from django.test.client import Client from mockldap import MockLdap -from ...common.test_helpers import OkupyTestCase, get_ldap_user, set_search_seed +from .. import vars +from ...common.test_helpers import OkupyTestCase, ldap_users, set_search_seed -class IndexTests(OkupyTestCase): +class IndexIntegrationTests(OkupyTestCase): @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) + cls.mockldap = MockLdap(vars.DIRECTORY) def setUp(self): self.client = Client() @@ -25,7 +26,7 @@ class IndexTests(OkupyTestCase): self.assertRedirects(response, '/login/?next=/') def test_index_page_uses_correct_template(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) response = self.client.post('/login/', {'username': 'alice', 'password': 'ldaptest'}) response = self.client.get('/') self.assertTemplateUsed(response, 'base.html') diff --git a/okupy/tests/integration/login.py b/okupy/tests/integration/test_login.py index dd907f5..ab3d515 100644 --- a/okupy/tests/integration/login.py +++ b/okupy/tests/integration/test_login.py @@ -1,22 +1,19 @@ # vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python from django.conf import settings +from django.test import TestCase from django.test.client import Client from mockldap import MockLdap -from ...common.test_helpers import OkupyTestCase, get_ldap_user, set_search_seed +from .. import vars +from ...common.test_helpers import ldap_users, set_search_seed -account1 = {'username': 'alice', 'password': 'ldaptest'} -account2 = {'username': 'bob', 'password': 'ldapmoretest'} -wrong_account = {'username': 'wrong', 'password': 'wrong'} - - -class LoginIntegrationTests(OkupyTestCase): +class LoginIntegrationTests(TestCase): @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) + cls.mockldap = MockLdap(vars.DIRECTORY) def setUp(self): self.client = Client() @@ -32,21 +29,21 @@ class LoginIntegrationTests(OkupyTestCase): self.assertTemplateUsed(response, 'login.html') def test_correct_user_post_login_redirect(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - account = account1.copy() + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + account = vars.LOGIN_ALICE.copy() account['next'] = '' response = self.client.post('/login/', account) self.assertRedirects(response, '/', 302, 200) def test_already_authenticated_user_redirects_to_index(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - self.client.post('/login/', account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + self.client.post('/login/', vars.LOGIN_ALICE) response = self.client.get('/login/') self.assertRedirects(response, '/') def test_logout_for_logged_in_user_redirects_to_login(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - self.client.post('/login/', account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + self.client.post('/login/', vars.LOGIN_ALICE) response = self.client.get('/logout/') self.assertRedirects(response, '/login/') @@ -55,8 +52,8 @@ class LoginIntegrationTests(OkupyTestCase): self.assertRedirects(response, '/login/') def test_logout_no_ldap_doesnt_raise_exception(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - self.client.post('/login/', account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + self.client.post('/login/', vars.LOGIN_ALICE) self.mockldap.stop() response = self.client.get('/logout/') self.assertRedirects(response, '/login/', 302, 200) diff --git a/okupy/tests/integration/test_signup.py b/okupy/tests/integration/test_signup.py new file mode 100644 index 0000000..acd894e --- /dev/null +++ b/okupy/tests/integration/test_signup.py @@ -0,0 +1,69 @@ +# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python + +from django.conf import settings +from django.test import TestCase +from django.test.client import Client +from mockldap import MockLdap + +from .. import vars +from ...accounts.models import LDAPUser +from ...common.test_helpers import set_search_seed, ldap_users + + +class SignupIntegrationTests(TestCase): + @classmethod + def setUpClass(cls): + cls.mockldap = MockLdap(vars.DIRECTORY) + + def setUp(self): + self.client = Client() + self.mockldap.start() + self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI] + + def tearDown(self): + self.mockldap.stop() + + def test_signup_page_uses_correct_template(self): + response = self.client.get('/signup/') + self.assertTemplateUsed(response, 'signup.html') + + def test_wrong_activation_link_redirects_to_login(self): + vars.QUEUEDUSER.save() + response = self.client.get('/activate/invalidurl/') + self.assertRedirects(response, '/login/', 302, 200) + + def test_valid_data_to_signup_redirects_to_login(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + response = self.client.post('/signup/', vars.SIGNUP_TESTUSER) + self.assertRedirects(response, '/login/', 302, 200) + + def test_logged_in_user_signup_url_redirects_to_index(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + self.client.post('/login/', {'username': 'alice', 'password': 'ldaptest'}) + response = self.client.get('/signup/') + self.assertRedirects(response, '/', 302, 200) + + def test_logged_in_user_activate_url_redirects_to_index(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + self.client.post('/login/', {'username': 'alice', 'password': 'ldaptest'}) + response = self.client.get(activate_url) + self.assertRedirects(response, '/', 302, 200) + + +class SignupIntegrationTestsNoLDAP(TestCase): + def setUp(self): + self.client = Client() + + def test_activate_no_ldap_connection_redirects_to_login(self): + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + response = self.client.get(activate_url) + self.assertRedirects(response, '/login/', 302, 200) + + def test_activate_page_without_token_returns_404(self): + response = self.client.get('/activate/') + self.assertTrue(response.status_code, 404) diff --git a/okupy/tests/settings.py b/okupy/tests/settings.py index b713032..f4d0c07 100644 --- a/okupy/tests/settings.py +++ b/okupy/tests/settings.py @@ -299,34 +299,3 @@ DATABASES['ldap'] = { DATABASE_ROUTERS = ['ldapdb.router.Router'] TEST_RUNNER = 'discover_runner.DiscoverRunner' - -DIRECTORY = { - "o=test": {}, - "cn=anon,o=test": { - "userPassword": ["{CRYPT}$1$n4jlXi20$.5a8UTvwIqVfVAMlXJ1EZ0"], - }, - "cn=Manager,o=test": { - "userPassword": ["{CRYPT}$1$sY4mlRve$0eg5TLYMyZfBCIUgU/RPf0"], - }, - "ou=people,o=test": {}, - "uid=alice,ou=people,o=test": { - "uid": ["alice"], - "userPassword": ['{CRYPT}$1$lO/RU6zz$2fJCOwurxBtCqdImkoLQo1'], - "objectClass": AUTH_LDAP_USER_OBJECTCLASS + AUTH_LDAP_DEV_OBJECTCLASS, - "uidNumber": ["1000"], - "gidNumber": ["1000"], - "givenName": ["Alice"], - "sn": ["Adams"], - "mail": ["alice@test.com"], - }, - "uid=bob,ou=people,o=test": { - "uid": ["bob"], - "userPassword": ['{CRYPT}$1$eFSQMJY6$8y.WUL/ONeEarVXqeCIbH.'], - "objectClass": AUTH_LDAP_USER_OBJECTCLASS, - "uidNumber": ["1001"], - "gidNumber": ["50"], - "givenName": ["Robert"], - "sn": ["Barker"], - "mail": ["bob@test.com"], - } -} diff --git a/okupy/tests/tests.py b/okupy/tests/tests.py deleted file mode 100644 index 9229eb9..0000000 --- a/okupy/tests/tests.py +++ /dev/null @@ -1,11 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python - -# run tests modules -from .unit.index import * -from .unit.login import * -from .unit.secondary_password import * -from .unit.openid import * -#from .unit.signup import * -from .integration.index import * -from .integration.login import * -#from .integration.signup import * diff --git a/okupy/tests/unit/__init__.py b/okupy/tests/unit/__init__.py index 1e2514b..e69de29 100644 --- a/okupy/tests/unit/__init__.py +++ b/okupy/tests/unit/__init__.py @@ -1,7 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python - -from .index import * -from .login import * -from .secondary_password import * -from .openid import * -from .signup import * diff --git a/okupy/tests/unit/secondary_password.py b/okupy/tests/unit/secondary_password.py deleted file mode 100644 index 4f9e4c6..0000000 --- a/okupy/tests/unit/secondary_password.py +++ /dev/null @@ -1,113 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python - -from django.conf import settings -from django.contrib.auth.models import User -from django.test import TestCase - -from base64 import b64encode -from Crypto import Random -from mockldap import MockLdap -from passlib.hash import ldap_md5_crypt - -from ...common.crypto import cipher -from ...common.ldap_helpers import set_secondary_password, remove_secondary_password -from ...common.test_helpers import set_request, set_search_seed, get_ldap_user - - -class SecondaryPassword(TestCase): - @classmethod - def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) - - def setUp(self): - self.mockldap.start() - self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI] - - def tearDown(self): - self.mockldap.stop() - - def test_secondary_password_gets_added_in_session(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - set_secondary_password(request, 'ldaptest') - self.assertEqual(len(request.session['secondary_password']), 48) - - def test_secondary_password_gets_added_in_ldap(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - self.assertEqual(len(get_ldap_user('alice')[1]['userPassword']), 1) - set_secondary_password(request, 'ldaptest') - self.assertEqual(len(get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']), 2) - - def test_remove_leftovers_before_adding_secondary_password(self): - leftover = ldap_md5_crypt.encrypt('leftover_password') - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(leftover) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - set_secondary_password(request, 'ldaptest') - self.assertNotIn(leftover, get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']) - - def test_dont_remove_primary_password_while_cleaning_leftovers(self): - leftover = ldap_md5_crypt.encrypt('leftover_password') - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(leftover) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - set_secondary_password(request, 'ldaptest') - self.assertTrue(ldap_md5_crypt.verify('ldaptest',get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword'][0])) - - def test_dont_remove_unknown_hashes_while_cleaning_leftovers(self): - leftover = ldap_md5_crypt.encrypt('leftover_password') - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(leftover) - leftover2 = 'plain_leftover2' - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(leftover2) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - set_secondary_password(request, 'ldaptest') - self.assertIn(leftover2, get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']) - - def test_session_and_ldap_secondary_passwords_match(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - set_secondary_password(request, 'ldaptest') - self.assertTrue(ldap_md5_crypt.verify(b64encode(cipher.decrypt(request.session['secondary_password'], 48)), get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword'][1])) - - def test_remove_secondary_password_from_ldap(self): - secondary_password = Random.get_random_bytes(48) - secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(secondary_password_crypt) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - request.session['secondary_password'] = cipher.encrypt(secondary_password) - remove_secondary_password(request) - self.assertNotIn(secondary_password_crypt, get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']) - - def test_dont_remove_primary_password_while_removing_secondary_password(self): - secondary_password = Random.get_random_bytes(48) - secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(secondary_password_crypt) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - request.session['secondary_password'] = cipher.encrypt(secondary_password) - remove_secondary_password(request) - self.assertTrue(ldap_md5_crypt.verify('ldaptest',get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword'][0])) - - def test_dont_remove_unknown_hashes_while_removing_secondary_password(self): - secondary_password = Random.get_random_bytes(48) - secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(secondary_password_crypt) - unknown_hash = 'unknown_hash' - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(unknown_hash) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User.objects.create(username='alice', password='ldaptest') - request = set_request(uri='/', user=alice) - request.session['secondary_password'] = cipher.encrypt(secondary_password) - remove_secondary_password(request) - self.assertIn(unknown_hash, get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']) diff --git a/okupy/tests/unit/signup.py b/okupy/tests/unit/signup.py deleted file mode 100644 index 071c68e..0000000 --- a/okupy/tests/unit/signup.py +++ /dev/null @@ -1,18 +0,0 @@ -# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python - -from django.core.urlresolvers import resolve -from django.test import TestCase - -from ...accounts.views import signup -from ...common.test_helpers import set_request - - -class SignupUnitTests(TestCase): - def test_signup_url_resolves_to_signup_view(self): - found = resolve('/signup') - self.assertEqual(found.func, signup) - - def test_signup_page_returns_200_for_anonymous(self): - request = set_request(uri='/signup') - response = signup(request) - self.assertEqual(response.status_code, 200) diff --git a/okupy/tests/unit/test_cipher.py b/okupy/tests/unit/test_cipher.py new file mode 100644 index 0000000..31ac795 --- /dev/null +++ b/okupy/tests/unit/test_cipher.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from Crypto import Random +from unittest import TestCase + +from ...common.crypto import cipher + + +class OkupyCipherTests(TestCase): + def test_verify_password_less_than_8_chars(self): + hash = cipher.encrypt('test1') + self.assertEqual(cipher.decrypt(hash, 5), 'test1') + + def test_verify_password_8_chars(self): + hash = cipher.encrypt('testtest') + self.assertEqual(cipher.decrypt(hash, 8), 'testtest') + + def test_verify_password_more_than_8_chars(self): + hash = cipher.encrypt('testtest123') + self.assertEqual(cipher.decrypt(hash, 11), 'testtest123') + + def test_verify_password_more_than_16_chars(self): + hash = cipher.encrypt('testtest123456789012') + self.assertEqual(cipher.decrypt(hash, 20), 'testtest123456789012') + + def test_encrypt_random_bytes(self): + password = Random.get_random_bytes(45) + hash = cipher.encrypt(password) + self.assertEqual(cipher.decrypt(hash, 45), password) diff --git a/okupy/tests/unit/index.py b/okupy/tests/unit/test_index.py index bae044e..7e4a8eb 100644 --- a/okupy/tests/unit/index.py +++ b/okupy/tests/unit/test_index.py @@ -1,25 +1,20 @@ # vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python from django.conf import settings -from django.contrib.auth.models import User from django.core.urlresolvers import resolve from django.test import TestCase from mockldap import MockLdap +from .. import vars from ...accounts.views import index -from ...common.test_helpers import set_request, get_ldap_user, set_search_seed - - -alice = User(username='alice', password='ldaptest') -account2 = {'username': 'bob', 'password': 'ldapmoretest'} -wrong_account = {'username': 'wrong', 'password': 'wrong'} +from ...common.test_helpers import set_request, ldap_users, set_search_seed class IndexUnitTests(TestCase): @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) + cls.mockldap = MockLdap(vars.DIRECTORY) def setUp(self): self.mockldap.start() @@ -33,14 +28,14 @@ class IndexUnitTests(TestCase): self.assertEqual(found.func, index) def test_index_page_returns_200_for_logged_in(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - request = set_request(uri='/', user=alice) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/', user=vars.USER_ALICE) response = index(request) self.assertEqual(response.status_code, 200) def test_rendered_index_page(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - request = set_request(uri='/', user=alice) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/', user=vars.USER_ALICE) response = index(request) nickname_html = '<tr class="even"><th>Nickname</th><td>alice</td></tr>' self.assertIn(nickname_html, response.content) diff --git a/okupy/tests/unit/login.py b/okupy/tests/unit/test_login.py index 6d5e94d..58c01ea 100644 --- a/okupy/tests/unit/login.py +++ b/okupy/tests/unit/test_login.py @@ -12,21 +12,17 @@ from Crypto import Random from passlib.hash import ldap_md5_crypt from mockldap import MockLdap +from .. import vars from ...accounts.views import login, logout from ...accounts.forms import LoginForm from ...common.crypto import cipher -from ...common.test_helpers import OkupyTestCase, set_request, no_database, get_ldap_user, set_search_seed - - -account1 = {'username': 'alice', 'password': 'ldaptest'} -account2 = {'username': 'bob', 'password': 'ldapmoretest'} -wrong_account = {'username': 'wrong', 'password': 'wrong'} +from ...common.test_helpers import OkupyTestCase, set_request, no_database, ldap_users, set_search_seed class LoginUnitTests(OkupyTestCase): @classmethod def setUpClass(cls): - cls.mockldap = MockLdap(settings.DIRECTORY) + cls.mockldap = MockLdap(vars.DIRECTORY) def setUp(self): self.mockldap.start() @@ -35,42 +31,14 @@ class LoginUnitTests(OkupyTestCase): def tearDown(self): self.mockldap.stop() - def test_login_url_resolves_to_login_view(self): - found = resolve('/login/') - self.assertEqual(found.func, login) - - def test_login_page_returns_200(self): - request = set_request(uri='/login') - response = login(request) - self.assertEqual(response.status_code, 200) - - def test_rendered_login_form(self): - request = set_request(uri='/login') - response = login(request) - login_form_part = '<input id="id_username" maxlength="100" name="username" type="text" />' - self.assertIn(login_form_part, response.content) - - def test_empty_user_raises_form_error_messages(self): - request = set_request(uri='/login') - response = login(request) - response.context = RequestContext(request, {'login_form': LoginForm(request.POST)}) - self.assertFormError(response, 'login_form', 'username', 'This field is required.') - self.assertFormError(response, 'login_form', 'password', 'This field is required.') - - def test_empty_user_raises_login_failed(self): - request = set_request(uri='/login', post=True, messages=True) - response = login(request) - response.context = RequestContext(request) - self.assertMessage(response, 'Login failed', 40) - def test_incorrect_user_raises_login_failed(self): - request = set_request(uri='/login', post=wrong_account, messages=True) + request = set_request(uri='/login', post=vars.LOGIN_WRONG, messages=True) response = login(request) response.context = RequestContext(request) self.assertMessage(response, 'Login failed', 40) def test_incorrect_user_does_not_get_transferred_in_db(self): - request = set_request(uri='/login', post=wrong_account, messages=True) + request = set_request(uri='/login', post=vars.LOGIN_WRONG, messages=True) login(request) self.assertEqual(User.objects.count(), 0) @@ -79,61 +47,96 @@ class LoginUnitTests(OkupyTestCase): 'django_auth_ldap.backend.LDAPBackend', 'django.contrib.auth.backends.ModelBackend')) def test_no_database_raises_critical(self): - request = set_request(uri='/login', post=account1, messages=True) + request = set_request(uri='/login', post=vars.LOGIN_ALICE, messages=True) response = login(request) response.context = RequestContext(request) self.assertMessage(response, "Can't contact the LDAP server or the database", 40) + + @no_database() + @override_settings(AUTHENTICATION_BACKENDS=( + 'django_auth_ldap.backend.LDAPBackend', + 'django.contrib.auth.backends.ModelBackend')) + def test_no_database_sends_notification_mail(self): + request = set_request(uri='/login', post=vars.LOGIN_ALICE, messages=True) + response = login(request) + response.context = RequestContext(request) self.assertEqual(len(mail.outbox), 1) self.assertTrue(mail.outbox[0].subject.startswith('%sERROR:' % settings.EMAIL_SUBJECT_PREFIX)) def test_correct_user_gets_transferred_in_db(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - request = set_request(uri='/login', post=account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/login', post=vars.LOGIN_ALICE) login(request) self.assertEqual(User.objects.count(), 1) def test_authenticate_account_that_is_already_in_db(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - User.objects.create_user(username='alice') - request = set_request(uri='/login', post=account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + vars.USER_ALICE.save() + request = set_request(uri='/login', post=vars.LOGIN_ALICE) login(request) self.assertEqual(User.objects.count(), 1) def test_secondary_password_is_added_in_login(self): - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice')]) - request = set_request(uri='/login', post=account1) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/login', post=vars.LOGIN_ALICE) login(request) - self.assertEqual(len(get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']), 2) + self.assertEqual(len(ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']), 2) self.assertEqual(len(request.session['secondary_password']), 48) def test_secondary_password_is_removed_in_logout(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) - self.ldapobject.directory[get_ldap_user('alice')[0]]['userPassword'].append(secondary_password_crypt) - self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([get_ldap_user('alice', directory=self.ldapobject.directory)]) - alice = User(username='alice') - request = set_request(uri='/login', post=account1, user=alice) + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(secondary_password_crypt) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/login', post=vars.LOGIN_ALICE, user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt(secondary_password) logout(request) - self.assertEqual(len(get_ldap_user('alice', directory=self.ldapobject.directory)[1]['userPassword']), 1) + self.assertEqual(len(ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']), 1) class LoginUnitTestsNoLDAP(OkupyTestCase): + def test_login_url_resolves_to_login_view(self): + found = resolve('/login/') + self.assertEqual(found.func, login) + + def test_login_page_returns_200(self): + request = set_request(uri='/login') + response = login(request) + self.assertEqual(response.status_code, 200) + + def test_rendered_login_form(self): + request = set_request(uri='/login') + response = login(request) + login_form_part = '<input id="id_username" maxlength="100" name="username" type="text" />' + self.assertIn(login_form_part, response.content) + + def test_empty_user_raises_form_error_messages(self): + request = set_request(uri='/login') + response = login(request) + response.context = RequestContext(request, {'login_form': LoginForm(request.POST)}) + self.assertFormError(response, 'login_form', 'username', 'This field is required.') + self.assertFormError(response, 'login_form', 'password', 'This field is required.') + + def test_empty_user_raises_login_failed(self): + request = set_request(uri='/login', post=True, messages=True) + response = login(request) + response.context = RequestContext(request) + self.assertMessage(response, 'Login failed', 40) + def test_dont_authenticate_from_db_when_ldap_is_down(self): - request = set_request(uri='/login', post=account2, messages=True) + request = set_request(uri='/login', post=vars.LOGIN_BOB, messages=True) response = login(request) response.context = RequestContext(request) self.assertMessage(response, 'Login failed', 40) def test_no_ldap_connection_raises_login_failed_in_login(self): - request = set_request(uri='/login', post=wrong_account, messages=True) + request = set_request(uri='/login', post=vars.LOGIN_WRONG, messages=True) response = login(request) response.context = RequestContext(request) self.assertMessage(response, 'Login failed', 40) def test_no_ldap_connection_in_logout_sends_notification_mail(self): - alice = User(username='alice') - request = set_request(uri='/login', post=account1, user=alice) + request = set_request(uri='/login', post=vars.LOGIN_ALICE, user=vars.USER_ALICE) request.session['secondary_password'] = 'test' logout(request) self.assertEqual(len(mail.outbox), 1) diff --git a/okupy/tests/unit/openid.py b/okupy/tests/unit/test_openid.py index b50928f..4d5a75a 100644 --- a/okupy/tests/unit/openid.py +++ b/okupy/tests/unit/test_openid.py @@ -1,12 +1,13 @@ # vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python +from django.test import TestCase + from ...accounts.openid_store import DjangoDBOpenIDStore -from ...common.test_helpers import OkupyTestCase import time -class OpenIDStoreTests(OkupyTestCase): +class OpenIDStoreTests(TestCase): def setUp(self): self.store = DjangoDBOpenIDStore() diff --git a/okupy/tests/unit/test_secondary_password.py b/okupy/tests/unit/test_secondary_password.py new file mode 100644 index 0000000..8338827 --- /dev/null +++ b/okupy/tests/unit/test_secondary_password.py @@ -0,0 +1,103 @@ +# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python + +from django.conf import settings +from django.test import TestCase + +from base64 import b64encode +from Crypto import Random +from mockldap import MockLdap +from passlib.hash import ldap_md5_crypt + +from .. import vars +from ...common.crypto import cipher +from ...common.ldap_helpers import set_secondary_password, remove_secondary_password +from ...common.test_helpers import set_request, set_search_seed, ldap_users + + +class SecondaryPassword(TestCase): + @classmethod + def setUpClass(cls): + cls.mockldap = MockLdap(vars.DIRECTORY) + + def setUp(self): + self.mockldap.start() + self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI] + + def tearDown(self): + self.mockldap.stop() + + def test_secondary_password_gets_added_in_session(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/', user=vars.USER_ALICE) + set_secondary_password(request, 'ldaptest') + self.assertEqual(len(request.session['secondary_password']), 48) + + def test_secondary_password_gets_added_in_ldap(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/', user=vars.USER_ALICE) + self.assertEqual(len(ldap_users('alice')[1]['userPassword']), 1) + set_secondary_password(request, 'ldaptest') + self.assertEqual(len(ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']), 2) + + def test_remove_leftovers_before_adding_secondary_password(self): + leftover = ldap_md5_crypt.encrypt('leftover_password') + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(leftover) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + set_secondary_password(request, 'ldaptest') + self.assertNotIn(leftover, ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']) + + def test_dont_remove_primary_password_while_cleaning_leftovers(self): + leftover = ldap_md5_crypt.encrypt('leftover_password') + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(leftover) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + set_secondary_password(request, 'ldaptest') + self.assertTrue(ldap_md5_crypt.verify('ldaptest', ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword'][0])) + + def test_dont_remove_unknown_hashes_while_cleaning_leftovers(self): + leftover = ldap_md5_crypt.encrypt('leftover_password') + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(leftover) + leftover2 = 'plain_leftover2' + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(leftover2) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + set_secondary_password(request, 'ldaptest') + self.assertIn(leftover2, ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']) + + def test_session_and_ldap_secondary_passwords_match(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + request = set_request(uri='/', user=vars.USER_ALICE) + set_secondary_password(request, 'ldaptest') + self.assertTrue(ldap_md5_crypt.verify(b64encode(cipher.decrypt(request.session['secondary_password'], 48)), ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword'][1])) + + def test_remove_secondary_password_from_ldap(self): + secondary_password = Random.get_random_bytes(48) + secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(secondary_password_crypt) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + request.session['secondary_password'] = cipher.encrypt(secondary_password) + remove_secondary_password(request) + self.assertNotIn(secondary_password_crypt, ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']) + + def test_dont_remove_primary_password_while_removing_secondary_password(self): + secondary_password = Random.get_random_bytes(48) + secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(secondary_password_crypt) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + request.session['secondary_password'] = cipher.encrypt(secondary_password) + remove_secondary_password(request) + self.assertTrue(ldap_md5_crypt.verify('ldaptest', ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword'][0])) + + def test_dont_remove_unknown_hashes_while_removing_secondary_password(self): + secondary_password = Random.get_random_bytes(48) + secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode(secondary_password)) + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append('unknown_hash') + self.ldapobject.directory[ldap_users('alice')[0]]['userPassword'].append(secondary_password_crypt) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice', directory=self.ldapobject.directory)]) + request = set_request(uri='/', user=vars.USER_ALICE) + request.session['secondary_password'] = cipher.encrypt(secondary_password) + remove_secondary_password(request) + self.assertIn('unknown_hash', ldap_users('alice', directory=self.ldapobject.directory)[1]['userPassword']) diff --git a/okupy/tests/unit/test_signup.py b/okupy/tests/unit/test_signup.py new file mode 100644 index 0000000..c32869a --- /dev/null +++ b/okupy/tests/unit/test_signup.py @@ -0,0 +1,257 @@ +# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python + +from django.conf import settings +from django.core import mail +from django.core.urlresolvers import resolve +from django.template import RequestContext + +from mockldap import MockLdap +from passlib.hash import ldap_md5_crypt + +from .. import vars +from ...accounts.forms import SignupForm +from ...accounts.models import LDAPUser, Queue +from ...accounts.views import signup, activate +from ...common.test_helpers import OkupyTestCase, set_request, set_search_seed, ldap_users, no_database + + +class SignupUnitTests(OkupyTestCase): + @classmethod + def setUpClass(cls): + cls.mockldap = MockLdap(vars.DIRECTORY) + + def setUp(self): + self.mockldap.start() + self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI] + + def tearDown(self): + self.mockldap.stop() + + def test_username_already_exists_in_ldap(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice'))([ldap_users('alice')]) + _form = vars.SIGNUP_TESTUSER.copy() + _form['username'] = 'alice' + request = set_request(uri='/signup', post=_form, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, 'Username already exists', 40) + + def test_email_already_exists_in_ldap(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('alice@test.com', attr='mail'))([ldap_users('alice')]) + _form = vars.SIGNUP_TESTUSER.copy() + _form['email'] = 'alice@test.com' + request = set_request(uri='/signup', post=_form, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, 'Email already exists', 40) + + def test_username_already_pending_activation(self): + _form = vars.SIGNUP_TESTUSER.copy() + _form['username'] = 'queueduser' + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('queueduser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + vars.QUEUEDUSER.save() + request = set_request(uri='/signup', post=_form, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, 'Account is already pending activation', 40) + + def test_email_already_pending_activation(self): + _form = vars.SIGNUP_TESTUSER.copy() + _form['email'] = 'queued_user@test.com' + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('queued_user@test.com', attr='mail'))(LDAPUser.DoesNotExist) + vars.QUEUEDUSER.save() + request = set_request(uri='/signup', post=_form, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, 'Account is already pending activation', 40) + + def test_add_queued_account_to_ldap_prints_success_message(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + request = set_request(uri=activate_url, messages=True) + response = activate(request, vars.QUEUEDUSER.encrypted_id) + response.context = RequestContext(request) + self.assertMessage(response, 'Your account has been activated successfully', 25) + + def test_queued_account_gets_added_to_ldap(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + request = set_request(activate_url, messages=True) + activate(request, vars.QUEUEDUSER.encrypted_id) + self.assertTrue(ldap_users(vars.QUEUEDUSER.username, directory=self.ldapobject.directory)) + ldap_account = ldap_users(vars.QUEUEDUSER.username, directory=self.ldapobject.directory)[1] + self.assertEqual(ldap_account['objectClass'], settings.AUTH_LDAP_USER_OBJECTCLASS) + self.assertEqual(ldap_account['sn'][0], vars.QUEUEDUSER.last_name) + self.assertEqual(ldap_account['cn'][0], '%s %s' % (vars.QUEUEDUSER.first_name, vars.QUEUEDUSER.last_name)) + self.assertTrue(ldap_md5_crypt.verify(vars.QUEUEDUSER.password, ldap_account['userPassword'][0])) + self.assertEqual(ldap_account['givenName'][0], vars.QUEUEDUSER.first_name) + self.assertEqual(ldap_account['mail'][0], vars.QUEUEDUSER.email) + self.assertEqual(ldap_account['uid'][0], vars.QUEUEDUSER.username) + self.assertEqual(ldap_account['uidNumber'][0], '1002') + self.assertEqual(ldap_account['gidNumber'][0], '100') + self.assertEqual(ldap_account['gecos'][0], '%s %s' % (vars.QUEUEDUSER.first_name, vars.QUEUEDUSER.last_name)) + self.assertEqual(ldap_account['homeDirectory'][0], '/home/%s' % vars.QUEUEDUSER.username) + self.assertEqual(ldap_account['gentooACL'][0], 'user.group') + + def test_add_queued_account_remove_from_queue(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + request = set_request(activate_url, messages=True) + activate(request, vars.QUEUEDUSER.encrypted_id) + self.assertEqual(Queue.objects.count(), 0) + + def test_valid_data_to_signup_form_prints_info_message(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, 'You will shortly receive an activation mail', 20) + + def test_valid_data_to_signup_form_sends_activation_mail(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, '%sAccount Activation' % settings.EMAIL_SUBJECT_PREFIX) + + def test_valid_data_to_signup_form_adds_user_to_queue(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertEqual(Queue.objects.count(), 1) + vars.QUEUEDUSER = Queue.objects.get(pk=1) + self.assertEqual(vars.QUEUEDUSER.username, vars.SIGNUP_TESTUSER['username']) + self.assertEqual(vars.QUEUEDUSER.first_name, vars.SIGNUP_TESTUSER['first_name']) + self.assertEqual(vars.QUEUEDUSER.last_name, vars.SIGNUP_TESTUSER['last_name']) + self.assertEqual(vars.QUEUEDUSER.email, vars.SIGNUP_TESTUSER['email']) + self.assertEqual(vars.QUEUEDUSER.password, vars.SIGNUP_TESTUSER['password_origin']) + # note: this needs to be kept in line with used cipher + self.assertRegexpMatches(vars.QUEUEDUSER.encrypted_id, '^[a-f0-9]{16}$') + + @no_database() + def test_no_database_connection_raises_error_in_signup(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, "Can't contact the database", 40) + + @no_database() + def test_no_database_connection_sends_notification_mail_in_signup(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('testuser'))(LDAPUser.DoesNotExist) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed('test@test.com', attr='mail'))(LDAPUser.DoesNotExist) + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertEqual(len(mail.outbox), 1) + self.assertTrue(mail.outbox[0].subject.startswith('%sERROR:' % settings.EMAIL_SUBJECT_PREFIX)) + + @no_database() + def test_no_database_connection_raises_error_in_activation(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + request = set_request('/activate/test', messages=True) + response = activate(request, vars.QUEUEDUSER.encrypted_id) + response.context = RequestContext(request) + self.assertMessage(response, "Can't contact the database", 40) + + @no_database() + def test_no_database_connection_sends_notification_mail_in_activation(self): + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True)) + request = set_request('/activate/test', messages=True) + activate(request, vars.QUEUEDUSER.encrypted_id) + self.assertEqual(len(mail.outbox), 1) + self.assertTrue(mail.outbox[0].subject.startswith('%sERROR:' % settings.EMAIL_SUBJECT_PREFIX)) + + def test_add_first_user_in_empty_ldap_directory(self): + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + self.ldapobject.directory = ldap_users(clean=True) + self.ldapobject.search_s.seed(settings.AUTH_LDAP_USER_BASE_DN, 2, set_search_seed())(ldap_users(all=True, directory=self.ldapobject.directory)) + request = set_request(activate_url, messages=True) + activate(request, vars.QUEUEDUSER.encrypted_id) + self.assertTrue(ldap_users(vars.QUEUEDUSER.username, directory=self.ldapobject.directory)) + self.assertEqual(ldap_users(vars.QUEUEDUSER.username, directory=self.ldapobject.directory)[1]['uidNumber'][0], '1') + + +class SignupunitTestsNoLDAP(OkupyTestCase): + def test_signup_url_resolves_to_signup_view(self): + found = resolve('/signup/') + self.assertEqual(found.func, signup) + + def test_signup_page_returns_200_for_anonymous(self): + request = set_request(uri='/signup') + response = signup(request) + self.assertEqual(response.status_code, 200) + + def test_rendered_signup_form(self): + request = set_request(uri='/signup') + response = signup(request) + signup_form_part = '<label for="id_first_name">First Name:</label><input id="id_first_name" maxlength="100" name="first_name" type="text" />' + self.assertIn(signup_form_part, response.content) + + def test_empty_signup_form_raises_form_error_messages(self): + request = set_request(uri='/signup') + response = signup(request) + response.context = RequestContext(request, {'signup_form': SignupForm(request.POST)}) + self.assertFormError(response, 'signup_form', 'username', 'This field is required.') + self.assertFormError(response, 'signup_form', 'first_name', 'This field is required.') + self.assertFormError(response, 'signup_form', 'last_name', 'This field is required.') + self.assertFormError(response, 'signup_form', 'email', 'This field is required.') + self.assertFormError(response, 'signup_form', 'password_origin', 'This field is required.') + self.assertFormError(response, 'signup_form', 'password_verify', 'This field is required.') + + def test_passwords_dont_match(self): + _form = vars.SIGNUP_TESTUSER.copy() + _form['password_verify'] = 'wrong' + request = set_request(uri='/signup', post=_form) + response = signup(request) + response.context = RequestContext(request, {'signup_form': SignupForm(request.POST)}) + self.assertFormError(response, 'signup_form', 'password_verify', "Passwords don't match") + + def test_wrong_activaltion_link_raises_invalid_url(self): + request = set_request(uri='/activate/invalidurl', messages=True) + response = activate(request, 'invalidurl') + response.context = RequestContext(request) + self.assertMessage(response, 'Invalid URL', 40) + + def test_no_ldap_connection_raises_error_in_signup(self): + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertMessage(response, "Can't contact LDAP server", 40) + + def test_no_ldap_connection_sends_notification_mail_in_signup(self): + request = set_request(uri='/signup', post=vars.SIGNUP_TESTUSER, messages=True) + response = signup(request) + response.context = RequestContext(request) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, '%sERROR: {\'desc\': "Can\'t contact LDAP server"}' % settings.EMAIL_SUBJECT_PREFIX) + + def test_no_ldap_connection_raises_error_in_activation(self): + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + request = set_request(activate_url, messages=True) + response = activate(request, vars.QUEUEDUSER.encrypted_id) + response.context = RequestContext(request) + self.assertMessage(response, "Can't contact LDAP server", 40) + + def test_no_ldap_connection_sends_notification_mail_in_activation(self): + vars.QUEUEDUSER.save() + activate_url = '/activate/%s/' % vars.QUEUEDUSER.encrypted_id + request = set_request(activate_url, messages=True) + response = activate(request, vars.QUEUEDUSER.encrypted_id) + response.context = RequestContext(request) + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(mail.outbox[0].subject, '%sERROR: {\'desc\': "Can\'t contact LDAP server"}' % settings.EMAIL_SUBJECT_PREFIX) diff --git a/okupy/tests/vars.py b/okupy/tests/vars.py new file mode 100644 index 0000000..f4edbc1 --- /dev/null +++ b/okupy/tests/vars.py @@ -0,0 +1,69 @@ +# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python + +""" Various variables used by the tests """ + +from django.conf import settings +from django.contrib.auth.models import User + +from ..accounts.models import Queue + + +# LDAP directory +DIRECTORY = { + "o=test": {}, + "cn=anon,o=test": { + "userPassword": ["{CRYPT}$1$n4jlXi20$.5a8UTvwIqVfVAMlXJ1EZ0"], + }, + "cn=Manager,o=test": { + "userPassword": ["{CRYPT}$1$sY4mlRve$0eg5TLYMyZfBCIUgU/RPf0"], + }, + "ou=people,o=test": {}, + "uid=alice,ou=people,o=test": { + "uid": ["alice"], + "userPassword": ['{CRYPT}$1$lO/RU6zz$2fJCOwurxBtCqdImkoLQo1'], + "objectClass": settings.AUTH_LDAP_USER_OBJECTCLASS + + settings.AUTH_LDAP_DEV_OBJECTCLASS, + "uidNumber": ["1000"], + "gidNumber": ["1000"], + "givenName": ["Alice"], + "sn": ["Adams"], + "mail": ["alice@test.com"], + }, + "uid=bob,ou=people,o=test": { + "uid": ["bob"], + "userPassword": ['{CRYPT}$1$eFSQMJY6$8y.WUL/ONeEarVXqeCIbH.'], + "objectClass": settings.AUTH_LDAP_USER_OBJECTCLASS, + "uidNumber": ["1001"], + "gidNumber": ["50"], + "givenName": ["Robert"], + "sn": ["Barker"], + "mail": ["bob@test.com"], + } +} + +# User objects +USER_ALICE = User(username='alice', password='ldaptest') + +# Queue objects +QUEUEDUSER = Queue( + username='queueduser', + password='queuedpass', + email='queued_user@test.com', + first_name='queued_first_name', + last_name='queued_last_name', +) + +# login form data +LOGIN_ALICE = {'username': 'alice', 'password': 'ldaptest'} +LOGIN_BOB = {'username': 'bob', 'password': 'ldapmoretest'} +LOGIN_WRONG = {'username': 'wrong', 'password': 'wrong'} + +# signup form data +SIGNUP_TESTUSER = { + 'username': 'testuser', + 'first_name': 'testfirstname', + 'last_name': 'testlastname', + 'email': 'test@test.com', + 'password_origin': 'testpassword', + 'password_verify': 'testpassword', +} diff --git a/requirements.txt b/requirements.txt index aa3a692..11c4030 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,10 +4,10 @@ django-compressor>=1.3 django-discover-runner>=1.0 django-otp>=0.1.7 git+https://github.com/tampakrap/django-ldapdb@okupy#egg=django-ldapdb -edpwd>=0.0.7 mock>=1.0.1 hg+https://bitbucket.org/psagers/mockldap#egg=mockldap passlib>=1.6.1 +pycrypto>=2.6 pyopenssl>=0.13 python-ldap>=2.4.10 python-memcached>=1.53 @@ -38,8 +38,8 @@ setup( 'django-compressor>=1.3', 'django-ldapdb', 'django-otp>=0.1.7', - 'edpwd>=0.0.7', 'passlib>=1.6.1', + 'pycrypto>=2.6', 'pyopenssl>=0.13', 'python-ldap>=2.4.10', 'python-memcached>=1.53', |