Commit | Line | Data |
---|---|---|
5adb906a RE |
1 | # GNU MediaGoblin -- federated, autonomous media hosting |
2 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. | |
3 | # | |
4 | # This program 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 | # This program 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 this program. If not, see <http://www.gnu.org/licenses/>. | |
df206ab6 | 16 | |
5adb906a RE |
17 | import pkg_resources |
18 | import pytest | |
e49b7e02 | 19 | import six |
9459fa3c BP |
20 | import six.moves.urllib.parse as urlparse |
21 | try: | |
22 | import mock | |
23 | except ImportError: | |
24 | import unittest.mock as mock | |
5adb906a | 25 | |
df206ab6 CAW |
26 | openid_consumer = pytest.importorskip( |
27 | "openid.consumer.consumer") | |
5adb906a RE |
28 | |
29 | from mediagoblin import mg_globals | |
30 | from mediagoblin.db.base import Session | |
31 | from mediagoblin.db.models import User | |
32 | from mediagoblin.plugins.openid.models import OpenIDUserURL | |
33 | from mediagoblin.tests.tools import get_app, fixture_add_user | |
34 | from mediagoblin.tools import template | |
35 | ||
f9931418 | 36 | |
5adb906a RE |
37 | # App with plugin enabled |
38 | @pytest.fixture() | |
39 | def openid_plugin_app(request): | |
40 | return get_app( | |
41 | request, | |
42 | mgoblin_config=pkg_resources.resource_filename( | |
43 | 'mediagoblin.tests.auth_configs', | |
44 | 'openid_appconfig.ini')) | |
45 | ||
46 | ||
47 | class TestOpenIDPlugin(object): | |
48 | def _setup(self, openid_plugin_app, value=True, edit=False, delete=False): | |
49 | if value: | |
df206ab6 | 50 | response = openid_consumer.SuccessResponse(mock.Mock(), mock.Mock()) |
5adb906a RE |
51 | if edit or delete: |
52 | response.identity_url = u'http://add.myopenid.com' | |
53 | else: | |
54 | response.identity_url = u'http://real.myopenid.com' | |
55 | self._finish_verification = mock.Mock(return_value=response) | |
56 | else: | |
57 | self._finish_verification = mock.Mock(return_value=False) | |
58 | ||
59 | @mock.patch('mediagoblin.plugins.openid.views._response_email', mock.Mock(return_value=None)) | |
60 | @mock.patch('mediagoblin.plugins.openid.views._response_nickname', mock.Mock(return_value=None)) | |
61 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
62 | def _setup_start(self, openid_plugin_app, edit, delete): | |
63 | if edit: | |
64 | self._start_verification = mock.Mock(return_value=openid_plugin_app.post( | |
65 | '/edit/openid/finish/')) | |
66 | elif delete: | |
67 | self._start_verification = mock.Mock(return_value=openid_plugin_app.post( | |
68 | '/edit/openid/delete/finish/')) | |
69 | else: | |
70 | self._start_verification = mock.Mock(return_value=openid_plugin_app.post( | |
71 | '/auth/openid/login/finish/')) | |
72 | _setup_start(self, openid_plugin_app, edit, delete) | |
73 | ||
74 | def test_bad_login(self, openid_plugin_app): | |
75 | """ Test that attempts to login with invalid paramaters""" | |
76 | ||
77 | # Test GET request for auth/register page | |
78 | res = openid_plugin_app.get('/auth/register/').follow() | |
79 | ||
80 | # Make sure it redirected to the correct place | |
81 | assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' | |
82 | ||
83 | # Test GET request for auth/login page | |
84 | res = openid_plugin_app.get('/auth/login/') | |
85 | res.follow() | |
86 | ||
87 | # Correct redirect? | |
88 | assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' | |
89 | ||
90 | # Test GET request for auth/openid/register page | |
91 | res = openid_plugin_app.get('/auth/openid/register/') | |
92 | res.follow() | |
93 | ||
94 | # Correct redirect? | |
95 | assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' | |
96 | ||
97 | # Test GET request for auth/openid/login/finish page | |
98 | res = openid_plugin_app.get('/auth/openid/login/finish/') | |
99 | res.follow() | |
100 | ||
101 | # Correct redirect? | |
102 | assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' | |
103 | ||
104 | # Test GET request for auth/openid/login page | |
105 | res = openid_plugin_app.get('/auth/openid/login/') | |
106 | ||
107 | # Correct place? | |
108 | assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT | |
109 | ||
110 | # Try to login with an empty form | |
111 | template.clear_test_template_context() | |
112 | openid_plugin_app.post( | |
113 | '/auth/openid/login/', {}) | |
114 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] | |
115 | form = context['login_form'] | |
116 | assert form.openid.errors == [u'This field is required.'] | |
117 | ||
118 | # Try to login with wrong form values | |
119 | template.clear_test_template_context() | |
120 | openid_plugin_app.post( | |
121 | '/auth/openid/login/', { | |
122 | 'openid': 'not_a_url.com'}) | |
123 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] | |
124 | form = context['login_form'] | |
125 | assert form.openid.errors == [u'Please enter a valid url.'] | |
126 | ||
127 | # Should be no users in the db | |
128 | assert User.query.count() == 0 | |
129 | ||
130 | # Phony OpenID URl | |
131 | template.clear_test_template_context() | |
132 | openid_plugin_app.post( | |
133 | '/auth/openid/login/', { | |
134 | 'openid': 'http://phoney.myopenid.com/'}) | |
135 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/login.html'] | |
136 | form = context['login_form'] | |
137 | assert form.openid.errors == [u'Sorry, the OpenID server could not be found'] | |
138 | ||
139 | def test_login(self, openid_plugin_app): | |
140 | """Tests that test login and registion with openid""" | |
141 | # Test finish_login redirects correctly when response = False | |
142 | self._setup(openid_plugin_app, False) | |
143 | ||
144 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
145 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
146 | def _test_non_response(): | |
147 | template.clear_test_template_context() | |
148 | res = openid_plugin_app.post( | |
149 | '/auth/openid/login/', { | |
150 | 'openid': 'http://phoney.myopenid.com/'}) | |
151 | res.follow() | |
152 | ||
153 | # Correct Place? | |
154 | assert urlparse.urlsplit(res.location)[2] == '/auth/openid/login/' | |
155 | assert 'mediagoblin/plugins/openid/login.html' in template.TEMPLATE_TEST_CONTEXT | |
156 | _test_non_response() | |
157 | ||
158 | # Test login with new openid | |
159 | # Need to clear_test_template_context before calling _setup | |
160 | template.clear_test_template_context() | |
161 | self._setup(openid_plugin_app) | |
162 | ||
163 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
164 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
165 | def _test_new_user(): | |
166 | openid_plugin_app.post( | |
167 | '/auth/openid/login/', { | |
168 | 'openid': u'http://real.myopenid.com'}) | |
169 | ||
170 | # Right place? | |
171 | assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT | |
172 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] | |
173 | register_form = context['register_form'] | |
174 | ||
175 | # Register User | |
176 | res = openid_plugin_app.post( | |
177 | '/auth/openid/register/', { | |
178 | 'openid': register_form.openid.data, | |
179 | 'username': u'chris', | |
180 | 'email': u'chris@example.com'}) | |
181 | res.follow() | |
182 | ||
183 | # Correct place? | |
184 | assert urlparse.urlsplit(res.location)[2] == '/u/chris/' | |
515e3bd9 | 185 | assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT |
5adb906a RE |
186 | |
187 | # No need to test if user is in logged in and verification email | |
188 | # awaits, since openid uses the register_user function which is | |
189 | # tested in test_auth | |
190 | ||
191 | # Logout User | |
192 | openid_plugin_app.get('/auth/logout') | |
193 | ||
194 | # Get user and detach from session | |
44082b12 RE |
195 | test_user = mg_globals.database.User.query.filter_by( |
196 | username=u'chris').first() | |
5adb906a RE |
197 | Session.expunge(test_user) |
198 | ||
199 | # Log back in | |
200 | # Could not get it to work by 'POST'ing to /auth/openid/login/ | |
201 | template.clear_test_template_context() | |
202 | res = openid_plugin_app.post( | |
203 | '/auth/openid/login/finish/', { | |
204 | 'openid': u'http://real.myopenid.com'}) | |
205 | res.follow() | |
206 | ||
207 | assert urlparse.urlsplit(res.location)[2] == '/' | |
208 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT | |
209 | ||
210 | # Make sure user is in the session | |
211 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] | |
212 | session = context['request'].session | |
e49b7e02 | 213 | assert session['user_id'] == six.text_type(test_user.id) |
5adb906a RE |
214 | |
215 | _test_new_user() | |
216 | ||
217 | # Test register with empty form | |
218 | template.clear_test_template_context() | |
219 | openid_plugin_app.post( | |
220 | '/auth/openid/register/', {}) | |
221 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] | |
222 | register_form = context['register_form'] | |
223 | ||
224 | assert register_form.openid.errors == [u'This field is required.'] | |
225 | assert register_form.email.errors == [u'This field is required.'] | |
226 | assert register_form.username.errors == [u'This field is required.'] | |
227 | ||
228 | # Try to register with existing username and email | |
229 | template.clear_test_template_context() | |
230 | openid_plugin_app.post( | |
231 | '/auth/openid/register/', { | |
232 | 'openid': 'http://real.myopenid.com', | |
233 | 'email': 'chris@example.com', | |
234 | 'username': 'chris'}) | |
235 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] | |
236 | register_form = context['register_form'] | |
237 | ||
238 | assert register_form.username.errors == [u'Sorry, a user with that name already exists.'] | |
239 | assert register_form.email.errors == [u'Sorry, a user with that email address already exists.'] | |
240 | assert register_form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] | |
241 | ||
242 | def test_add_delete(self, openid_plugin_app): | |
243 | """Test adding and deleting openids""" | |
244 | # Add user | |
6483b370 | 245 | test_user = fixture_add_user(password='', privileges=[u'active']) |
5adb906a RE |
246 | openid = OpenIDUserURL() |
247 | openid.openid_url = 'http://real.myopenid.com' | |
248 | openid.user_id = test_user.id | |
249 | openid.save() | |
250 | ||
251 | # Log user in | |
252 | template.clear_test_template_context() | |
253 | self._setup(openid_plugin_app) | |
254 | ||
255 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
256 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
257 | def _login_user(): | |
258 | openid_plugin_app.post( | |
259 | '/auth/openid/login/finish/', { | |
260 | 'openid': u'http://real.myopenid.com'}) | |
261 | ||
262 | _login_user() | |
263 | ||
264 | # Try and delete only OpenID url | |
265 | template.clear_test_template_context() | |
266 | res = openid_plugin_app.post( | |
267 | '/edit/openid/delete/', { | |
268 | 'openid': 'http://real.myopenid.com'}) | |
269 | assert 'mediagoblin/plugins/openid/delete.html' in template.TEMPLATE_TEST_CONTEXT | |
270 | ||
271 | # Add OpenID to user | |
272 | # Empty form | |
273 | template.clear_test_template_context() | |
274 | res = openid_plugin_app.post( | |
275 | '/edit/openid/', {}) | |
276 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
277 | form = context['form'] | |
278 | assert form.openid.errors == [u'This field is required.'] | |
279 | ||
280 | # Try with a bad url | |
281 | template.clear_test_template_context() | |
282 | openid_plugin_app.post( | |
283 | '/edit/openid/', { | |
284 | 'openid': u'not_a_url.com'}) | |
285 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
286 | form = context['form'] | |
287 | assert form.openid.errors == [u'Please enter a valid url.'] | |
288 | ||
289 | # Try with a url that's already registered | |
290 | template.clear_test_template_context() | |
291 | openid_plugin_app.post( | |
292 | '/edit/openid/', { | |
293 | 'openid': 'http://real.myopenid.com'}) | |
294 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
295 | form = context['form'] | |
296 | assert form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] | |
297 | ||
298 | # Test adding openid to account | |
299 | # Need to clear_test_template_context before calling _setup | |
300 | template.clear_test_template_context() | |
301 | self._setup(openid_plugin_app, edit=True) | |
302 | ||
303 | # Need to remove openid_url from db because it was added at setup | |
304 | openid = OpenIDUserURL.query.filter_by( | |
305 | openid_url=u'http://add.myopenid.com') | |
306 | openid.delete() | |
307 | ||
308 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
309 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
310 | def _test_add(): | |
311 | # Successful add | |
312 | template.clear_test_template_context() | |
313 | res = openid_plugin_app.post( | |
314 | '/edit/openid/', { | |
315 | 'openid': u'http://add.myopenid.com'}) | |
316 | res.follow() | |
317 | ||
318 | # Correct place? | |
319 | assert urlparse.urlsplit(res.location)[2] == '/edit/account/' | |
320 | assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT | |
321 | ||
322 | # OpenID Added? | |
44082b12 RE |
323 | new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( |
324 | openid_url=u'http://add.myopenid.com').first() | |
5adb906a RE |
325 | assert new_openid |
326 | ||
327 | _test_add() | |
328 | ||
329 | # Test deleting openid from account | |
330 | # Need to clear_test_template_context before calling _setup | |
331 | template.clear_test_template_context() | |
332 | self._setup(openid_plugin_app, delete=True) | |
333 | ||
334 | # Need to add OpenID back to user because it was deleted during | |
335 | # patch | |
336 | openid = OpenIDUserURL() | |
337 | openid.openid_url = 'http://add.myopenid.com' | |
338 | openid.user_id = test_user.id | |
339 | openid.save() | |
340 | ||
341 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
342 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
343 | def _test_delete(self, test_user): | |
344 | # Delete openid from user | |
345 | # Create another user to test deleting OpenID that doesn't belong to them | |
346 | new_user = fixture_add_user(username='newman') | |
347 | openid = OpenIDUserURL() | |
348 | openid.openid_url = 'http://realfake.myopenid.com/' | |
349 | openid.user_id = new_user.id | |
350 | openid.save() | |
351 | ||
352 | # Try and delete OpenID url that isn't the users | |
353 | template.clear_test_template_context() | |
354 | res = openid_plugin_app.post( | |
355 | '/edit/openid/delete/', { | |
356 | 'openid': 'http://realfake.myopenid.com/'}) | |
357 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/delete.html'] | |
358 | form = context['form'] | |
359 | assert form.openid.errors == [u'That OpenID is not registered to this account.'] | |
360 | ||
361 | # Delete OpenID | |
362 | # Kind of weird to POST to delete/finish | |
363 | template.clear_test_template_context() | |
364 | res = openid_plugin_app.post( | |
365 | '/edit/openid/delete/finish/', { | |
366 | 'openid': u'http://add.myopenid.com'}) | |
367 | res.follow() | |
368 | ||
369 | # Correct place? | |
370 | assert urlparse.urlsplit(res.location)[2] == '/edit/account/' | |
371 | assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT | |
372 | ||
373 | # OpenID deleted? | |
44082b12 RE |
374 | new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( |
375 | openid_url=u'http://add.myopenid.com').first() | |
5adb906a RE |
376 | assert not new_openid |
377 | ||
378 | _test_delete(self, test_user) |