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
32 # App with plugin enabled
34 def openid_plugin_app(request
):
37 mgoblin_config
=pkg_resources
.resource_filename(
38 'mediagoblin.tests.auth_configs',
39 'openid_appconfig.ini'))
42 class TestOpenIDPlugin(object):
43 def _setup(self
, openid_plugin_app
, value
=True, edit
=False, delete
=False):
45 response
= openid_consumer
.SuccessResponse(mock
.Mock(), mock
.Mock())
47 response
.identity_url
= u
'http://add.myopenid.com'
49 response
.identity_url
= u
'http://real.myopenid.com'
50 self
._finish
_verification
= mock
.Mock(return_value
=response
)
52 self
._finish
_verification
= mock
.Mock(return_value
=False)
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
):
59 self
._start
_verification
= mock
.Mock(return_value
=openid_plugin_app
.post(
60 '/edit/openid/finish/'))
62 self
._start
_verification
= mock
.Mock(return_value
=openid_plugin_app
.post(
63 '/edit/openid/delete/finish/'))
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
)
69 def test_bad_login(self
, openid_plugin_app
):
70 """ Test that attempts to login with invalid paramaters"""
72 # Test GET request for auth/register page
73 res
= openid_plugin_app
.get('/auth/register/').follow()
75 # Make sure it redirected to the correct place
76 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
78 # Test GET request for auth/login page
79 res
= openid_plugin_app
.get('/auth/login/')
83 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
85 # Test GET request for auth/openid/register page
86 res
= openid_plugin_app
.get('/auth/openid/register/')
90 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
92 # Test GET request for auth/openid/login/finish page
93 res
= openid_plugin_app
.get('/auth/openid/login/finish/')
97 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
99 # Test GET request for auth/openid/login page
100 res
= openid_plugin_app
.get('/auth/openid/login/')
103 assert 'mediagoblin/plugins/openid/login.html' in template
.TEMPLATE_TEST_CONTEXT
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.']
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.']
122 # Should be no users in the db
123 assert User
.query
.count() == 0
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']
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)
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/'})
149 assert urlparse
.urlsplit(res
.location
)[2] == '/auth/openid/login/'
150 assert 'mediagoblin/plugins/openid/login.html' in template
.TEMPLATE_TEST_CONTEXT
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
)
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'})
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']
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'})
179 assert urlparse
.urlsplit(res
.location
)[2] == '/u/chris/'
180 assert 'mediagoblin/user_pages/user.html' in template
.TEMPLATE_TEST_CONTEXT
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
187 openid_plugin_app
.get('/auth/logout')
189 # Get user and detach from session
190 test_user
= mg_globals
.database
.User
.query
.filter_by(
191 username
=u
'chris').first()
192 Session
.expunge(test_user
)
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'})
202 assert urlparse
.urlsplit(res
.location
)[2] == '/'
203 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
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)
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']
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.']
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']
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.']
237 def test_add_delete(self
, openid_plugin_app
):
238 """Test adding and deleting openids"""
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
247 template
.clear_test_template_context()
248 self
._setup
(openid_plugin_app
)
250 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
251 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
253 openid_plugin_app
.post(
254 '/auth/openid/login/finish/', {
255 'openid': u
'http://real.myopenid.com'})
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
268 template
.clear_test_template_context()
269 res
= openid_plugin_app
.post(
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.']
276 template
.clear_test_template_context()
277 openid_plugin_app
.post(
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.']
284 # Try with a url that's already registered
285 template
.clear_test_template_context()
286 openid_plugin_app
.post(
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.']
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)
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')
303 @mock.patch('mediagoblin.plugins.openid.views._finish_verification', self
._finish
_verification
)
304 @mock.patch('mediagoblin.plugins.openid.views._start_verification', self
._start
_verification
)
307 template
.clear_test_template_context()
308 res
= openid_plugin_app
.post(
310 'openid': u
'http://add.myopenid.com'})
314 assert urlparse
.urlsplit(res
.location
)[2] == '/edit/account/'
315 assert 'mediagoblin/edit/edit_account.html' in template
.TEMPLATE_TEST_CONTEXT
318 new_openid
= mg_globals
.database
.OpenIDUserURL
.query
.filter_by(
319 openid_url
=u
'http://add.myopenid.com').first()
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)
329 # Need to add OpenID back to user because it was deleted during
331 openid
= OpenIDUserURL()
332 openid
.openid_url
= 'http://add.myopenid.com'
333 openid
.user_id
= test_user
.id
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
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.']
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'})
365 assert urlparse
.urlsplit(res
.location
)[2] == '/edit/account/'
366 assert 'mediagoblin/edit/edit_account.html' in template
.TEMPLATE_TEST_CONTEXT
369 new_openid
= mg_globals
.database
.OpenIDUserURL
.query
.filter_by(
370 openid_url
=u
'http://add.myopenid.com').first()
371 assert not new_openid
373 _test_delete(self
, test_user
)