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