1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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.
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.
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/>.
22 openid_consumer
= pytest
.importorskip(
23 "openid.consumer.consumer")
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
33 # App with plugin enabled
35 def openid_plugin_app(request
):
38 mgoblin_config
=pkg_resources
.resource_filename(
39 'mediagoblin.tests.auth_configs',
40 'openid_appconfig.ini'))
43 class TestOpenIDPlugin(object):
44 def _setup(self
, openid_plugin_app
, value
=True, edit
=False, delete
=False):
46 response
= openid_consumer
.SuccessResponse(mock
.Mock(), mock
.Mock())
48 response
.identity_url
= u
'http://add.myopenid.com'
50 response
.identity_url
= u
'http://real.myopenid.com'
51 self
._finish
_verification
= mock
.Mock(return_value
=response
)
53 self
._finish
_verification
= mock
.Mock(return_value
=False)
55 @mock.patch('mediagoblin.plugins.openid.views._response_email', mock
.Mock(return_value
=None))
56 @mock.patch('mediagoblin.plugins.openid.views._response_nickname', mock
.Mock(return_value
=None))
57 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
58 def _setup_start(self
, openid_plugin_app
, edit
, delete
):
60 self
._start
_verification
= mock
.Mock(return_value
=openid_plugin_app
.post(
61 '/edit/openid/finish/'))
63 self
._start
_verification
= mock
.Mock(return_value
=openid_plugin_app
.post(
64 '/edit/openid/delete/finish/'))
66 self
._start
_verification
= mock
.Mock(return_value
=openid_plugin_app
.post(
67 '/auth/openid/login/finish/'))
68 _setup_start(self
, openid_plugin_app
, edit
, delete
)
70 def test_bad_login(self
, openid_plugin_app
):
71 """ Test that attempts to login with invalid paramaters"""
73 # Test GET request for auth/register page
74 res
= openid_plugin_app
.get('/auth/register/').follow()
76 # Make sure it redirected to the correct place
77 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
79 # Test GET request for auth/login page
80 res
= openid_plugin_app
.get('/auth/login/')
84 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
86 # Test GET request for auth/openid/register page
87 res
= openid_plugin_app
.get('/auth/openid/register/')
91 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
93 # Test GET request for auth/openid/login/finish page
94 res
= openid_plugin_app
.get('/auth/openid/login/finish/')
98 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
100 # Test GET request for auth/openid/login page
101 res
= openid_plugin_app
.get('/auth/openid/login/')
104 assert 'mediagoblin/plugins/openid/login.html' in template
.TEMPLATE_TEST_CONTEXT
106 # Try to login with an empty form
107 template
.clear_test_template_context()
108 openid_plugin_app
.post(
109 '/auth/openid/login/', {})
110 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/login.html']
111 form
= context
['login_form']
112 assert form
.openid
.errors
== [u
'This field is required.']
114 # Try to login with wrong form values
115 template
.clear_test_template_context()
116 openid_plugin_app
.post(
117 '/auth/openid/login/', {
118 'openid': 'not_a_url.com'})
119 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/login.html']
120 form
= context
['login_form']
121 assert form
.openid
.errors
== [u
'Please enter a valid url.']
123 # Should be no users in the db
124 assert User
.query
.count() == 0
127 template
.clear_test_template_context()
128 openid_plugin_app
.post(
129 '/auth/openid/login/', {
130 'openid': 'http://phoney.myopenid.com/'})
131 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/login.html']
132 form
= context
['login_form']
133 assert form
.openid
.errors
== [u
'Sorry, the OpenID server could not be found']
135 def test_login(self
, openid_plugin_app
):
136 """Tests that test login and registion with openid"""
137 # Test finish_login redirects correctly when response = False
138 self
._setup
(openid_plugin_app
, False)
140 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
141 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
142 def _test_non_response():
143 template
.clear_test_template_context()
144 res
= openid_plugin_app
.post(
145 '/auth/openid/login/', {
146 'openid': 'http://phoney.myopenid.com/'})
150 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
151 assert 'mediagoblin/plugins/openid/login.html' in template
.TEMPLATE_TEST_CONTEXT
154 # Test login with new openid
155 # Need to clear_test_template_context before calling _setup
156 template
.clear_test_template_context()
157 self
._setup
(openid_plugin_app
)
159 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
160 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
161 def _test_new_user():
162 openid_plugin_app
.post(
163 '/auth/openid/login/', {
164 'openid': u
'http://real.myopenid.com'})
167 assert 'mediagoblin/auth/register.html' in template
.TEMPLATE_TEST_CONTEXT
168 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
169 register_form
= context
['register_form']
172 res
= openid_plugin_app
.post(
173 '/auth/openid/register/', {
174 'openid': register_form
.openid
.data
,
175 'username': u
'chris',
176 'email': u
'chris@example.com'})
180 assert urlparse
.urlsplit(res
.location
)[2] == '/u/chris/'
181 assert 'mediagoblin/user_pages/user_nonactive.html' in template
.TEMPLATE_TEST_CONTEXT
183 # No need to test if user is in logged in and verification email
184 # awaits, since openid uses the register_user function which is
185 # tested in test_auth
188 openid_plugin_app
.get('/auth/logout')
190 # Get user and detach from session
191 test_user
= mg_globals
.database
.User
.query
.filter_by(
192 username
=u
'chris').first()
193 Session
.expunge(test_user
)
196 # Could not get it to work by 'POST'ing to /auth/openid/login/
197 template
.clear_test_template_context()
198 res
= openid_plugin_app
.post(
199 '/auth/openid/login/finish/', {
200 'openid': u
'http://real.myopenid.com'})
203 assert urlparse
.urlsplit(res
.location
)[2] == '/'
204 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
206 # Make sure user is in the session
207 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/root.html']
208 session
= context
['request'].session
209 assert session
['user_id'] == unicode(test_user
.id)
213 # Test register with empty form
214 template
.clear_test_template_context()
215 openid_plugin_app
.post(
216 '/auth/openid/register/', {})
217 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
218 register_form
= context
['register_form']
220 assert register_form
.openid
.errors
== [u
'This field is required.']
221 assert register_form
.email
.errors
== [u
'This field is required.']
222 assert register_form
.username
.errors
== [u
'This field is required.']
224 # Try to register with existing username and email
225 template
.clear_test_template_context()
226 openid_plugin_app
.post(
227 '/auth/openid/register/', {
228 'openid': 'http://real.myopenid.com',
229 'email': 'chris@example.com',
230 'username': 'chris'})
231 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
232 register_form
= context
['register_form']
234 assert register_form
.username
.errors
== [u
'Sorry, a user with that name already exists.']
235 assert register_form
.email
.errors
== [u
'Sorry, a user with that email address already exists.']
236 assert register_form
.openid
.errors
== [u
'Sorry, an account is already registered to that OpenID.']
238 def test_add_delete(self
, openid_plugin_app
):
239 """Test adding and deleting openids"""
241 test_user
= fixture_add_user(password
='', privileges
=[u
'active'])
242 openid
= OpenIDUserURL()
243 openid
.openid_url
= 'http://real.myopenid.com'
244 openid
.user_id
= test_user
.id
248 template
.clear_test_template_context()
249 self
._setup
(openid_plugin_app
)
251 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
252 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
254 openid_plugin_app
.post(
255 '/auth/openid/login/finish/', {
256 'openid': u
'http://real.myopenid.com'})
260 # Try and delete only OpenID url
261 template
.clear_test_template_context()
262 res
= openid_plugin_app
.post(
263 '/edit/openid/delete/', {
264 'openid': 'http://real.myopenid.com'})
265 assert 'mediagoblin/plugins/openid/delete.html' in template
.TEMPLATE_TEST_CONTEXT
269 template
.clear_test_template_context()
270 res
= openid_plugin_app
.post(
272 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/add.html']
273 form
= context
['form']
274 assert form
.openid
.errors
== [u
'This field is required.']
277 template
.clear_test_template_context()
278 openid_plugin_app
.post(
280 'openid': u
'not_a_url.com'})
281 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/add.html']
282 form
= context
['form']
283 assert form
.openid
.errors
== [u
'Please enter a valid url.']
285 # Try with a url that's already registered
286 template
.clear_test_template_context()
287 openid_plugin_app
.post(
289 'openid': 'http://real.myopenid.com'})
290 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/add.html']
291 form
= context
['form']
292 assert form
.openid
.errors
== [u
'Sorry, an account is already registered to that OpenID.']
294 # Test adding openid to account
295 # Need to clear_test_template_context before calling _setup
296 template
.clear_test_template_context()
297 self
._setup
(openid_plugin_app
, edit
=True)
299 # Need to remove openid_url from db because it was added at setup
300 openid
= OpenIDUserURL
.query
.filter_by(
301 openid_url
=u
'http://add.myopenid.com')
304 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
305 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
308 template
.clear_test_template_context()
309 res
= openid_plugin_app
.post(
311 'openid': u
'http://add.myopenid.com'})
315 assert urlparse
.urlsplit(res
.location
)[2] == '/edit/account/'
316 assert 'mediagoblin/edit/edit_account.html' in template
.TEMPLATE_TEST_CONTEXT
319 new_openid
= mg_globals
.database
.OpenIDUserURL
.query
.filter_by(
320 openid_url
=u
'http://add.myopenid.com').first()
325 # Test deleting openid from account
326 # Need to clear_test_template_context before calling _setup
327 template
.clear_test_template_context()
328 self
._setup
(openid_plugin_app
, delete
=True)
330 # Need to add OpenID back to user because it was deleted during
332 openid
= OpenIDUserURL()
333 openid
.openid_url
= 'http://add.myopenid.com'
334 openid
.user_id
= test_user
.id
337 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
338 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
339 def _test_delete(self
, test_user
):
340 # Delete openid from user
341 # Create another user to test deleting OpenID that doesn't belong to them
342 new_user
= fixture_add_user(username
='newman')
343 openid
= OpenIDUserURL()
344 openid
.openid_url
= 'http://realfake.myopenid.com/'
345 openid
.user_id
= new_user
.id
348 # Try and delete OpenID url that isn't the users
349 template
.clear_test_template_context()
350 res
= openid_plugin_app
.post(
351 '/edit/openid/delete/', {
352 'openid': 'http://realfake.myopenid.com/'})
353 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/plugins/openid/delete.html']
354 form
= context
['form']
355 assert form
.openid
.errors
== [u
'That OpenID is not registered to this account.']
358 # Kind of weird to POST to delete/finish
359 template
.clear_test_template_context()
360 res
= openid_plugin_app
.post(
361 '/edit/openid/delete/finish/', {
362 'openid': u
'http://add.myopenid.com'})
366 assert urlparse
.urlsplit(res
.location
)[2] == '/edit/account/'
367 assert 'mediagoblin/edit/edit_account.html' in template
.TEMPLATE_TEST_CONTEXT
370 new_openid
= mg_globals
.database
.OpenIDUserURL
.query
.filter_by(
371 openid_url
=u
'http://add.myopenid.com').first()
372 assert not new_openid
374 _test_delete(self
, test_user
)