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 | |
d88fcb03 | 31 | from mediagoblin.db.models import User, LocalUser |
5adb906a RE |
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 | |
d88fcb03 JT |
195 | test_user = mg_globals.database.User.query.filter( |
196 | LocalUser.username==u'chris' | |
197 | ).first() | |
5adb906a RE |
198 | Session.expunge(test_user) |
199 | ||
200 | # Log back in | |
201 | # Could not get it to work by 'POST'ing to /auth/openid/login/ | |
202 | template.clear_test_template_context() | |
203 | res = openid_plugin_app.post( | |
204 | '/auth/openid/login/finish/', { | |
205 | 'openid': u'http://real.myopenid.com'}) | |
206 | res.follow() | |
207 | ||
208 | assert urlparse.urlsplit(res.location)[2] == '/' | |
209 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT | |
210 | ||
211 | # Make sure user is in the session | |
212 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] | |
213 | session = context['request'].session | |
e49b7e02 | 214 | assert session['user_id'] == six.text_type(test_user.id) |
5adb906a RE |
215 | |
216 | _test_new_user() | |
217 | ||
218 | # Test register with empty form | |
219 | template.clear_test_template_context() | |
220 | openid_plugin_app.post( | |
221 | '/auth/openid/register/', {}) | |
222 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] | |
223 | register_form = context['register_form'] | |
224 | ||
225 | assert register_form.openid.errors == [u'This field is required.'] | |
226 | assert register_form.email.errors == [u'This field is required.'] | |
227 | assert register_form.username.errors == [u'This field is required.'] | |
228 | ||
229 | # Try to register with existing username and email | |
230 | template.clear_test_template_context() | |
231 | openid_plugin_app.post( | |
232 | '/auth/openid/register/', { | |
233 | 'openid': 'http://real.myopenid.com', | |
234 | 'email': 'chris@example.com', | |
235 | 'username': 'chris'}) | |
236 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] | |
237 | register_form = context['register_form'] | |
238 | ||
239 | assert register_form.username.errors == [u'Sorry, a user with that name already exists.'] | |
240 | assert register_form.email.errors == [u'Sorry, a user with that email address already exists.'] | |
241 | assert register_form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] | |
242 | ||
243 | def test_add_delete(self, openid_plugin_app): | |
244 | """Test adding and deleting openids""" | |
245 | # Add user | |
6483b370 | 246 | test_user = fixture_add_user(password='', privileges=[u'active']) |
5adb906a RE |
247 | openid = OpenIDUserURL() |
248 | openid.openid_url = 'http://real.myopenid.com' | |
249 | openid.user_id = test_user.id | |
250 | openid.save() | |
251 | ||
252 | # Log user in | |
253 | template.clear_test_template_context() | |
254 | self._setup(openid_plugin_app) | |
255 | ||
256 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
257 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
258 | def _login_user(): | |
259 | openid_plugin_app.post( | |
260 | '/auth/openid/login/finish/', { | |
261 | 'openid': u'http://real.myopenid.com'}) | |
262 | ||
263 | _login_user() | |
264 | ||
265 | # Try and delete only OpenID url | |
266 | template.clear_test_template_context() | |
267 | res = openid_plugin_app.post( | |
268 | '/edit/openid/delete/', { | |
269 | 'openid': 'http://real.myopenid.com'}) | |
270 | assert 'mediagoblin/plugins/openid/delete.html' in template.TEMPLATE_TEST_CONTEXT | |
271 | ||
272 | # Add OpenID to user | |
273 | # Empty form | |
274 | template.clear_test_template_context() | |
275 | res = openid_plugin_app.post( | |
276 | '/edit/openid/', {}) | |
277 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
278 | form = context['form'] | |
279 | assert form.openid.errors == [u'This field is required.'] | |
280 | ||
281 | # Try with a bad url | |
282 | template.clear_test_template_context() | |
283 | openid_plugin_app.post( | |
284 | '/edit/openid/', { | |
285 | 'openid': u'not_a_url.com'}) | |
286 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
287 | form = context['form'] | |
288 | assert form.openid.errors == [u'Please enter a valid url.'] | |
289 | ||
290 | # Try with a url that's already registered | |
291 | template.clear_test_template_context() | |
292 | openid_plugin_app.post( | |
293 | '/edit/openid/', { | |
294 | 'openid': 'http://real.myopenid.com'}) | |
295 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/add.html'] | |
296 | form = context['form'] | |
297 | assert form.openid.errors == [u'Sorry, an account is already registered to that OpenID.'] | |
298 | ||
299 | # Test adding openid to account | |
300 | # Need to clear_test_template_context before calling _setup | |
301 | template.clear_test_template_context() | |
302 | self._setup(openid_plugin_app, edit=True) | |
303 | ||
304 | # Need to remove openid_url from db because it was added at setup | |
305 | openid = OpenIDUserURL.query.filter_by( | |
306 | openid_url=u'http://add.myopenid.com') | |
307 | openid.delete() | |
308 | ||
309 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
310 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
311 | def _test_add(): | |
312 | # Successful add | |
313 | template.clear_test_template_context() | |
314 | res = openid_plugin_app.post( | |
315 | '/edit/openid/', { | |
316 | 'openid': u'http://add.myopenid.com'}) | |
317 | res.follow() | |
318 | ||
319 | # Correct place? | |
320 | assert urlparse.urlsplit(res.location)[2] == '/edit/account/' | |
321 | assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT | |
322 | ||
323 | # OpenID Added? | |
44082b12 RE |
324 | new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( |
325 | openid_url=u'http://add.myopenid.com').first() | |
5adb906a RE |
326 | assert new_openid |
327 | ||
328 | _test_add() | |
329 | ||
330 | # Test deleting openid from account | |
331 | # Need to clear_test_template_context before calling _setup | |
332 | template.clear_test_template_context() | |
333 | self._setup(openid_plugin_app, delete=True) | |
334 | ||
335 | # Need to add OpenID back to user because it was deleted during | |
336 | # patch | |
337 | openid = OpenIDUserURL() | |
338 | openid.openid_url = 'http://add.myopenid.com' | |
339 | openid.user_id = test_user.id | |
340 | openid.save() | |
341 | ||
342 | @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self._finish_verification) | |
343 | @mock.patch('mediagoblin.plugins.openid.views._start_verification', self._start_verification) | |
344 | def _test_delete(self, test_user): | |
345 | # Delete openid from user | |
346 | # Create another user to test deleting OpenID that doesn't belong to them | |
347 | new_user = fixture_add_user(username='newman') | |
348 | openid = OpenIDUserURL() | |
349 | openid.openid_url = 'http://realfake.myopenid.com/' | |
350 | openid.user_id = new_user.id | |
351 | openid.save() | |
352 | ||
353 | # Try and delete OpenID url that isn't the users | |
354 | template.clear_test_template_context() | |
355 | res = openid_plugin_app.post( | |
356 | '/edit/openid/delete/', { | |
357 | 'openid': 'http://realfake.myopenid.com/'}) | |
358 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/plugins/openid/delete.html'] | |
359 | form = context['form'] | |
360 | assert form.openid.errors == [u'That OpenID is not registered to this account.'] | |
361 | ||
362 | # Delete OpenID | |
363 | # Kind of weird to POST to delete/finish | |
364 | template.clear_test_template_context() | |
365 | res = openid_plugin_app.post( | |
366 | '/edit/openid/delete/finish/', { | |
367 | 'openid': u'http://add.myopenid.com'}) | |
368 | res.follow() | |
369 | ||
370 | # Correct place? | |
371 | assert urlparse.urlsplit(res.location)[2] == '/edit/account/' | |
372 | assert 'mediagoblin/edit/edit_account.html' in template.TEMPLATE_TEST_CONTEXT | |
373 | ||
374 | # OpenID deleted? | |
44082b12 RE |
375 | new_openid = mg_globals.database.OpenIDUserURL.query.filter_by( |
376 | openid_url=u'http://add.myopenid.com').first() | |
5adb906a RE |
377 | assert not new_openid |
378 | ||
379 | _test_delete(self, test_user) |