Commit | Line | Data |
---|---|---|
515e3bd9 | 1 | |
8e1e744d | 2 | # GNU MediaGoblin -- federated, autonomous media hosting |
cf29e8a8 | 3 | # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. |
4b5f4e87 CAW |
4 | # |
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. | |
9 | # | |
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. | |
14 | # | |
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/>. | |
fd19da34 | 17 | |
dfd3f561 RE |
18 | import pkg_resources |
19 | import pytest | |
4b5f4e87 | 20 | |
e49b7e02 BP |
21 | import six |
22 | ||
fd19da34 BP |
23 | import six.moves.urllib.parse as urlparse |
24 | ||
7e55bcb8 | 25 | from mediagoblin import mg_globals |
b0c8328e | 26 | from mediagoblin.db.models import User |
dfd3f561 | 27 | from mediagoblin.tests.tools import get_app, fixture_add_user |
152a3bfa | 28 | from mediagoblin.tools import template, mail |
3b8c733b | 29 | from mediagoblin.auth import tools as auth_tools |
460ce564 | 30 | |
4b5f4e87 | 31 | |
1be247b3 | 32 | def test_register_views(test_app): |
2fecc29d CAW |
33 | """ |
34 | Massive test function that all our registration-related views all work. | |
35 | """ | |
460ce564 | 36 | # Test doing a simple GET on the page |
651403f0 CAW |
37 | # ----------------------------------- |
38 | ||
460ce564 CAW |
39 | test_app.get('/auth/register/') |
40 | # Make sure it rendered with the appropriate template | |
04453ccf | 41 | assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT |
757690cc | 42 | |
460ce564 | 43 | # Try to register without providing anything, should error |
651403f0 CAW |
44 | # -------------------------------------------------------- |
45 | ||
ae3bc7fa | 46 | template.clear_test_template_context() |
460ce564 CAW |
47 | test_app.post( |
48 | '/auth/register/', {}) | |
ae3bc7fa | 49 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] |
460ce564 CAW |
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.'] | |
460ce564 | 53 | assert form.email.errors == [u'This field is required.'] |
651403f0 CAW |
54 | |
55 | # Try to register with fields that are known to be invalid | |
56 | # -------------------------------------------------------- | |
57 | ||
58 | ## too short | |
ae3bc7fa | 59 | template.clear_test_template_context() |
651403f0 CAW |
60 | test_app.post( |
61 | '/auth/register/', { | |
62 | 'username': 'l', | |
63 | 'password': 'o', | |
651403f0 | 64 | 'email': 'l'}) |
ae3bc7fa | 65 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] |
651403f0 CAW |
66 | form = context['register_form'] |
67 | ||
7d503a89 CAW |
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.'] | |
651403f0 CAW |
70 | |
71 | ## bad form | |
ae3bc7fa | 72 | template.clear_test_template_context() |
651403f0 CAW |
73 | test_app.post( |
74 | '/auth/register/', { | |
75 | 'username': '@_@', | |
76 | 'email': 'lollerskates'}) | |
ae3bc7fa | 77 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html'] |
651403f0 CAW |
78 | form = context['register_form'] |
79 | ||
7d503a89 CAW |
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.'] | |
651403f0 | 82 | |
651403f0 | 83 | ## At this point there should be no users in the database ;) |
7d503a89 | 84 | assert User.query.count() == 0 |
651403f0 CAW |
85 | |
86 | # Successful register | |
87 | # ------------------- | |
ae3bc7fa | 88 | template.clear_test_template_context() |
1972a888 CAW |
89 | response = test_app.post( |
90 | '/auth/register/', { | |
e1561d04 | 91 | 'username': u'angrygirl', |
92 | 'password': 'iamsoangry', | |
93 | 'email': 'angrygrrl@example.org'}) | |
1972a888 CAW |
94 | response.follow() |
95 | ||
651403f0 | 96 | ## Did we redirect to the proper page? Use the right template? |
e1561d04 | 97 | assert urlparse.urlsplit(response.location)[2] == '/u/angrygirl/' |
515e3bd9 | 98 | assert 'mediagoblin/user_pages/user_nonactive.html' in template.TEMPLATE_TEST_CONTEXT |
1972a888 | 99 | |
651403f0 | 100 | ## Make sure user is in place |
44082b12 | 101 | new_user = mg_globals.database.User.query.filter_by( |
e1561d04 | 102 | username=u'angrygirl').first() |
1972a888 | 103 | assert new_user |
1972a888 | 104 | |
8e91df87 | 105 | ## Make sure that the proper privileges are granted on registration |
106 | ||
107 | assert new_user.has_privilege(u'commenter') | |
108 | assert new_user.has_privilege(u'uploader') | |
109 | assert new_user.has_privilege(u'reporter') | |
110 | assert not new_user.has_privilege(u'active') | |
f73f4c4b | 111 | ## Make sure user is logged in |
ae3bc7fa | 112 | request = template.TEMPLATE_TEST_CONTEXT[ |
515e3bd9 | 113 | 'mediagoblin/user_pages/user_nonactive.html']['request'] |
e49b7e02 | 114 | assert request.session['user_id'] == six.text_type(new_user.id) |
f73f4c4b | 115 | |
1972a888 | 116 | ## Make sure we get email confirmation, and try verifying |
152a3bfa AW |
117 | assert len(mail.EMAIL_TEST_INBOX) == 1 |
118 | message = mail.EMAIL_TEST_INBOX.pop() | |
e1561d04 | 119 | assert message['To'] == 'angrygrrl@example.org' |
ae3bc7fa | 120 | email_context = template.TEMPLATE_TEST_CONTEXT[ |
1972a888 | 121 | 'mediagoblin/auth/verification_email.txt'] |
cda3055b | 122 | assert email_context['verification_url'].encode('ascii') in message.get_payload(decode=True) |
1972a888 CAW |
123 | |
124 | path = urlparse.urlsplit(email_context['verification_url'])[2] | |
125 | get_params = urlparse.urlsplit(email_context['verification_url'])[3] | |
126 | assert path == u'/auth/verify_email/' | |
127 | parsed_get_params = urlparse.parse_qs(get_params) | |
128 | ||
7b1e17ed | 129 | ## Try verifying with bs verification key, shouldn't work |
ae3bc7fa | 130 | template.clear_test_template_context() |
a656ccd5 | 131 | response = test_app.get( |
342f06f7 | 132 | "/auth/verify_email/?token=total_bs") |
a656ccd5 | 133 | response.follow() |
342f06f7 RE |
134 | |
135 | # Correct redirect? | |
136 | assert urlparse.urlsplit(response.location)[2] == '/' | |
137 | ||
a656ccd5 CAW |
138 | # assert context['verification_successful'] == True |
139 | # TODO: Would be good to test messages here when we can do so... | |
44082b12 | 140 | new_user = mg_globals.database.User.query.filter_by( |
e1561d04 | 141 | username=u'angrygirl').first() |
7b1e17ed | 142 | assert new_user |
7b1e17ed CAW |
143 | |
144 | ## Verify the email activation works | |
ae3bc7fa | 145 | template.clear_test_template_context() |
a656ccd5 CAW |
146 | response = test_app.get("%s?%s" % (path, get_params)) |
147 | response.follow() | |
ae3bc7fa | 148 | context = template.TEMPLATE_TEST_CONTEXT[ |
e054ae9b | 149 | 'mediagoblin/user_pages/user.html'] |
a656ccd5 CAW |
150 | # assert context['verification_successful'] == True |
151 | # TODO: Would be good to test messages here when we can do so... | |
44082b12 | 152 | new_user = mg_globals.database.User.query.filter_by( |
e1561d04 | 153 | username=u'angrygirl').first() |
7b1e17ed | 154 | assert new_user |
1972a888 | 155 | |
cb9bac0c CAW |
156 | # Uniqueness checks |
157 | # ----------------- | |
158 | ## We shouldn't be able to register with that user twice | |
ae3bc7fa | 159 | template.clear_test_template_context() |
8a869db8 CAW |
160 | response = test_app.post( |
161 | '/auth/register/', { | |
e1561d04 | 162 | 'username': u'angrygirl', |
163 | 'password': 'iamsoangry2', | |
164 | 'email': 'angrygrrl2@example.org'}) | |
757690cc | 165 | |
ae3bc7fa | 166 | context = template.TEMPLATE_TEST_CONTEXT[ |
8a869db8 CAW |
167 | 'mediagoblin/auth/register.html'] |
168 | form = context['register_form'] | |
169 | assert form.username.errors == [ | |
170 | u'Sorry, a user with that name already exists.'] | |
651403f0 | 171 | |
8a869db8 | 172 | ## TODO: Also check for double instances of an email address? |
757690cc | 173 | |
f339b76a RE |
174 | ### Oops, forgot the password |
175 | # ------------------- | |
176 | template.clear_test_template_context() | |
177 | response = test_app.post( | |
178 | '/auth/forgot_password/', | |
e1561d04 | 179 | {'username': u'angrygirl'}) |
f339b76a RE |
180 | response.follow() |
181 | ||
182 | ## Did we redirect to the proper page? Use the right template? | |
183 | assert urlparse.urlsplit(response.location)[2] == '/auth/login/' | |
184 | assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT | |
185 | ||
186 | ## Make sure link to change password is sent by email | |
187 | assert len(mail.EMAIL_TEST_INBOX) == 1 | |
188 | message = mail.EMAIL_TEST_INBOX.pop() | |
e1561d04 | 189 | assert message['To'] == 'angrygrrl@example.org' |
f339b76a | 190 | email_context = template.TEMPLATE_TEST_CONTEXT[ |
af665c4e | 191 | 'mediagoblin/plugins/basic_auth/fp_verification_email.txt'] |
f339b76a | 192 | #TODO - change the name of verification_url to something forgot-password-ish |
cda3055b | 193 | assert email_context['verification_url'].encode('ascii') in message.get_payload(decode=True) |
f339b76a RE |
194 | |
195 | path = urlparse.urlsplit(email_context['verification_url'])[2] | |
196 | get_params = urlparse.urlsplit(email_context['verification_url'])[3] | |
f339b76a | 197 | parsed_get_params = urlparse.parse_qs(get_params) |
342f06f7 | 198 | assert path == u'/auth/forgot_password/verify/' |
f339b76a RE |
199 | |
200 | ## Try using a bs password-changing verification key, shouldn't work | |
201 | template.clear_test_template_context() | |
202 | response = test_app.get( | |
342f06f7 RE |
203 | "/auth/forgot_password/verify/?token=total_bs") |
204 | response.follow() | |
f339b76a | 205 | |
342f06f7 RE |
206 | # Correct redirect? |
207 | assert urlparse.urlsplit(response.location)[2] == '/' | |
f339b76a RE |
208 | |
209 | ## Verify step 1 of password-change works -- can see form to change password | |
210 | template.clear_test_template_context() | |
211 | response = test_app.get("%s?%s" % (path, get_params)) | |
af665c4e RE |
212 | assert 'mediagoblin/plugins/basic_auth/change_fp.html' in \ |
213 | template.TEMPLATE_TEST_CONTEXT | |
f339b76a RE |
214 | |
215 | ## Verify step 2.1 of password-change works -- report success to user | |
216 | template.clear_test_template_context() | |
217 | response = test_app.post( | |
218 | '/auth/forgot_password/verify/', { | |
e1561d04 | 219 | 'password': 'iamveryveryangry', |
f339b76a RE |
220 | 'token': parsed_get_params['token']}) |
221 | response.follow() | |
222 | assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT | |
223 | ||
224 | ## Verify step 2.2 of password-change works -- login w/ new password success | |
225 | template.clear_test_template_context() | |
226 | response = test_app.post( | |
227 | '/auth/login/', { | |
e1561d04 | 228 | 'username': u'angrygirl', |
229 | 'password': 'iamveryveryangry'}) | |
f339b76a RE |
230 | |
231 | # User should be redirected | |
232 | response.follow() | |
233 | assert urlparse.urlsplit(response.location)[2] == '/' | |
234 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT | |
235 | ||
5c2ece74 | 236 | def test_authentication_views(test_app): |
757690cc CM |
237 | """ |
238 | Test logging in and logging out | |
239 | """ | |
240 | # Make a new user | |
e1561d04 | 241 | test_user = fixture_add_user() |
757690cc | 242 | |
5adb906a | 243 | |
757690cc | 244 | # Get login |
0a4cecdc | 245 | # --------- |
757690cc | 246 | test_app.get('/auth/login/') |
04453ccf | 247 | assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT |
757690cc | 248 | |
0a4cecdc CM |
249 | # Failed login - blank form |
250 | # ------------------------- | |
ae3bc7fa | 251 | template.clear_test_template_context() |
0a4cecdc | 252 | response = test_app.post('/auth/login/') |
ae3bc7fa | 253 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] |
0a4cecdc CM |
254 | form = context['login_form'] |
255 | assert form.username.errors == [u'This field is required.'] | |
0a4cecdc CM |
256 | |
257 | # Failed login - blank user | |
258 | # ------------------------- | |
ae3bc7fa | 259 | template.clear_test_template_context() |
0a4cecdc CM |
260 | response = test_app.post( |
261 | '/auth/login/', { | |
262 | 'password': u'toast'}) | |
ae3bc7fa | 263 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] |
0a4cecdc CM |
264 | form = context['login_form'] |
265 | assert form.username.errors == [u'This field is required.'] | |
266 | ||
267 | # Failed login - blank password | |
268 | # ----------------------------- | |
ae3bc7fa | 269 | template.clear_test_template_context() |
0a4cecdc CM |
270 | response = test_app.post( |
271 | '/auth/login/', { | |
272 | 'username': u'chris'}) | |
e4deacd9 | 273 | assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT |
0a4cecdc CM |
274 | |
275 | # Failed login - bad user | |
276 | # ----------------------- | |
ae3bc7fa | 277 | template.clear_test_template_context() |
0a4cecdc CM |
278 | response = test_app.post( |
279 | '/auth/login/', { | |
280 | 'username': u'steve', | |
281 | 'password': 'toast'}) | |
ae3bc7fa | 282 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] |
0a4cecdc CM |
283 | assert context['login_failed'] |
284 | ||
285 | # Failed login - bad password | |
286 | # --------------------------- | |
ae3bc7fa | 287 | template.clear_test_template_context() |
0a4cecdc CM |
288 | response = test_app.post( |
289 | '/auth/login/', { | |
290 | 'username': u'chris', | |
a89df961 | 291 | 'password': 'jam_and_ham'}) |
ae3bc7fa | 292 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] |
0a4cecdc CM |
293 | assert context['login_failed'] |
294 | ||
295 | # Successful login | |
296 | # ---------------- | |
ae3bc7fa | 297 | template.clear_test_template_context() |
757690cc CM |
298 | response = test_app.post( |
299 | '/auth/login/', { | |
300 | 'username': u'chris', | |
301 | 'password': 'toast'}) | |
0a4cecdc CM |
302 | |
303 | # User should be redirected | |
757690cc | 304 | response.follow() |
7d503a89 | 305 | assert urlparse.urlsplit(response.location)[2] == '/' |
04453ccf | 306 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT |
757690cc | 307 | |
0a4cecdc | 308 | # Make sure user is in the session |
ae3bc7fa | 309 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] |
0a4cecdc | 310 | session = context['request'].session |
e49b7e02 | 311 | assert session['user_id'] == six.text_type(test_user.id) |
757690cc | 312 | |
0a4cecdc CM |
313 | # Successful logout |
314 | # ----------------- | |
ae3bc7fa | 315 | template.clear_test_template_context() |
0a4cecdc CM |
316 | response = test_app.get('/auth/logout/') |
317 | ||
318 | # Should be redirected to index page | |
319 | response.follow() | |
7d503a89 | 320 | assert urlparse.urlsplit(response.location)[2] == '/' |
04453ccf | 321 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT |
0a4cecdc CM |
322 | |
323 | # Make sure the user is not in the session | |
ae3bc7fa | 324 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html'] |
0a4cecdc | 325 | session = context['request'].session |
04453ccf | 326 | assert 'user_id' not in session |
757690cc | 327 | |
12c231c8 CM |
328 | # User is redirected to custom URL if POST['next'] is set |
329 | # ------------------------------------------------------- | |
ae3bc7fa | 330 | template.clear_test_template_context() |
12c231c8 CM |
331 | response = test_app.post( |
332 | '/auth/login/', { | |
333 | 'username': u'chris', | |
334 | 'password': 'toast', | |
335 | 'next' : '/u/chris/'}) | |
7d503a89 | 336 | assert urlparse.urlsplit(response.location)[2] == '/u/chris/' |
dfd3f561 | 337 | |
8cf9d643 | 338 | ## Verify that username is lowercased on login attempt |
339 | template.clear_test_template_context() | |
340 | response = test_app.post( | |
341 | '/auth/login/', { | |
342 | 'username': u'ANDREW', | |
343 | 'password': 'fuselage'}) | |
344 | context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html'] | |
345 | form = context['login_form'] | |
346 | ||
347 | # Username should no longer be uppercased; it should be lowercased | |
348 | assert not form.username.data == u'ANDREW' | |
349 | assert form.username.data == u'andrew' | |
350 | ||
dfd3f561 | 351 | @pytest.fixture() |
5101c469 | 352 | def authentication_disabled_app(request): |
dfd3f561 RE |
353 | return get_app( |
354 | request, | |
355 | mgoblin_config=pkg_resources.resource_filename( | |
356 | 'mediagoblin.tests.auth_configs', | |
5101c469 | 357 | 'authentication_disabled_appconfig.ini')) |
dfd3f561 RE |
358 | |
359 | ||
5101c469 | 360 | def test_authentication_disabled_app(authentication_disabled_app): |
dfd3f561 | 361 | # app.auth should = false |
2c901db0 | 362 | assert mg_globals |
dfd3f561 RE |
363 | assert mg_globals.app.auth is False |
364 | ||
365 | # Try to visit register page | |
366 | template.clear_test_template_context() | |
5101c469 | 367 | response = authentication_disabled_app.get('/auth/register/') |
dfd3f561 RE |
368 | response.follow() |
369 | ||
370 | # Correct redirect? | |
371 | assert urlparse.urlsplit(response.location)[2] == '/' | |
372 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT | |
373 | ||
374 | # Try to vist login page | |
375 | template.clear_test_template_context() | |
5101c469 | 376 | response = authentication_disabled_app.get('/auth/login/') |
dfd3f561 RE |
377 | response.follow() |
378 | ||
379 | # Correct redirect? | |
380 | assert urlparse.urlsplit(response.location)[2] == '/' | |
381 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT | |
382 | ||
3b8c733b RE |
383 | ## Test check_login_simple should return None |
384 | assert auth_tools.check_login_simple('test', 'simple') is None | |
f339b76a RE |
385 | |
386 | # Try to visit the forgot password page | |
387 | template.clear_test_template_context() | |
5101c469 | 388 | response = authentication_disabled_app.get('/auth/register/') |
f339b76a RE |
389 | response.follow() |
390 | ||
391 | # Correct redirect? | |
392 | assert urlparse.urlsplit(response.location)[2] == '/' | |
393 | assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT |