~hazmat/charms/trusty/juju-gui/trunk

« back to all changes in this revision

Viewing changes to server/guiserver/tests/test_auth.py

  • Committer: Francesco Banconi
  • Date: 2013-08-30 13:58:14 UTC
  • mfrom: (60.13.26 trunk)
  • Revision ID: francesco.banconi@canonical.com-20130830135814-rib0sa70apyzr3n3
MergedĀ juju-guiĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This file is part of the Juju GUI, which lets users view and manage Juju
 
2
# environments within a graphical interface (https://launchpad.net/juju-gui).
 
3
# Copyright (C) 2013 Canonical Ltd.
 
4
#
 
5
# This program is free software: you can redistribute it and/or modify it under
 
6
# the terms of the GNU Affero General Public License version 3, as published by
 
7
# the Free Software Foundation.
 
8
#
 
9
# This program is distributed in the hope that it will be useful, but WITHOUT
 
10
# ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
 
11
# SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
# 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 
 
17
"""Tests for the Juju GUI server authentication management."""
 
18
 
 
19
import unittest
 
20
 
 
21
from tornado.testing import LogTrapTestCase
 
22
 
 
23
from guiserver import auth
 
24
from guiserver.tests import helpers
 
25
 
 
26
 
 
27
class TestUser(unittest.TestCase):
 
28
 
 
29
    def test_authenticated_repr(self):
 
30
        # An authenticated user is correctly represented.
 
31
        user = auth.User(
 
32
            username='the-doctor', password='bad-wolf', is_authenticated=True)
 
33
        expected = '<User: the-doctor (authenticated)>'
 
34
        self.assertEqual(expected, repr(user))
 
35
 
 
36
    def test_not_authenticated_repr(self):
 
37
        # A not authenticated user is correctly represented.
 
38
        user = auth.User(
 
39
            username='the-doctor', password='bad-wolf', is_authenticated=False)
 
40
        expected = '<User: the-doctor (not authenticated)>'
 
41
        self.assertEqual(expected, repr(user))
 
42
 
 
43
    def test_anonymous_repr(self):
 
44
        # An anonymous user is correctly represented.
 
45
        user = auth.User()
 
46
        expected = '<User: anonymous (not authenticated)>'
 
47
        self.assertEqual(expected, repr(user))
 
48
 
 
49
    def test_str(self):
 
50
        # The string representation of an user is correctly generated.
 
51
        user = auth.User(username='the-doctor')
 
52
        self.assertEqual('the-doctor', str(user))
 
53
 
 
54
 
 
55
class AuthMiddlewareTestMixin(object):
 
56
    """Include tests for the AuthMiddleware.
 
57
 
 
58
    Subclasses must subclass one of the API test mixins in helpers.
 
59
    """
 
60
 
 
61
    def setUp(self):
 
62
        self.user = auth.User()
 
63
        self.auth = auth.AuthMiddleware(self.user, self.get_auth_backend())
 
64
 
 
65
    def assert_user(self, username, password, is_authenticated):
 
66
        """Ensure the current user reflects the given values."""
 
67
        user = self.user
 
68
        self.assertEqual(username, user.username)
 
69
        self.assertEqual(password, user.password)
 
70
        self.assertEqual(is_authenticated, user.is_authenticated)
 
71
 
 
72
    def test_login_request(self):
 
73
        # The authentication process starts if a login request is processed.
 
74
        request = self.make_login_request(username='user', password='passwd')
 
75
        self.auth.process_request(request)
 
76
        self.assertTrue(self.auth.in_progress())
 
77
        self.assert_user('user', 'passwd', False)
 
78
 
 
79
    def test_login_success(self):
 
80
        # The user is logged in if the authentication process completes.
 
81
        request = self.make_login_request(username='user', password='passwd')
 
82
        self.auth.process_request(request)
 
83
        response = self.make_login_response()
 
84
        self.auth.process_response(response)
 
85
        self.assertFalse(self.auth.in_progress())
 
86
        self.assert_user('user', 'passwd', True)
 
87
 
 
88
    def test_login_failure(self):
 
89
        # The user is not logged in if the authentication process fails.
 
90
        request = self.make_login_request()
 
91
        self.auth.process_request(request)
 
92
        response = self.make_login_response(successful=False)
 
93
        self.auth.process_response(response)
 
94
        self.assertFalse(self.auth.in_progress())
 
95
        self.assert_user('', '', False)
 
96
 
 
97
    def test_request_mismatch(self):
 
98
        # The authentication fails if the request and response identifiers
 
99
        # don't match.
 
100
        request = self.make_login_request(
 
101
            request_id=42, username='user', password='passwd')
 
102
        self.auth.process_request(request)
 
103
        response = self.make_login_response(request_id=47)
 
104
        self.auth.process_response(response)
 
105
        self.assertTrue(self.auth.in_progress())
 
106
        self.assert_user('user', 'passwd', False)
 
107
 
 
108
    def test_multiple_auth_requests(self):
 
109
        # Only the last authentication request is taken into consideration.
 
110
        request1 = self.make_login_request(request_id=1)
 
111
        request2 = self.make_login_request(
 
112
            request_id=2, username='user2', password='passwd2')
 
113
        self.auth.process_request(request1)
 
114
        self.auth.process_request(request2)
 
115
        # The first response arrives.
 
116
        response = self.make_login_response(request_id=1)
 
117
        self.auth.process_response(response)
 
118
        # The user is still not autheticated and the auth is in progress.
 
119
        self.assertFalse(self.user.is_authenticated)
 
120
        self.assertTrue(self.auth.in_progress())
 
121
        # The second response arrives.
 
122
        response = self.make_login_response(request_id=2)
 
123
        self.auth.process_response(response)
 
124
        # The user logged in and the auth process completed.
 
125
        self.assert_user('user2', 'passwd2', True)
 
126
        self.assertFalse(self.auth.in_progress())
 
127
 
 
128
    def test_request_id_is_zero(self):
 
129
        # The authentication process starts if a login request is processed
 
130
        # and the request id is zero.
 
131
        request = self.make_login_request(request_id=0)
 
132
        self.auth.process_request(request)
 
133
        self.assertTrue(self.auth.in_progress())
 
134
 
 
135
 
 
136
class TestGoAuthMiddleware(
 
137
        helpers.GoAPITestMixin, AuthMiddlewareTestMixin,
 
138
        LogTrapTestCase, unittest.TestCase):
 
139
    pass
 
140
 
 
141
 
 
142
class TestPythonAuthMiddleware(
 
143
        helpers.PythonAPITestMixin, AuthMiddlewareTestMixin,
 
144
        LogTrapTestCase, unittest.TestCase):
 
145
    pass
 
146
 
 
147
 
 
148
class BackendTestMixin(object):
 
149
    """Include tests for the authentication backends.
 
150
 
 
151
    Subclasses must subclass one of the API test mixins in helpers.
 
152
    """
 
153
 
 
154
    def setUp(self):
 
155
        self.backend = self.get_auth_backend()
 
156
 
 
157
    def test_get_request_id(self):
 
158
        # The request id is correctly returned.
 
159
        request = self.make_login_request(request_id=42)
 
160
        self.assertEqual(42, self.backend.get_request_id(request))
 
161
 
 
162
    def test_get_request_id_failure(self):
 
163
        # If the request id cannot be found, None is returned.
 
164
        self.assertIsNone(self.backend.get_request_id({}))
 
165
 
 
166
    def test_request_is_login(self):
 
167
        # True is returned if a login request is passed.
 
168
        request = self.make_login_request()
 
169
        self.assertTrue(self.backend.request_is_login(request))
 
170
 
 
171
    def test_get_credentials(self):
 
172
        # The user name and password are returned parsing the login request.
 
173
        request = self.make_login_request(username='user', password='passwd')
 
174
        username, password = self.backend.get_credentials(request)
 
175
        self.assertEqual('user', username)
 
176
        self.assertEqual('passwd', password)
 
177
 
 
178
    def test_login_succeeded(self):
 
179
        # True is returned if the login attempt succeeded.
 
180
        response = self.make_login_response()
 
181
        self.assertTrue(self.backend.login_succeeded(response))
 
182
 
 
183
    def test_login_failed(self):
 
184
        # False is returned if the login attempt failed.
 
185
        response = self.make_login_response(successful=False)
 
186
        self.assertFalse(self.backend.login_succeeded(response))
 
187
 
 
188
 
 
189
class TestGoBackend(
 
190
        helpers.GoAPITestMixin, BackendTestMixin, unittest.TestCase):
 
191
 
 
192
    def test_request_is_not_login(self):
 
193
        # False is returned if the passed data is not a login request.
 
194
        requests = (
 
195
            {},
 
196
            {
 
197
                'RequestId': 1,
 
198
                'Type': 'INVALID',
 
199
                'Request': 'Login',
 
200
                'Params': {'AuthTag': 'user', 'Password': 'passwd'},
 
201
            },
 
202
            {
 
203
                'RequestId': 2,
 
204
                'Type': 'Admin',
 
205
                'Request': 'INVALID',
 
206
                'Params': {'AuthTag': 'user', 'Password': 'passwd'},
 
207
            },
 
208
            {
 
209
                'RequestId': 3,
 
210
                'Type': 'Admin',
 
211
                'Request': 'Login',
 
212
                'Params': {'Password': 'passwd'},
 
213
            },
 
214
        )
 
215
        for request in requests:
 
216
            is_login = self.backend.request_is_login(request)
 
217
            self.assertFalse(is_login, request)
 
218
 
 
219
 
 
220
class TestPythonBackend(
 
221
        helpers.PythonAPITestMixin, BackendTestMixin, unittest.TestCase):
 
222
 
 
223
    def test_request_is_not_login(self):
 
224
        # False is returned if the passed data is not a login request.
 
225
        requests = (
 
226
            {},
 
227
            {
 
228
                'request_id': 42,
 
229
                'op': 'INVALID',
 
230
                'user': 'user',
 
231
                'password': 'passwd',
 
232
            },
 
233
            {
 
234
                'request_id': 42,
 
235
                'op': 'login',
 
236
                'password': 'passwd',
 
237
            },
 
238
            {
 
239
                'request_id': 42,
 
240
                'op': 'login',
 
241
                'user': 'user',
 
242
            },
 
243
        )
 
244
        for request in requests:
 
245
            is_login = self.backend.request_is_login(request)
 
246
            self.assertFalse(is_login, request)