diff options
author | NavaL <mnandri@thoughtworks.com> | 2016-01-25 20:47:27 +0100 |
---|---|---|
committer | NavaL <mnandri@thoughtworks.com> | 2016-01-25 20:47:52 +0100 |
commit | bb16581d63d1de23a5dc5457e0030802b9fd00d7 (patch) | |
tree | d8e8adb2d6d76881c62a7fd5f374447995512608 /service | |
parent | a542199a90aefdcee010db02134c40a1aaf6e919 (diff) |
added integration test
Issue #576
Diffstat (limited to 'service')
-rw-r--r-- | service/pixelated/application.py | 2 | ||||
-rw-r--r-- | service/pixelated/resources/auth.py | 11 | ||||
-rw-r--r-- | service/test/integration/test_multi_user_login.py | 51 | ||||
-rw-r--r-- | service/test/support/integration/multi_user_client.py | 134 | ||||
-rw-r--r-- | service/test/support/test_helper.py | 11 | ||||
-rw-r--r-- | service/test/unit/resources/test_login_resource.py | 1 |
6 files changed, 201 insertions, 9 deletions
diff --git a/service/pixelated/application.py b/service/pixelated/application.py index 73d978da..07488985 100644 --- a/service/pixelated/application.py +++ b/service/pixelated/application.py @@ -161,7 +161,7 @@ def _start_in_multi_user_mode(args, root_resource, services_factory): config, provider = initialize_leap_provider(args.provider, args.leap_provider_cert, args.leap_provider_cert_fingerprint, args.leap_home) - checker = LeapPasswordChecker(args, provider) + checker = LeapPasswordChecker(provider) session_checker = SessionChecker() anonymous_resource = LoginResource(services_factory) diff --git a/service/pixelated/resources/auth.py b/service/pixelated/resources/auth.py index 7076490d..2d31316b 100644 --- a/service/pixelated/resources/auth.py +++ b/service/pixelated/resources/auth.py @@ -32,7 +32,7 @@ from twisted.web.resource import IResource, ErrorPage from pixelated.adapter.welcome_mail import add_welcome_mail from pixelated.config.leap import authenticate_user -from pixelated.config.services import Services +from pixelated.config import services from pixelated.resources import IPixelatedSession @@ -46,8 +46,7 @@ class LeapPasswordChecker(object): credentials.IUsernameHashedPassword ) - def __init__(self, setup_args, leap_provider): - self._setup_args = setup_args + def __init__(self, leap_provider): self._leap_provider = leap_provider def requestAvatarId(self, credentials): @@ -99,13 +98,13 @@ class LeapUser(object): @defer.inlineCallbacks def start_services(self, services_factory): - services = Services(self._leap_session) - yield services.setup() + _services = services.Services(self._leap_session) + yield _services.setup() if self._leap_session.fresh_account: yield add_welcome_mail(self._leap_session.mail_store) - services_factory.add_session(self._leap_session.user_auth.uuid, services) + services_factory.add_session(self._leap_session.user_auth.uuid, _services) def init_http_session(self, request): session = IPixelatedSession(request.getSession()) diff --git a/service/test/integration/test_multi_user_login.py b/service/test/integration/test_multi_user_login.py new file mode 100644 index 00000000..3b5b9d4b --- /dev/null +++ b/service/test/integration/test_multi_user_login.py @@ -0,0 +1,51 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. +from twisted.internet import defer + +from test.support.integration import load_mail_from_file +from test.support.integration.multi_user_client import MultiUserClient +from test.support.integration.soledad_test_base import SoledadTestBase + + +class MultiUserLoginTest(MultiUserClient, SoledadTestBase): + + @defer.inlineCallbacks + def test_logged_out_users_should_receive_unauthorized(self): + response, request = yield self.get("/mail", as_json=False) + + response_str = yield response + self.assertEqual(401, request.responseCode) + self.assertEquals('Unauthorized!', response_str) + + @defer.inlineCallbacks + def test_logged_in_users_sees_resources(self): + response, login_request = yield self.login() + mail = load_mail_from_file('mbox00000000') + mail_id = yield self._create_mail_in_soledad(mail) + expected_mail_dict = {'body': u'Dignissimos ducimus veritatis. Est tenetur consequatur quia occaecati. Vel sit sit voluptas.\n\nEarum distinctio eos. Accusantium qui sint ut quia assumenda. Facere dignissimos inventore autem sit amet. Pariatur voluptatem sint est.\n\nUt recusandae praesentium aspernatur. Exercitationem amet placeat deserunt quae consequatur eum. Unde doloremque suscipit quia.\n\n', 'header': {u'date': u'Tue, 21 Apr 2015 08:43:27 +0000 (UTC)', u'to': [u'carmel@murazikortiz.name'], u'x-tw-pixelated-tags': u'nite, macro, trash', u'from': u'darby.senger@zemlak.biz', u'subject': u'Itaque consequatur repellendus provident sunt quia.'}, 'ident': mail_id, 'status': [], 'tags': [], 'textPlainBody': u'Dignissimos ducimus veritatis. Est tenetur consequatur quia occaecati. Vel sit sit voluptas.\n\nEarum distinctio eos. Accusantium qui sint ut quia assumenda. Facere dignissimos inventore autem sit amet. Pariatur voluptatem sint est.\n\nUt recusandae praesentium aspernatur. Exercitationem amet placeat deserunt quae consequatur eum. Unde doloremque suscipit quia.\n\n', 'mailbox': u'inbox', 'attachments': [], 'security_casing': {'imprints': [{'state': 'no_signature_information'}], 'locks': []}} + response, request = yield self.get("/mail/%s" % mail_id, from_request=login_request) + response = yield response + + self.assertEqual(200, request.code) + for key, val in expected_mail_dict.items(): + self.assertEquals(val, response[key]) + + @defer.inlineCallbacks + def test_wrong_credentials_cannot_access_resources(self): + response, login_request = yield self.login('username', 'wrong_password') + response_str = yield response + self.assertEqual(401, login_request.responseCode) + self.assertIn('Invalid credentials', login_request.written) diff --git a/service/test/support/integration/multi_user_client.py b/service/test/support/integration/multi_user_client.py new file mode 100644 index 00000000..c610c3e8 --- /dev/null +++ b/service/test/support/integration/multi_user_client.py @@ -0,0 +1,134 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see <http://www.gnu.org/licenses/>. +import json +import shutil + +from leap.exceptions import SRPAuthenticationError +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 + +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 +from pixelated.config import services as 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 initialize_soledad + +from test.support.test_helper import request_mock + + +class MultiUserClient(AppTestClient): + + @defer.inlineCallbacks + def start_client(self): + self.soledad_test_folder = self._generate_soledad_test_folder_name() + SearchEngine.DEFAULT_INDEX_HOME = self.soledad_test_folder + self.cleanup = lambda: shutil.rmtree(self.soledad_test_folder) + self.soledad = yield initialize_soledad(tempdir=self.soledad_test_folder) + + self.service_factory = ServicesFactory(UserAgentMode(is_single_user=False)) + + root_resource = RootResource(self.service_factory) + anonymous_resource = LoginResource(self.service_factory) + + leap_provider = mock() + checker = LeapPasswordChecker(leap_provider) + session_checker = SessionChecker() + + realm = PixelatedRealm(root_resource, anonymous_resource) + _portal = portal.Portal(realm, [checker, session_checker, AllowAnonymousAccess()]) + + protected_resource = PixelatedAuthSessionWrapper(_portal, root_resource, anonymous_resource, []) + anonymous_resource.set_portal(_portal) + root_resource.initialize(_portal) + + self.resource = protected_resource + + @defer.inlineCallbacks + def login(self, username='username', password='password'): + 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._set_leap_srp_auth(username, password) + when(LeapSessionFactory).create(username, password).thenReturn(leap_session) + _services = yield self.generate_services() + when(config_services).Services(leap_session).thenReturn(_services) + # when(Services).setup().thenReturn(defer.succeed('mocked so irrelevant')) + + request = request_mock(path='/login', method="POST", body={'username': username, 'password': password}) + defer.returnValue(self._render(request, as_json=False)) + + def _set_leap_srp_auth(self, username, password): + auth_dict = {'username': 'password'} + if auth_dict[username] == password: + when(SRPAuth).authenticate(username, password).thenReturn(True) + else: + when(SRPAuth).authenticate(username, password).thenRaise(SRPAuthenticationError()) + + def get(self, path, get_args='', as_json=True, from_request=None): + request = request_mock(path) + request.args = get_args + if from_request: + session = from_request.getSession() + request.session = session + return self._render(request, as_json) + + @defer.inlineCallbacks + def generate_services(self): + search_engine = SearchEngine(self.INDEX_KEY, user_home=self.soledad_test_folder) + self.mail_sender = self._create_mail_sender() + + self.mail_store = SearchableMailStore(LeapMailStore(self.soledad), search_engine) + self.attachment_store = LeapAttachmentStore(self.soledad) + + account_ready_cb = defer.Deferred() + self.account = IMAPAccount(self.ACCOUNT, self.soledad, account_ready_cb) + yield account_ready_cb + self.leap_session = mock() + + mail_service = self._create_mail_service(self.mail_sender, self.mail_store, search_engine, self.attachment_store) + mails = yield mail_service.all_mails() + search_engine.index_mails(mails) + + services = mock() + services.keymanager = mock() + services.mail_service = mail_service + services.draft_service = DraftService(self.mail_store) + services.search_engine = search_engine + services.feedback_service = FeedbackService(self.leap_session) + defer.returnValue(services) diff --git a/service/test/support/test_helper.py b/service/test/support/test_helper.py index 703b62fa..77c74407 100644 --- a/service/test/support/test_helper.py +++ b/service/test/support/test_helper.py @@ -93,11 +93,20 @@ class PixRequestMock(DummyRequest): if len(self.written): return self.written[0] + def redirect(self, url): + self.setResponseCode(302) + self.setHeader(b"location", url) + def request_mock(path='', method='GET', body='', headers={}): dummy = PixRequestMock(path.split('/')) for name, val in headers.iteritems(): dummy.headers[name.lower()] = val dummy.method = method - dummy.content = io.BytesIO(body) + if isinstance(body, str): + dummy.content = io.BytesIO(body) + else: + for key, val in body.items(): + dummy.addArg(key, val) + return dummy diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 04be26f8..ee0845ea 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -1,7 +1,6 @@ from leap.exceptions import SRPAuthenticationError from mock import patch from mockito import mock, when, any as ANY, verify, verifyZeroInteractions -from twisted.cred import credentials from twisted.trial import unittest from twisted.web.resource import IResource from twisted.web.test.requesthelper import DummyRequest |