diff options
Diffstat (limited to 'service/test/unit')
-rw-r--r-- | service/test/unit/config/test_leap.py | 70 | ||||
-rw-r--r-- | service/test/unit/config/test_services.py | 58 | ||||
-rw-r--r-- | service/test/unit/resources/test_login_resource.py | 109 | ||||
-rw-r--r-- | service/test/unit/test_authentication.py | 50 |
4 files changed, 213 insertions, 74 deletions
diff --git a/service/test/unit/config/test_leap.py b/service/test/unit/config/test_leap.py index ce533c7f..8f582dd8 100644 --- a/service/test/unit/config/test_leap.py +++ b/service/test/unit/config/test_leap.py @@ -1,8 +1,8 @@ from leap.soledad.common.errors import InvalidAuthTokenError -from mock import MagicMock, patch +from mock import MagicMock, patch, Mock from twisted.trial import unittest from twisted.internet import defer -from pixelated.config.leap import create_leap_session +from pixelated.config.leap import create_leap_session, BootstrapUserServices from pixelated.config.sessions import LeapSessionFactory, SessionCache @@ -35,3 +35,69 @@ class TestAuth(unittest.TestCase): self.assertFalse(session.first_required_sync.called) self.assertEqual(session, returned_session) + + +class TestUserBootstrap(unittest.TestCase): + + def setUp(self): + self._service_factory = Mock() + self._provider = Mock() + self._user_bootstrap = BootstrapUserServices(self._service_factory, self._provider) + + username = 'ayoyo' + password = 'ayoyo_password' + self.username = username + self.password = password + + user_auth = Mock() + user_auth.username = username + self.uuid = 'some_user_uuid' + user_auth.uuid = self.uuid + self.user_auth = user_auth + + leap_session = Mock() + leap_session.user_auth = user_auth + leap_session.fresh_account = False + self.leap_session = leap_session + + @patch('pixelated.config.leap.create_leap_session') + def test_should_create_leap_session(self, mock_create_leap_session): + mock_create_leap_session.return_value = self.leap_session + self._service_factory.has_session.return_value = False + + self._user_bootstrap.setup(self.user_auth, self.password) + + mock_create_leap_session.called_once_with(self._provider, self.username, self.password, self.user_auth) + + @patch('pixelated.config.leap.create_leap_session') + def test_should_setup_user_services_and_map_email(self, mock_create_leap_session): + mock_create_leap_session.return_value = self.leap_session + self._service_factory.has_session.return_value = False + + self._user_bootstrap.setup(self.user_auth, self.password) + + self._service_factory.create_services_from.assert_called_once_with(self.leap_session) + self._service_factory.map_email.assert_called_once_with(self.username, self.uuid) + + @patch('pixelated.config.leap.create_leap_session') + def test_should_not_user_services_if_there_is_already_a_session(self, mock_create_leap_session): + mock_create_leap_session.return_value = self.leap_session + self._service_factory.has_session.return_value = True + + self._user_bootstrap.setup(self.user_auth, self.password) + + self.assertFalse(self._service_factory.create_services_from.called) + + @patch('pixelated.config.leap.add_welcome_mail') + @patch('pixelated.config.leap.create_leap_session') + def test_should_add_welcome_email_on_a_fresh_account(self, mock_create_leap_session, mock_add_welcome_email): + self.leap_session.fresh_account = True + mail_store = Mock() + self.leap_session.mail_store = mail_store + mock_create_leap_session.return_value = self.leap_session + self._service_factory.has_session.return_value = False + some_language = 'en-US' + + self._user_bootstrap.setup(self.user_auth, self.password, '') + + mock_add_welcome_email.called_once_with(mail_store, some_language) diff --git a/service/test/unit/config/test_services.py b/service/test/unit/config/test_services.py index 8277c919..ed221261 100644 --- a/service/test/unit/config/test_services.py +++ b/service/test/unit/config/test_services.py @@ -15,6 +15,7 @@ # along with Pixelated. If not, see <http://www.gnu.org/licenses/>. import unittest +from mock import Mock, ANY, patch from mockito import mock, verify from pixelated.config.services import Services, ServicesFactory @@ -36,9 +37,58 @@ class ServicesTest(unittest.TestCase): class ServicesFactoryTest(unittest.TestCase): + def setUp(self): + self.service_factory = ServicesFactory(Mock()) + + def test_users_has_no_default_sessions(self): + user_id = ANY + self.assertFalse(self.service_factory.has_session(user_id)) + + def test_add_user_sessions(self): + user_id = 'irrelevant' + some_service = Mock() + + self.service_factory.add_session(user_id, some_service) + + self.assertTrue(self.service_factory.has_session(user_id)) + self.assertEqual(some_service, self.service_factory.services(user_id)) + def test_online_sessions_counts_logged_in_users(self): - service_factory = ServicesFactory(mock()) - service_factory.add_session('some_id1', mock()) - service_factory.add_session('some_id2', mock()) + self.service_factory.add_session('some_id1', mock()) + self.service_factory.add_session('some_id2', mock()) + + self.assertEqual(2, self.service_factory.online_sessions()) + + @patch('pixelated.config.services.Services.setup') + def test_create_services_from_leap_session_sets_up_services_and_add_a_user_session(self, mock_setup_services): + leap_session = Mock() + user_id = 'irrelevant' + leap_session.user_auth.uuid = user_id + + self.service_factory.create_services_from(leap_session) + + self.assertTrue(mock_setup_services.called) + self.assertTrue(self.service_factory.has_session(user_id)) + + def test_destroy_session_using_close_user_services_and_deletes_sessions(self): + user_id = 'irrelevant' + some_service = Mock() + self.service_factory.add_session(user_id, some_service) + + self.service_factory.destroy_session(user_id) + + self.assertFalse(self.service_factory.has_session(user_id)) + self.assertTrue(some_service.close.called) + + def test_sessions_can_be_destroyed_using_email_rather_than_uuid(self): + user_id = 'irrelevant' + username = 'haha' + email = '%s@ha.ha' % username + some_service = Mock() + self.service_factory.add_session(user_id, some_service) + self.service_factory.map_email(username, user_id) + + self.service_factory.destroy_session(email, using_email=True) - self.assertEqual(2, service_factory.online_sessions()) + self.assertFalse(self.service_factory.has_session(user_id)) + self.assertTrue(some_service.close.called) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 5843ef28..d3d7ba64 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -1,17 +1,15 @@ import os -from leap.bitmask.bonafide._srp import SRPAuthError from mock import patch -from mockito import mock, when, any as ANY, verify, verifyZeroInteractions, verifyNoMoreInteractions +from mockito import mock, when, any as ANY +from twisted.cred.error import UnauthorizedLogin +from twisted.internet import defer from twisted.trial import unittest -from twisted.web.resource import IResource from twisted.web.test.requesthelper import DummyRequest -from pixelated.config.sessions import LeapSession from pixelated.resources.login_resource import LoginResource from pixelated.resources.login_resource import parse_accept_language from test.unit.resources import DummySite -from test.support.mockito import AnswerSelector class TestParseAcceptLanguage(unittest.TestCase): @@ -163,9 +161,8 @@ class TestLoginResource(unittest.TestCase): class TestLoginPOST(unittest.TestCase): def setUp(self): self.services_factory = mock() - self.portal = mock() self.provider = mock() - self.resource = LoginResource(self.services_factory, self.portal) + self.resource = LoginResource(self.services_factory, self.provider) self.web = DummySite(self.resource) self.request = DummyRequest(['']) @@ -176,83 +173,85 @@ class TestLoginPOST(unittest.TestCase): self.password = password self.request.addArg('password', password) self.request.method = 'POST' - leap_session = mock(LeapSession) user_auth = mock() user_auth.uuid = 'some_user_uuid' - leap_session.user_auth = user_auth - config = mock() - config.leap_home = 'some_folder' - leap_session.config = config - leap_session.fresh_account = False - self.leap_session = leap_session self.user_auth = user_auth - def mock_user_has_services_setup(self): - when(self.services_factory).has_session('some_user_uuid').thenReturn(True) + @patch('pixelated.authentication.Authenticator.authenticate') + @patch('twisted.web.util.redirectTo') + @patch('pixelated.resources.session.PixelatedSession.is_logged_in') + def test_should_redirect_to_home_if_user_if_already_logged_in(self, mock_logged_in, mock_redirect, mock_authenticate): + mock_logged_in.return_value = True + when(self.services_factory).has_session(ANY()).thenReturn(True) + mock_redirect.return_value = "mocked redirection" - def test_login_responds_interstitial_and_add_corresponding_session_to_services_factory(self): - irrelevant = None - when(self.portal).login(ANY(), None, IResource).thenReturn((irrelevant, self.leap_session, irrelevant)) - with patch('mockito.invocation.AnswerSelector', AnswerSelector): - when(self.services_factory).create_services_from(self.leap_session).thenAnswer(self.mock_user_has_services_setup) + d = self.web.get(self.request) + + def assert_redirected_to_home(_): + mock_redirect.assert_called_once_with('/', self.request) + self.assertFalse(mock_authenticate.called) + + d.addCallback(assert_redirected_to_home) + return d + + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_should_return_form_back_with_error_message_when_login_fails(self, mock_authenticate, + mock_user_bootstrap_setup): + mock_authenticate.side_effect = UnauthorizedLogin() d = self.web.get(self.request) - def assert_login_setup_service_for_user(_): - verify(self.portal).login(ANY(), None, IResource) - verify(self.services_factory).create_services_from(self.leap_session) - verify(self.services_factory).map_email('ayoyo', 'some_user_uuid') - interstitial_js_in_template = '<script src="startup-assets/Interstitial.js"></script>' - self.assertIn(interstitial_js_in_template, self.request.written[0]) - self.assertTrue(self.resource.is_logged_in(self.request)) + def assert_error_response_and_user_services_not_setup(_): + mock_authenticate.assert_called_once_with(self.username, self.password) + self.assertEqual(401, self.request.responseCode) + written_response = ''.join(self.request.written) + self.assertIn('Invalid credentials', written_response) + self.assertFalse(mock_user_bootstrap_setup.called) + self.assertFalse(self.resource.get_session(self.request).is_logged_in()) - d.addCallback(assert_login_setup_service_for_user) + d.addCallback(assert_error_response_and_user_services_not_setup) return d - def test_login_does_not_reload_services_if_already_loaded(self): - irrelevant = None - when(self.portal).login(ANY(), None, IResource).thenReturn((irrelevant, self.leap_session, irrelevant)) - when(self.services_factory).has_session('some_user_uuid').thenReturn(True) + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_successful_login_responds_interstitial(self, mock_authenticate, mock_user_bootstrap_setup): + mock_authenticate.return_value = self.user_auth d = self.web.get(self.request) - def assert_login_setup_service_for_user(_): - verify(self.portal).login(ANY(), None, IResource) - verify(self.services_factory).has_session('some_user_uuid') - verifyNoMoreInteractions(self.services_factory) + def assert_interstitial_in_response(_): + mock_authenticate.assert_called_once_with(self.username, self.password) interstitial_js_in_template = '<script src="startup-assets/Interstitial.js"></script>' self.assertIn(interstitial_js_in_template, self.request.written[0]) - self.assertTrue(self.resource.is_logged_in(self.request)) - d.addCallback(assert_login_setup_service_for_user) + d.addCallback(assert_interstitial_in_response) return d - def test_should_return_form_back_with_error_message_when_login_fails(self): - when(self.portal).login(ANY(), None, IResource).thenRaise(Exception()) + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_successful_login_runs_user_services_bootstrap_when_interstitial_loaded(self, mock_authenticate, mock_user_bootstrap_setup): + mock_authenticate.return_value = self.user_auth + d = self.web.get(self.request) def assert_login_setup_service_for_user(_): - verify(self.portal).login(ANY(), None, IResource) - self.assertEqual(401, self.request.responseCode) - written_response = ''.join(self.request.written) - self.assertIn('Invalid credentials', written_response) - self.assertFalse(self.resource.is_logged_in(self.request)) + mock_user_bootstrap_setup.assert_called_once_with(self.user_auth, self.password, 'pt-BR') d.addCallback(assert_login_setup_service_for_user) return d - @patch('twisted.web.util.redirectTo') - @patch('pixelated.resources.session.PixelatedSession.is_logged_in') - def test_should_not_process_login_if_already_logged_in(self, mock_logged_in, mock_redirect): - mock_logged_in.return_value = True - when(self.services_factory).has_session(ANY()).thenReturn(True) - mock_redirect.return_value = "mocked redirection" - when(self.portal).login(ANY(), None, IResource).thenRaise(Exception()) + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_successful_adds_cookies_to_indicat_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup): + mock_authenticate.return_value = self.user_auth + irrelevant = None + mock_user_bootstrap_setup.return_value = defer.succeed(irrelevant) + d = self.web.get(self.request) def assert_login_setup_service_for_user(_): - verifyZeroInteractions(self.portal) - mock_redirect.assert_called_once_with('/', self.request) + self.assertTrue(self.resource.get_session(self.request).is_logged_in()) d.addCallback(assert_login_setup_service_for_user) return d diff --git a/service/test/unit/test_authentication.py b/service/test/unit/test_authentication.py index cebb6543..b729e64f 100644 --- a/service/test/unit/test_authentication.py +++ b/service/test/unit/test_authentication.py @@ -8,7 +8,7 @@ from mock import patch, Mock from pixelated.authentication import Authenticator from pixelated.bitmask_libraries.provider import LeapProvider - +from pixelated.config.leap import Authentication PROVIDER_JSON = { "api_uri": "https://api.domain.org:4430", @@ -21,36 +21,60 @@ PROVIDER_JSON = { class AuthenticatorTest(unittest.TestCase): def setUp(self): + self._domain = 'domain.org' with patch.object(LeapProvider, 'fetch_provider_json', return_value=PROVIDER_JSON): - self._leap_provider = LeapProvider('domain.org') + self._leap_provider = LeapProvider(self._domain) @inlineCallbacks def test_bonafide_srp_exceptions_should_raise_unauthorized_login(self): auth = Authenticator(self._leap_provider) mock_bonafide_session = Mock() mock_bonafide_session.authenticate = Mock(side_effect=SRPAuthError()) - with patch('pixelated.config.leap.Session', return_value=mock_bonafide_session): + with patch('pixelated.authentication.Session', return_value=mock_bonafide_session): with self.assertRaises(UnauthorizedLogin): yield auth.authenticate('username', 'password') @inlineCallbacks - def test_auth_username_with_domain_only_makes_bonafide_auth_with_username(self): + def test_domain_name_is_stripped_before_making_bonafide_srp_auth(self): + username_without_domain = 'username' + username_with_domain = '%s@%s' % (username_without_domain, self._domain) auth = Authenticator(self._leap_provider) - with patch('pixelated.authentication.authenticate') as mock_leap_authenticate: - yield auth.authenticate('username@domain.org', 'password') - mock_leap_authenticate.assert_called_once_with(self._leap_provider, 'username', 'password') + with patch.object(Authenticator, '_bonafide_auth') as mock_leap_authenticate: + yield auth.authenticate(username_with_domain, 'password') + mock_leap_authenticate.assert_called_once_with(username_without_domain, 'password') + + @inlineCallbacks + def test_successful_bonafide_auth_should_return_the_user_authentication_object(self): + auth = Authenticator(self._leap_provider) + mock_bonafide_session = Mock() + mock_srp_auth = Mock() + mock_srp_auth.token = 'some_token' + mock_srp_auth.uuid = 'some_uuid' + mock_bonafide_session.authenticate = Mock(return_value=mock_srp_auth) + with patch('pixelated.authentication.Session', return_value=mock_srp_auth): + resulting_auth = yield auth.authenticate('username@domain.org', 'password') + self.assertIsInstance(resulting_auth, Authentication) + self.assertEquals('username', resulting_auth.username) + self.assertEquals('some_token', resulting_auth.token) + self.assertEquals('some_uuid', resulting_auth.uuid) - def test_validate_username_accepts_username(self): + def test_username_without_domain_is_not_changed(self): + username_without_domain = 'username' auth = Authenticator(self._leap_provider) - self.assertTrue(auth.validate_username('username')) + self.assertEqual(username_without_domain, auth.clean_username(username_without_domain)) - def test_validate_username_accepts_email_address(self): + def test_username_with_domain_is_stripped(self): + username_without_domain = 'username' + username_with_domain = '%s@%s' % (username_without_domain, self._domain) auth = Authenticator(self._leap_provider) - self.assertTrue(auth.validate_username('username@domain.org')) + self.assertEqual(username_without_domain, auth.clean_username(username_with_domain)) - def test_validate_username_denies_other_domains(self): + def test_username_with_wrong_domain_raises_exception(self): + username_without_domain = 'username' + username_with_wrong_domain = '%s@%s' % (username_without_domain, 'wrongdomain.org') auth = Authenticator(self._leap_provider) - self.assertFalse(auth.validate_username('username@wrongdomain.org')) + with self.assertRaises(UnauthorizedLogin): + auth.clean_username(username_with_wrong_domain) def test_username_with_domain(self): auth = Authenticator(self._leap_provider) |