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/>.
21 from mediagoblin
import mg_globals
22 from mediagoblin
.db
.models
import User
23 from mediagoblin
.tests
.tools
import get_app
, fixture_add_user
24 from mediagoblin
.tools
import template
, mail
25 from mediagoblin
.auth
import tools
as auth_tools
28 def test_register_views(test_app
):
30 Massive test function that all our registration-related views all work.
32 # Test doing a simple GET on the page
33 # -----------------------------------
35 test_app
.get('/auth/register/')
36 # Make sure it rendered with the appropriate template
37 assert 'mediagoblin/auth/register.html' in template
.TEMPLATE_TEST_CONTEXT
39 # Try to register without providing anything, should error
40 # --------------------------------------------------------
42 template
.clear_test_template_context()
44 '/auth/register/', {})
45 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
46 form
= context
['register_form']
47 assert form
.username
.errors
== [u
'This field is required.']
48 assert form
.password
.errors
== [u
'This field is required.']
49 assert form
.email
.errors
== [u
'This field is required.']
51 # Try to register with fields that are known to be invalid
52 # --------------------------------------------------------
55 template
.clear_test_template_context()
61 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
62 form
= context
['register_form']
64 assert form
.username
.errors
== [u
'Field must be between 3 and 30 characters long.']
65 assert form
.password
.errors
== [u
'Field must be between 5 and 1024 characters long.']
68 template
.clear_test_template_context()
72 'email': 'lollerskates'})
73 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/register.html']
74 form
= context
['register_form']
76 assert form
.username
.errors
== [u
'This field does not take email addresses.']
77 assert form
.email
.errors
== [u
'This field requires an email address.']
79 ## At this point there should be no users in the database ;)
80 assert User
.query
.count() == 0
84 template
.clear_test_template_context()
85 response
= test_app
.post(
87 'username': u
'happygirl',
88 'password': 'iamsohappy',
89 'email': 'happygrrl@example.org'})
92 ## Did we redirect to the proper page? Use the right template?
93 assert urlparse
.urlsplit(response
.location
)[2] == '/u/happygirl/'
94 assert 'mediagoblin/user_pages/user_nonactive.html' in template
.TEMPLATE_TEST_CONTEXT
96 ## Make sure user is in place
97 new_user
= mg_globals
.database
.User
.query
.filter_by(
98 username
=u
'happygirl').first()
100 assert new_user
.status
== u
'needs_email_verification'
101 assert new_user
.email_verified
== False
103 ## Make sure user is logged in
104 request
= template
.TEMPLATE_TEST_CONTEXT
[
105 'mediagoblin/user_pages/user_nonactive.html']['request']
106 assert request
.session
['user_id'] == unicode(new_user
.id)
108 ## Make sure we get email confirmation, and try verifying
109 assert len(mail
.EMAIL_TEST_INBOX
) == 1
110 message
= mail
.EMAIL_TEST_INBOX
.pop()
111 assert message
['To'] == 'happygrrl@example.org'
112 email_context
= template
.TEMPLATE_TEST_CONTEXT
[
113 'mediagoblin/auth/verification_email.txt']
114 assert email_context
['verification_url'] in message
.get_payload(decode
=True)
116 path
= urlparse
.urlsplit(email_context
['verification_url'])[2]
117 get_params
= urlparse
.urlsplit(email_context
['verification_url'])[3]
118 assert path
== u
'/auth/verify_email/'
119 parsed_get_params
= urlparse
.parse_qs(get_params
)
121 ## Try verifying with bs verification key, shouldn't work
122 template
.clear_test_template_context()
123 response
= test_app
.get(
124 "/auth/verify_email/?token=total_bs")
128 assert urlparse
.urlsplit(response
.location
)[2] == '/'
130 # assert context['verification_successful'] == True
131 # TODO: Would be good to test messages here when we can do so...
132 new_user
= mg_globals
.database
.User
.query
.filter_by(
133 username
=u
'happygirl').first()
135 assert new_user
.status
== u
'needs_email_verification'
136 assert new_user
.email_verified
== False
138 ## Verify the email activation works
139 template
.clear_test_template_context()
140 response
= test_app
.get("%s?%s" % (path
, get_params
))
142 context
= template
.TEMPLATE_TEST_CONTEXT
[
143 'mediagoblin/user_pages/user.html']
144 # assert context['verification_successful'] == True
145 # TODO: Would be good to test messages here when we can do so...
146 new_user
= mg_globals
.database
.User
.query
.filter_by(
147 username
=u
'happygirl').first()
149 assert new_user
.status
== u
'active'
150 assert new_user
.email_verified
== True
154 ## We shouldn't be able to register with that user twice
155 template
.clear_test_template_context()
156 response
= test_app
.post(
158 'username': u
'happygirl',
159 'password': 'iamsohappy2',
160 'email': 'happygrrl2@example.org'})
162 context
= template
.TEMPLATE_TEST_CONTEXT
[
163 'mediagoblin/auth/register.html']
164 form
= context
['register_form']
165 assert form
.username
.errors
== [
166 u
'Sorry, a user with that name already exists.']
168 ## TODO: Also check for double instances of an email address?
170 ### Oops, forgot the password
171 # -------------------
172 template
.clear_test_template_context()
173 response
= test_app
.post(
174 '/auth/forgot_password/',
175 {'username': u
'happygirl'})
178 ## Did we redirect to the proper page? Use the right template?
179 assert urlparse
.urlsplit(response
.location
)[2] == '/auth/login/'
180 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
182 ## Make sure link to change password is sent by email
183 assert len(mail
.EMAIL_TEST_INBOX
) == 1
184 message
= mail
.EMAIL_TEST_INBOX
.pop()
185 assert message
['To'] == 'happygrrl@example.org'
186 email_context
= template
.TEMPLATE_TEST_CONTEXT
[
187 'mediagoblin/plugins/basic_auth/fp_verification_email.txt']
188 #TODO - change the name of verification_url to something forgot-password-ish
189 assert email_context
['verification_url'] in message
.get_payload(decode
=True)
191 path
= urlparse
.urlsplit(email_context
['verification_url'])[2]
192 get_params
= urlparse
.urlsplit(email_context
['verification_url'])[3]
193 parsed_get_params
= urlparse
.parse_qs(get_params
)
194 assert path
== u
'/auth/forgot_password/verify/'
196 ## Try using a bs password-changing verification key, shouldn't work
197 template
.clear_test_template_context()
198 response
= test_app
.get(
199 "/auth/forgot_password/verify/?token=total_bs")
203 assert urlparse
.urlsplit(response
.location
)[2] == '/'
205 ## Verify step 1 of password-change works -- can see form to change password
206 template
.clear_test_template_context()
207 response
= test_app
.get("%s?%s" % (path
, get_params
))
208 assert 'mediagoblin/plugins/basic_auth/change_fp.html' in \
209 template
.TEMPLATE_TEST_CONTEXT
211 ## Verify step 2.1 of password-change works -- report success to user
212 template
.clear_test_template_context()
213 response
= test_app
.post(
214 '/auth/forgot_password/verify/', {
215 'password': 'iamveryveryhappy',
216 'token': parsed_get_params
['token']})
218 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
220 ## Verify step 2.2 of password-change works -- login w/ new password success
221 template
.clear_test_template_context()
222 response
= test_app
.post(
224 'username': u
'happygirl',
225 'password': 'iamveryveryhappy'})
227 # User should be redirected
229 assert urlparse
.urlsplit(response
.location
)[2] == '/'
230 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
233 def test_authentication_views(test_app
):
235 Test logging in and logging out
238 test_user
= fixture_add_user(active_user
=False)
243 test_app
.get('/auth/login/')
244 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
246 # Failed login - blank form
247 # -------------------------
248 template
.clear_test_template_context()
249 response
= test_app
.post('/auth/login/')
250 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
251 form
= context
['login_form']
252 assert form
.username
.errors
== [u
'This field is required.']
254 # Failed login - blank user
255 # -------------------------
256 template
.clear_test_template_context()
257 response
= test_app
.post(
259 'password': u
'toast'})
260 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
261 form
= context
['login_form']
262 assert form
.username
.errors
== [u
'This field is required.']
264 # Failed login - blank password
265 # -----------------------------
266 template
.clear_test_template_context()
267 response
= test_app
.post(
269 'username': u
'chris'})
270 assert 'mediagoblin/auth/login.html' in template
.TEMPLATE_TEST_CONTEXT
272 # Failed login - bad user
273 # -----------------------
274 template
.clear_test_template_context()
275 response
= test_app
.post(
277 'username': u
'steve',
278 'password': 'toast'})
279 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
280 assert context
['login_failed']
282 # Failed login - bad password
283 # ---------------------------
284 template
.clear_test_template_context()
285 response
= test_app
.post(
287 'username': u
'chris',
288 'password': 'jam_and_ham'})
289 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/auth/login.html']
290 assert context
['login_failed']
294 template
.clear_test_template_context()
295 response
= test_app
.post(
297 'username': u
'chris',
298 'password': 'toast'})
300 # User should be redirected
302 assert urlparse
.urlsplit(response
.location
)[2] == '/'
303 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
305 # Make sure user is in the session
306 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/root.html']
307 session
= context
['request'].session
308 assert session
['user_id'] == unicode(test_user
.id)
312 template
.clear_test_template_context()
313 response
= test_app
.get('/auth/logout/')
315 # Should be redirected to index page
317 assert urlparse
.urlsplit(response
.location
)[2] == '/'
318 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
320 # Make sure the user is not in the session
321 context
= template
.TEMPLATE_TEST_CONTEXT
['mediagoblin/root.html']
322 session
= context
['request'].session
323 assert 'user_id' not in session
325 # User is redirected to custom URL if POST['next'] is set
326 # -------------------------------------------------------
327 template
.clear_test_template_context()
328 response
= test_app
.post(
330 'username': u
'chris',
332 'next' : '/u/chris/'})
333 assert urlparse
.urlsplit(response
.location
)[2] == '/u/chris/'
337 def authentication_disabled_app(request
):
340 mgoblin_config
=pkg_resources
.resource_filename(
341 'mediagoblin.tests.auth_configs',
342 'authentication_disabled_appconfig.ini'))
345 def test_authentication_disabled_app(authentication_disabled_app
):
346 # app.auth should = false
347 assert mg_globals
.app
.auth
is False
349 # Try to visit register page
350 template
.clear_test_template_context()
351 response
= authentication_disabled_app
.get('/auth/register/')
355 assert urlparse
.urlsplit(response
.location
)[2] == '/'
356 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
358 # Try to vist login page
359 template
.clear_test_template_context()
360 response
= authentication_disabled_app
.get('/auth/login/')
364 assert urlparse
.urlsplit(response
.location
)[2] == '/'
365 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT
367 ## Test check_login_simple should return None
368 assert auth_tools
.check_login_simple('test', 'simple') is None
370 # Try to visit the forgot password page
371 template
.clear_test_template_context()
372 response
= authentication_disabled_app
.get('/auth/register/')
376 assert urlparse
.urlsplit(response
.location
)[2] == '/'
377 assert 'mediagoblin/root.html' in template
.TEMPLATE_TEST_CONTEXT