2 # GNU MediaGoblin -- federated, autonomous media hosting
3 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
15 # You should have received a copy of the GNU Affero General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import six
.moves
.urllib
.parse
as urlparse
25 from mediagoblin
import mg_globals
26 from mediagoblin
.db
.models
import User
, LocalUser
27 from mediagoblin
.tests
.tools
import get_app
, fixture_add_user
28 from mediagoblin
.tools
import template
, mail
29 from mediagoblin
.auth
import tools
as auth_tools
32 def test_register_views(test_app
):
34 Massive test function that all our registration-related views all work.
36 # Test doing a simple GET on the page
37 # -----------------------------------
39 test_app
.get('/auth/register/')
40 # Make sure it rendered with the appropriate template
41 assert 'mediagoblin/auth/register.html' in template
.TEMPLATE_TEST_CONTEXT
43 # Try to register without providing anything, should error
44 # --------------------------------------------------------
46 template
.clear_test_template_context()
48 '/auth/register/', {})
49 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
50 form
= context
['register_form']
51 assert form
.username
.errors
== [u
'This field is required.']
52 assert form
.password
.errors
== [u
'This field is required.']
53 assert form
.email
.errors
== [u
'This field is required.']
55 # Try to register with fields that are known to be invalid
56 # --------------------------------------------------------
59 template
.clear_test_template_context()
65 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
66 form
= context
['register_form']
68 assert form
.username
.errors
== [u
'Field must be between 3 and 30 characters long.']
69 assert form
.password
.errors
== [u
'Field must be between 5 and 1024 characters long.']
72 template
.clear_test_template_context()
76 'email': 'lollerskates'})
77 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
78 form
= context
['register_form']
80 assert form
.username
.errors
== [u
'This field does not take email addresses.']
81 assert form
.email
.errors
== [u
'This field requires an email address.']
83 ## At this point there should be no users in the database ;)
84 assert User
.query
.count() == 0
88 template
.clear_test_template_context()
89 response
= test_app
.post(
91 'username': u
'angrygirl',
92 'password': 'iamsoangry',
93 'email': 'angrygrrl@example.org'})
96 ## Did we redirect to the proper page? Use the right template?
97 assert urlparse
.urlsplit(response
.location
)[2] == '/u/angrygirl/'
98 assert 'mediagoblin/user_pages/user_nonactive.html' in template
.TEMPLATE_TEST_CONTEXT
100 ## Make sure user is in place
101 new_user
= mg_globals
.database
.LocalUser
.query
.filter(
102 LocalUser
.username
==u
'angrygirl'
106 ## Make sure that the proper privileges are granted on registration
108 assert new_user
.has_privilege(u
'commenter')
109 assert new_user
.has_privilege(u
'uploader')
110 assert new_user
.has_privilege(u
'reporter')
111 assert not new_user
.has_privilege(u
'active')
112 ## Make sure user is logged in
113 request
= template
.TEMPLATE_TEST_CONTEXT
[
114 'mediagoblin/user_pages/user_nonactive.html']['request']
115 assert request
.session
['user_id'] == six
.text_type(new_user
.id)
117 ## Make sure we get email confirmation, and try verifying
118 assert len(mail
.EMAIL_TEST_INBOX
) == 1
119 message
= mail
.EMAIL_TEST_INBOX
.pop()
120 assert message
['To'] == 'angrygrrl@example.org'
121 email_context
= template
.TEMPLATE_TEST_CONTEXT
[
122 'mediagoblin/auth/verification_email.txt']
123 assert email_context
['verification_url'].encode('ascii') in message
.get_payload(decode
=True)
125 path
= urlparse
.urlsplit(email_context
['verification_url'])[2]
126 get_params
= urlparse
.urlsplit(email_context
['verification_url'])[3]
127 assert path
== u
'/auth/verify_email/'
128 parsed_get_params
= urlparse
.parse_qs(get_params
)
130 ## Try verifying with bs verification key, shouldn't work
131 template
.clear_test_template_context()
132 response
= test_app
.get(
133 "/auth/verify_email/?token=total_bs")
137 assert urlparse
.urlsplit(response
.location
)[2] == '/'
139 # assert context['verification_successful'] == True
140 # TODO: Would be good to test messages here when we can do so...
141 new_user
= mg_globals
.database
.LocalUser
.query
.filter(
142 LocalUser
.username
==u
'angrygirl'
146 ## Verify the email activation works
147 template
.clear_test_template_context()
148 response
= test_app
.get("%s?%s" % (path
, get_params
))
150 context
= template
.TEMPLATE_TEST_CONTEXT
[
151 'mediagoblin/user_pages/user.html']
152 # assert context['verification_successful'] == True
153 # TODO: Would be good to test messages here when we can do so...
154 new_user
= mg_globals
.database
.LocalUser
.query
.filter(
155 LocalUser
.username
==u
'angrygirl'
161 ## We shouldn't be able to register with that user twice
162 template
.clear_test_template_context()
163 response
= test_app
.post(
165 'username': u
'angrygirl',
166 'password': 'iamsoangry2',
167 'email': 'angrygrrl2@example.org'})
169 context
= template
.TEMPLATE_TEST_CONTEXT
[
170 'mediagoblin/auth/register.html']
171 form
= context
['register_form']
172 assert form
.username
.errors
== [
173 u
'Sorry, a user with that name already exists.']
175 ## TODO: Also check for double instances of an email address?
177 ### Oops, forgot the password
178 # -------------------
179 template
.clear_test_template_context()
180 response
= test_app
.post(
181 '/auth/forgot_password/',
182 {'username': u
'angrygirl'})
185 ## Did we redirect to the proper page? Use the right template?
186 assert urlparse
.urlsplit(response
.location
)[2] == '/auth/login/'
187 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
189 ## Make sure link to change password is sent by email
190 assert len(mail
.EMAIL_TEST_INBOX
) == 1
191 message
= mail
.EMAIL_TEST_INBOX
.pop()
192 assert message
['To'] == 'angrygrrl@example.org'
193 email_context
= template
.TEMPLATE_TEST_CONTEXT
[
194 'mediagoblin/plugins/basic_auth/fp_verification_email.txt']
195 #TODO - change the name of verification_url to something forgot-password-ish
196 assert email_context
['verification_url'].encode('ascii') in message
.get_payload(decode
=True)
198 path
= urlparse
.urlsplit(email_context
['verification_url'])[2]
199 get_params
= urlparse
.urlsplit(email_context
['verification_url'])[3]
200 parsed_get_params
= urlparse
.parse_qs(get_params
)
201 assert path
== u
'/auth/forgot_password/verify/'
203 ## Try using a bs password-changing verification key, shouldn't work
204 template
.clear_test_template_context()
205 response
= test_app
.get(
206 "/auth/forgot_password/verify/?token=total_bs")
210 assert urlparse
.urlsplit(response
.location
)[2] == '/'
212 ## Verify step 1 of password-change works -- can see form to change password
213 template
.clear_test_template_context()
214 response
= test_app
.get("%s?%s" % (path
, get_params
))
215 assert 'mediagoblin/plugins/basic_auth/change_fp.html' in \
216 template
.TEMPLATE_TEST_CONTEXT
218 ## Verify step 2.1 of password-change works -- report success to user
219 template
.clear_test_template_context()
220 response
= test_app
.post(
221 '/auth/forgot_password/verify/', {
222 'password': 'iamveryveryangry',
223 'token': parsed_get_params
['token']})
225 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
227 ## Verify step 2.2 of password-change works -- login w/ new password success
228 template
.clear_test_template_context()
229 response
= test_app
.post(
231 'username': u
'angrygirl',
232 'password': 'iamveryveryangry'})
234 # User should be redirected
236 assert urlparse
.urlsplit(response
.location
)[2] == '/'
237 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
239 def test_authentication_views(test_app
):
241 Test logging in and logging out
244 test_user
= fixture_add_user()
249 test_app
.get('/auth/login/')
250 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
252 # Failed login - blank form
253 # -------------------------
254 template
.clear_test_template_context()
255 response
= test_app
.post('/auth/login/')
256 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
257 form
= context
['login_form']
258 assert form
.username
.errors
== [u
'This field is required.']
260 # Failed login - blank user
261 # -------------------------
262 template
.clear_test_template_context()
263 response
= test_app
.post(
265 'password': u
'toast'})
266 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
267 form
= context
['login_form']
268 assert form
.username
.errors
== [u
'This field is required.']
270 # Failed login - blank password
271 # -----------------------------
272 template
.clear_test_template_context()
273 response
= test_app
.post(
275 'username': u
'chris'})
276 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
278 # Failed login - bad user
279 # -----------------------
280 template
.clear_test_template_context()
281 response
= test_app
.post(
283 'username': u
'steve',
284 'password': 'toast'})
285 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
286 assert context
['login_failed']
288 # Failed login - bad password
289 # ---------------------------
290 template
.clear_test_template_context()
291 response
= test_app
.post(
293 'username': u
'chris',
294 'password': 'jam_and_ham'})
295 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
296 assert context
['login_failed']
300 template
.clear_test_template_context()
301 response
= test_app
.post(
303 'username': u
'chris',
304 'password': 'toast'})
306 # User should be redirected
308 assert urlparse
.urlsplit(response
.location
)[2] == '/'
309 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
311 # Make sure user is in the session
312 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/root.html']
313 session
= context
['request'].session
314 assert session
['user_id'] == six
.text_type(test_user
.id)
318 template
.clear_test_template_context()
319 response
= test_app
.get('/auth/logout/')
321 # Should be redirected to index page
323 assert urlparse
.urlsplit(response
.location
)[2] == '/'
324 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
326 # Make sure the user is not in the session
327 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/root.html']
328 session
= context
['request'].session
329 assert 'user_id' not in session
331 # User is redirected to custom URL if POST['next'] is set
332 # -------------------------------------------------------
333 template
.clear_test_template_context()
334 response
= test_app
.post(
336 'username': u
'chris',
338 'next' : '/u/chris/'})
339 assert urlparse
.urlsplit(response
.location
)[2] == '/u/chris/'
341 ## Verify that username is lowercased on login attempt
342 template
.clear_test_template_context()
343 response
= test_app
.post(
345 'username': u
'ANDREW',
346 'password': 'fuselage'})
347 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
348 form
= context
['login_form']
350 # Username should no longer be uppercased; it should be lowercased
351 assert not form
.username
.data
== u
'ANDREW'
352 assert form
.username
.data
== u
'andrew'
355 def authentication_disabled_app(request
):
358 mgoblin_config
=pkg_resources
.resource_filename(
359 'mediagoblin.tests.auth_configs',
360 'authentication_disabled_appconfig.ini'))
363 def test_authentication_disabled_app(authentication_disabled_app
):
364 # app.auth should = false
366 assert mg_globals
.app
.auth
is False
368 # Try to visit register page
369 template
.clear_test_template_context()
370 response
= authentication_disabled_app
.get('/auth/register/')
374 assert urlparse
.urlsplit(response
.location
)[2] == '/'
375 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
377 # Try to vist login page
378 template
.clear_test_template_context()
379 response
= authentication_disabled_app
.get('/auth/login/')
383 assert urlparse
.urlsplit(response
.location
)[2] == '/'
384 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
386 ## Test check_login_simple should return None
387 assert auth_tools
.check_login_simple('test', 'simple') is None
389 # Try to visit the forgot password page
390 template
.clear_test_template_context()
391 response
= authentication_disabled_app
.get('/auth/register/')
395 assert urlparse
.urlsplit(response
.location
)[2] == '/'
396 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT