diff --git a/tests/test_webinterface.py b/tests/test_webinterface.py index 1bc319a..4cbd626 100644 --- a/tests/test_webinterface.py +++ b/tests/test_webinterface.py @@ -4,6 +4,7 @@ import pytest from bs4 import BeautifulSoup from flask_security.utils import find_user from imaginaerraum_door_admin.door_handle import DoorHandle +from imaginaerraum_door_admin.auth import ExtendedLoginForm import re import secrets import pathlib @@ -53,16 +54,73 @@ def test_login_headless(client): for link in soup.findAll('a', attrs={'class': ['btn'], 'role': 'button'})]) +def test_validate_ldap(client, mocker): + # mock ldap Connection object to simulate successful authentication + import ldap3 + def init_success(self, *args, **kwargs): + pass + def init_LDAPBindError(self, *args, **kwargs): + raise ldap3.core.exceptions.LDAPBindError() + def init_LDAPSocketOpenError(self, *args, **kwargs): + raise ldap3.core.exceptions.LDAPSocketOpenError() + def init_Exception(self, *args, **kwargs): + raise Exception() + def search_success(self, *args, **kwargs): + return True + def search_failure(self, *args, **kwargs): + return False + + mocker.patch.object(ldap3.Connection, '__init__', init_success) + mocker.patch.object(ldap3.Connection, 'search', search_success) + mock_entries = mocker.MagicMock() + mock_entries[0].mail.value = 'user@example.com' + mocker.patch.object(ldap3.Connection, 'entries', mock_entries) + + with client.application.app_context(): + # test successful login + form = ExtendedLoginForm() + form.email.data = 'user' + form.password.data = 'password' + result = form.validate_ldap() + assert result[0] + assert result[1]['username'] == 'user' + assert result[1]['email'] == 'user@example.com' + assert result[1]['roles'] == ['admin'] + + # test failing ldap search + mocker.patch.object(ldap3.Connection, 'search', search_failure) + result = form.validate_ldap() + + assert not result[0] + assert result[1] is None + + # test some errors in ldap Connection and authentication + mocker.patch.object(ldap3.Connection, '__init__', init_LDAPBindError) + result = form.validate_ldap() + assert not result[0] + assert result[1] is None + + mocker.patch.object(ldap3.Connection, '__init__', init_LDAPSocketOpenError) + result = form.validate_ldap() + assert not result[0] + assert result[1] is None + + mocker.patch.object(ldap3.Connection, '__init__', init_Exception) + result = form.validate_ldap() + assert not result[0] + assert result[1] is None + + def test_login_ldap(client, temp_user, mocker): # mock ldap validation for admin user - def mock_validate(username, password): - auth = username == temp_user['username'] and password == temp_user['password'] + def mock_validate(self): + auth = self.email.data == temp_user['username'] and self.password.data == temp_user['password'] user_data = {'username': temp_user['username'], 'email': temp_user['email'], 'roles': ['admin'], 'password': temp_user['password']} return auth, user_data - mocker.patch('imaginaerraum_door_admin.auth.validate_ldap', mock_validate) + mocker.patch('imaginaerraum_door_admin.auth.ExtendedLoginForm.validate_ldap', mock_validate) user = find_user(temp_user['username']) # remove local role so that ldap authentication is the default @@ -84,14 +142,14 @@ def test_login_ldap(client, temp_user, mocker): def test_login_ldap_new_user(client, mocker): # mock ldap validation for admin user - def mock_validate(username, password): + def mock_validate(self): auth = True user_data = {'username': 'Balrog', 'email': 'balrog@moria.me', 'roles': ['admin'], 'password': 'youshallnotpass'} return auth, user_data - mocker.patch('imaginaerraum_door_admin.auth.validate_ldap', mock_validate) + mocker.patch('imaginaerraum_door_admin.auth.ExtendedLoginForm.validate_ldap', mock_validate) # initially, the Balrog user should not exist user = find_user('Balrog')