summaryrefslogtreecommitdiff
path: root/service/test/unit
diff options
context:
space:
mode:
authorNavaL <ayoyo@thoughtworks.com>2016-10-26 15:55:29 +0200
committerNavaL <ayoyo@thoughtworks.com>2016-10-28 18:02:25 +0200
commit423ca8f9fb7636b336b24ba28bde5d61538bf5fc (patch)
tree6d8f95fafe4f08b4ca557d52bc45d310fa8c37af /service/test/unit
parent3df56a4f3c411c3bde51c88e6e0bf34d5e582119 (diff)
authentication now returns Authentication
leap session creation is only done post-interstitial and that logic is also extracted into its own class #795
Diffstat (limited to 'service/test/unit')
-rw-r--r--service/test/unit/config/test_leap.py70
-rw-r--r--service/test/unit/config/test_services.py58
-rw-r--r--service/test/unit/resources/test_login_resource.py109
-rw-r--r--service/test/unit/test_authentication.py50
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)