From 766c5617007650d90f1d249aaa253755dcd1906c Mon Sep 17 00:00:00 2001 From: NavaL Date: Wed, 27 Jan 2016 19:29:36 +0100 Subject: making async setup user services after auth Issue #583 --- service/pixelated/application.py | 1 - service/pixelated/bitmask_libraries/session.py | 13 +++++---- service/pixelated/config/leap.py | 5 ++-- service/pixelated/resources/auth.py | 7 ++--- service/pixelated/resources/login_resource.py | 22 +++++++++----- .../test/support/integration/multi_user_client.py | 34 +++++++++++++++++----- service/test/unit/resources/test_login_resource.py | 9 ++++-- 7 files changed, 59 insertions(+), 32 deletions(-) diff --git a/service/pixelated/application.py b/service/pixelated/application.py index c7833367..dafab0b1 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -49,7 +49,6 @@ class ServicesFactory(object): return user_id in self._services_by_user def services(self, user_id): - print self._services_by_user.keys() return self._services_by_user[user_id] def log_out_user(self, user_id): diff --git a/service/pixelated/bitmask_libraries/session.py b/service/pixelated/bitmask_libraries/session.py index dfa96388..a88eff11 100644 --- a/service/pixelated/bitmask_libraries/session.py +++ b/service/pixelated/bitmask_libraries/session.py @@ -136,21 +136,24 @@ class LeapSessionFactory(object): self._provider = provider self._config = provider.config - def create(self, username, password): + def create(self, username, password, auth=None): key = self._session_key(username) session = self._lookup_session(key) if not session: - session = self._create_new_session(username, password) + session = self._create_new_session(username, password, auth) self._remember_session(key, session) return session - def _create_new_session(self, username, password): + def _auth_leap(self, username, password): + srp_auth = SRPAuth(self._provider.api_uri, self._provider.local_ca_crt) + return srp_auth.authenticate(username, password) + + def _create_new_session(self, username, password, auth=None): self._create_dir(self._provider.config.leap_home) self._provider.download_certificate() - srp_auth = SRPAuth(self._provider.api_uri, self._provider.local_ca_crt) - auth = srp_auth.authenticate(username, password) + auth = auth or self._auth_leap(username, password) account_email = self._provider.address_for(username) self._create_database_dir(auth.uuid) diff --git a/service/pixelated/config/leap.py b/service/pixelated/config/leap.py index dd475629..a8666086 100644 --- a/service/pixelated/config/leap.py +++ b/service/pixelated/config/leap.py @@ -40,9 +40,8 @@ def initialize_leap_multi_user(provider_hostname, @defer.inlineCallbacks -def authenticate_user(provider, username, password, initial_sync=True): - leap_session = LeapSessionFactory(provider).create(username, password) - +def authenticate_user(provider, username, password, initial_sync=True, auth=None): + leap_session = LeapSessionFactory(provider).create(username, password, auth) if initial_sync: yield leap_session.initial_sync() diff --git a/service/pixelated/resources/auth.py b/service/pixelated/resources/auth.py index 4eb6bd02..5e0221cb 100644 --- a/service/pixelated/resources/auth.py +++ b/service/pixelated/resources/auth.py @@ -53,12 +53,12 @@ class LeapPasswordChecker(object): def _validate_credentials(): try: srp_auth = SRPAuth(self._leap_provider.api_uri, self._leap_provider.local_ca_crt) - srp_auth.authenticate(credentials.username, credentials.password) + return srp_auth.authenticate(credentials.username, credentials.password) except SRPAuthenticationError: raise UnauthorizedLogin() - def _authententicate_user(_): - return authenticate_user(self._leap_provider, credentials.username, credentials.password) + def _authententicate_user(srp_auth): + return authenticate_user(self._leap_provider, credentials.username, credentials.password, auth=srp_auth) d = threads.deferToThread(_validate_credentials) d.addCallback(_authententicate_user) @@ -131,7 +131,6 @@ class PixelatedAuthSessionWrapper(object): def getChildWithDefault(self, path, request): request.postpath.insert(0, request.prepath.pop()) - return self._authorizedResource(request) def _authorizedResource(self, request): diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 065d71e7..6109f232 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -96,10 +96,14 @@ class LoginResource(BaseResource): return renderElement(request, site) def render_POST(self, request): + if self.is_logged_in(request): + return util.redirectTo("/", request) - def render_response(response): - util.redirectTo("/", request) + def render_response(leap_user): + request.setResponseCode(OK) + request.write(open(os.path.join(self._startup_folder, 'Interstitial.html')).read()) request.finish() + self._setup_user_services(leap_user, request) def render_error(error): log.info('Login Error for %s' % request.args['username'][0]) @@ -114,15 +118,17 @@ class LoginResource(BaseResource): @defer.inlineCallbacks def _handle_login(self, request): - if self.is_logged_in(request): - request.setResponseCode(OK) - defer.succeed(None) - return + creds = self._get_creds_from(request) + iface, leap_user, logout = yield self._portal.login(creds, None, IResource) + defer.returnValue(leap_user) + + def _get_creds_from(self, request): username = request.args['username'][0] password = request.args['password'][0] - creds = credentials.UsernamePassword(username, password) - iface, leap_user, logout = yield self._portal.login(creds, None, IResource) + return credentials.UsernamePassword(username, password) + @defer.inlineCallbacks + def _setup_user_services(self, leap_user, request): yield self._initialize_after_login(self._services_factory, leap_user) self._init_http_session(request, leap_user) diff --git a/service/test/support/integration/multi_user_client.py b/service/test/support/integration/multi_user_client.py index 13e1b64b..67b034cc 100644 --- a/service/test/support/integration/multi_user_client.py +++ b/service/test/support/integration/multi_user_client.py @@ -14,19 +14,36 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -from leap.auth import SRPAuth +import json +import shutil + from leap.exceptions import SRPAuthenticationError -from mockito import mock, when +from leap.mail.imap.account import IMAPAccount +from mockito import mock, when, any as ANY +from twisted.cred import portal +from twisted.cred.checkers import AllowAnonymousAccess from twisted.internet import defer +from leap.auth import SRPAuth + +from pixelated.adapter.mailstore.leap_attachment_store import LeapAttachmentStore +from pixelated.adapter.services.feedback_service import FeedbackService from pixelated.application import UserAgentMode, ServicesFactory, set_up_protected_resources + +from pixelated.adapter.mailstore import LeapMailStore +from pixelated.adapter.mailstore.searchable_mailstore import SearchableMailStore + +from pixelated.adapter.search import SearchEngine +from pixelated.adapter.services.draft_service import DraftService from pixelated.bitmask_libraries.session import LeapSession, LeapSessionFactory import pixelated.config.services # from pixelated.config.services import Services +from pixelated.resources.auth import LeapPasswordChecker, SessionChecker, PixelatedRealm, PixelatedAuthSessionWrapper +from pixelated.resources.login_resource import LoginResource from pixelated.resources.root_resource import RootResource from test.support.integration import AppTestClient -from test.support.integration.app_test_client import AppTestAccount - +from test.support.integration.app_test_client import initialize_soledad, AppTestAccount +import test.support.mockito from test.support.test_helper import request_mock @@ -58,18 +75,19 @@ class MultiUserClient(AppTestClient): leap_session.config = config leap_session.fresh_account = False - self._set_leap_srp_auth(username, password) + mock_srp_auth = 'mocked so irrelevant but just need a return value' + self._set_leap_srp_auth(username, password, mock_srp_auth) + when(LeapSessionFactory).create(username, password, mock_srp_auth).thenReturn(leap_session) when(leap_session).initial_sync().thenAnswer(lambda: defer.succeed(None)) - when(LeapSessionFactory).create(username, password).thenReturn(leap_session) when(pixelated.config.services).Services(ANY()).thenReturn(self._test_account.services) request = request_mock(path='/login', method="POST", body={'username': username, 'password': password}) return self._render(request, as_json=False) - def _set_leap_srp_auth(self, username, password): + def _set_leap_srp_auth(self, username, password, mock_srp_auth): auth_dict = {'username': 'password'} if auth_dict[username] == password: - when(SRPAuth).authenticate(username, password).thenReturn(True) + when(SRPAuth).authenticate(username, password).thenReturn(mock_srp_auth) else: when(SRPAuth).authenticate(username, password).thenRaise(SRPAuthenticationError()) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 1ccc530d..0baf7ac0 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -1,3 +1,5 @@ +import os + from leap.exceptions import SRPAuthenticationError from mock import patch from mockito import mock, when, any as ANY, verify, verifyZeroInteractions @@ -93,7 +95,7 @@ class TestLoginPOST(unittest.TestCase): @patch('twisted.web.util.redirectTo') @patch('pixelated.config.services.Services.setup') - def test_login_setups_user_services_and_add_corresponding_session_to_services_factory(self, mock_service_setup, mock_redirect): + def test_login_responds_interstitial_and_add_corresponding_session_to_services_factory(self, mock_service_setup, mock_redirect): irrelevant = None when(self.portal).login(ANY(), None, IResource).thenReturn((irrelevant, self.leap_user, irrelevant)) d = self.web.get(self.request) @@ -101,7 +103,8 @@ class TestLoginPOST(unittest.TestCase): def assert_login_setup_service_for_user(_): verify(self.portal).login(ANY(), None, IResource) verify(self.services_factory).create_services_from(self.leap_session) - mock_redirect.assert_called_once_with('/', self.request) + interstitial_js_in_template = '' + 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) @@ -143,12 +146,12 @@ class TestLoginPOST(unittest.TestCase): @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 + mock_redirect.return_value = "mocked redirection" when(self.portal).login(ANY(), None, IResource).thenRaise(Exception()) d = self.web.get(self.request) def assert_login_setup_service_for_user(_): verifyZeroInteractions(self.portal) - self.assertEqual(200, self.request.responseCode) mock_redirect.assert_called_once_with('/', self.request) d.addCallback(assert_login_setup_service_for_user) -- cgit v1.2.3