Rebase previous PR on current master - see PR #915 for details
[pixelated-user-agent.git] / service / test / unit / config / test_leap.py
1 #
2 # Copyright (c) 2015 ThoughtWorks, Inc.
3 #
4 # Pixelated is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # Pixelated is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with Pixelated. If not, see <http://www.gnu.org/licenses/>.
16
17 from leap.soledad.common.errors import InvalidAuthTokenError
18 from mock import MagicMock, patch, Mock
19 from twisted.trial import unittest
20 from twisted.internet import defer
21 from pixelated.config.leap import create_leap_session, BootstrapUserServices, initialize_leap_single_user
22 from pixelated.config.sessions import LeapSessionFactory, SessionCache, SoledadWrongPassphraseException
23 from leap.soledad.common.crypto import UnknownMacMethodError
24
25
26 class TestLeapInit(unittest.TestCase):
27
28     @patch('pixelated.config.sessions.SessionCache.session_key')
29     @defer.inlineCallbacks
30     def test_create_leap_session_calls_initial_sync_and_caches_sessions(self, mock_session_key):
31         mock_session_key.return_value = 'mocked key'
32         provider_mock = MagicMock()
33         auth_mock = MagicMock()
34         session = MagicMock()
35         with patch.object(LeapSessionFactory, '_create_new_session', return_value=session):
36             yield create_leap_session(provider_mock, 'username', 'password', auth=auth_mock)
37
38         session.first_required_sync.assert_called_once()
39         self.assertEqual({'mocked key': session}, SessionCache.sessions)
40
41     @patch('pixelated.config.sessions.SessionCache.lookup_session')
42     @defer.inlineCallbacks
43     def test_create_leap_session_uses_caches_when_available_and_not_sync(self, mock_cache_lookup_session):
44         mock_cache_lookup_session.return_value = 'mocked key'
45         provider_mock = MagicMock()
46         auth_mock = MagicMock()
47         session = MagicMock()
48         mock_cache_lookup_session.return_value = session
49
50         with patch.object(LeapSessionFactory, '_create_new_session', return_value=session):
51             returned_session = yield create_leap_session(provider_mock, 'username', 'password', auth=auth_mock)
52
53         self.assertFalse(session.first_required_sync.called)
54         self.assertEqual(session, returned_session)
55
56     @patch('pixelated.config.leap.initialize_leap_provider')
57     @patch('pixelated.config.leap.credentials')
58     @patch('pixelated.config.leap.events_server')
59     @defer.inlineCallbacks
60     def test_init_single_user_does_bonafide_auth_and_gives_a_leap_session(self, mock_event_server, mock_credentials, mock_init_leap_provider):
61         provider_mock = MagicMock()
62         mock_init_leap_provider.return_value = provider_mock
63         mock_credentials.read.return_value = ('provider_url', 'username', 'password')
64         mock_authenticator = MagicMock()
65
66         with patch('pixelated.config.leap.Authenticator', return_value=mock_authenticator) as mock_instantiate_authenticator:
67             auth_mock = MagicMock()
68             mock_authenticator.authenticate.return_value = defer.succeed(auth_mock)
69             leap_session = MagicMock()
70             deferred_leap_session = defer.succeed(leap_session)
71             with patch.object(LeapSessionFactory, 'create', return_value=deferred_leap_session) as mock_create_leap_session:
72                 returned_session = yield initialize_leap_single_user('leap_provider_cert', 'leap_provider_cert_fingerprint', 'credentials_file', 'leap_home')
73
74         mock_event_server.ensure_server.assert_called_once()
75         mock_credentials.read.assert_called_once_with('credentials_file')
76         mock_init_leap_provider.asser_called_once_with('provider_url', 'leap_provider_cert', 'leap_provider_cert_fingerprint', 'leap_home')
77         mock_instantiate_authenticator.assert_called_once_with(provider_mock)
78         mock_authenticator.authenticate.assert_called_once_with('username', 'password')
79         mock_create_leap_session.assert_called_once_with('username', 'password', auth_mock)
80         self.assertEqual(leap_session, returned_session)
81
82
83 class TestUserBootstrap(unittest.TestCase):
84
85     def setUp(self):
86         self._service_factory = Mock()
87         self._provider = Mock()
88         self._user_bootstrap = BootstrapUserServices(self._service_factory, self._provider)
89
90         username = 'ayoyo'
91         password = 'ayoyo_password'
92         self.username = username
93         self.password = password
94
95         user_auth = Mock()
96         user_auth.username = username
97         self.uuid = 'some_user_uuid'
98         user_auth.uuid = self.uuid
99         self.user_auth = user_auth
100
101         leap_session = Mock()
102         leap_session.user_auth = user_auth
103         leap_session.fresh_account = False
104         self.leap_session = leap_session
105
106     @patch('pixelated.config.leap.create_leap_session')
107     def test_should_create_leap_session(self, mock_create_leap_session):
108         mock_create_leap_session.return_value = self.leap_session
109         self._service_factory.has_session.return_value = False
110
111         self._user_bootstrap.setup(self.user_auth, self.password)
112
113         mock_create_leap_session.called_once_with(self._provider, self.username, self.password, self.user_auth)
114
115     @patch('pixelated.config.leap.create_leap_session')
116     def test_should_setup_user_services_and_map_email(self, mock_create_leap_session):
117         mock_create_leap_session.return_value = self.leap_session
118         self._service_factory.has_session.return_value = False
119
120         self._user_bootstrap.setup(self.user_auth, self.password)
121
122         self._service_factory.create_services_from.assert_called_once_with(self.leap_session)
123         self._service_factory.map_email.assert_called_once_with(self.username, self.uuid)
124
125     @patch('pixelated.config.leap.create_leap_session')
126     def test_should_not_user_services_if_there_is_already_a_session(self, mock_create_leap_session):
127         mock_create_leap_session.return_value = self.leap_session
128         self._service_factory.has_session.return_value = True
129
130         self._user_bootstrap.setup(self.user_auth, self.password)
131
132         self.assertFalse(self._service_factory.create_services_from.called)
133
134     @patch('pixelated.config.leap.add_welcome_mail')
135     @patch('pixelated.config.leap.create_leap_session')
136     def test_should_add_welcome_email_on_a_fresh_account(self, mock_create_leap_session, mock_add_welcome_email):
137         self.leap_session.fresh_account = True
138         mail_store = Mock()
139         self.leap_session.mail_store = mail_store
140         mock_create_leap_session.return_value = self.leap_session
141         self._service_factory.has_session.return_value = False
142         default_language = 'pt-BR'
143
144         self._user_bootstrap.setup(self.user_auth, self.password)
145
146         mock_add_welcome_email.assert_called_once_with(mail_store, default_language)
147
148     @patch('pixelated.config.leap.create_leap_session')
149     @patch('pixelated.config.leap.log.warn')
150     @defer.inlineCallbacks
151     def test__setup__should_log_an_error_raised_from_create_leap_session(self, mock_logger_warn, mock_create_leap_session):
152         mock_create_leap_session.side_effect = SoledadWrongPassphraseException(UnknownMacMethodError("oh no"))
153         with self.assertRaises(SoledadWrongPassphraseException):
154             yield self._user_bootstrap.setup(self.user_auth, self.password, '')
155         mock_logger_warn.assert_called_once_with("SoledadWrongPassphraseException: oh no. Closing session for user: ayoyo")
156
157     @patch('pixelated.config.leap.BootstrapUserServices._setup_user_services')
158     @patch('pixelated.config.leap.create_leap_session')
159     @patch('pixelated.config.leap.log.warn')
160     @defer.inlineCallbacks
161     def test__setup__should_log_an_error_raised_from__setup_user_services(self, mock_logger_warn, mock_create_leap_session, mock_setup_user_services):
162         leap_session = Mock()
163         mock_create_leap_session.return_value = leap_session
164         mock_setup_user_services.side_effect = UnknownMacMethodError("oh no")
165         with self.assertRaises(UnknownMacMethodError):
166             yield self._user_bootstrap.setup(self.user_auth, self.password, '')
167         mock_logger_warn.assert_called_once_with("UnknownMacMethodError: oh no. Closing session for user: ayoyo")
168
169     @patch('pixelated.config.leap.BootstrapUserServices._setup_user_services')
170     @patch('pixelated.config.leap.create_leap_session')
171     @patch('pixelated.config.leap.log.warn')
172     @defer.inlineCallbacks
173     def test__setup__should_close_leap_sesson_on_error_from__setup_user_services(self, mock_logger_warn, mock_create_leap_session, mock_setup_user_services):
174         leap_session = Mock()
175         leap_session.close = Mock()
176         mock_create_leap_session.return_value = leap_session
177         mock_setup_user_services.side_effect = UnknownMacMethodError("oh no")
178         with self.assertRaises(UnknownMacMethodError):
179             yield self._user_bootstrap.setup(self.user_auth, self.password, '')
180         leap_session.close.assert_called_once_with()
181
182     @patch('pixelated.config.leap.BootstrapUserServices._add_welcome_email')
183     @patch('pixelated.config.leap.BootstrapUserServices._setup_user_services')
184     @patch('pixelated.config.leap.create_leap_session')
185     @patch('pixelated.config.leap.log.warn')
186     @defer.inlineCallbacks
187     def test__setup__should_close_leap_sesson_on_error_from__add_welcome_email(self, mock_logger_warn, mock_create_leap_session, _, mock_add_welcome_email):
188         leap_session = Mock()
189         leap_session.close = Mock()
190         mock_create_leap_session.return_value = leap_session
191         mock_add_welcome_email.side_effect = UnknownMacMethodError("oh no")
192         with self.assertRaises(UnknownMacMethodError):
193             yield self._user_bootstrap.setup(self.user_auth, self.password, '')
194         leap_session.close.assert_called_once_with()