changed from sys.exit() to raise AuthError for handling no_auth=false in config and...
[mediagoblin.git] / mediagoblin / tests / test_auth.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4b5f4e87
CAW
3#
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.
8#
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.
13#
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/>.
16
1972a888 17import urlparse
4b5f4e87 18
7e55bcb8 19from mediagoblin import mg_globals
b0c8328e 20from mediagoblin.db.models import User
5c2ece74 21from mediagoblin.tests.tools import fixture_add_user
152a3bfa 22from mediagoblin.tools import template, mail
460ce564 23
4b5f4e87 24
1be247b3 25def test_register_views(test_app):
2fecc29d
CAW
26 """
27 Massive test function that all our registration-related views all work.
28 """
460ce564 29 # Test doing a simple GET on the page
651403f0
CAW
30 # -----------------------------------
31
460ce564
CAW
32 test_app.get('/auth/register/')
33 # Make sure it rendered with the appropriate template
04453ccf 34 assert 'mediagoblin/auth/register.html' in template.TEMPLATE_TEST_CONTEXT
757690cc 35
460ce564 36 # Try to register without providing anything, should error
651403f0
CAW
37 # --------------------------------------------------------
38
ae3bc7fa 39 template.clear_test_template_context()
460ce564
CAW
40 test_app.post(
41 '/auth/register/', {})
ae3bc7fa 42 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
460ce564
CAW
43 form = context['register_form']
44 assert form.username.errors == [u'This field is required.']
45 assert form.password.errors == [u'This field is required.']
460ce564 46 assert form.email.errors == [u'This field is required.']
651403f0
CAW
47
48 # Try to register with fields that are known to be invalid
49 # --------------------------------------------------------
50
51 ## too short
ae3bc7fa 52 template.clear_test_template_context()
651403f0
CAW
53 test_app.post(
54 '/auth/register/', {
55 'username': 'l',
56 'password': 'o',
651403f0 57 'email': 'l'})
ae3bc7fa 58 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
651403f0
CAW
59 form = context['register_form']
60
7d503a89
CAW
61 assert form.username.errors == [u'Field must be between 3 and 30 characters long.']
62 assert form.password.errors == [u'Field must be between 5 and 1024 characters long.']
651403f0
CAW
63
64 ## bad form
ae3bc7fa 65 template.clear_test_template_context()
651403f0
CAW
66 test_app.post(
67 '/auth/register/', {
68 'username': '@_@',
69 'email': 'lollerskates'})
ae3bc7fa 70 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
651403f0
CAW
71 form = context['register_form']
72
7d503a89
CAW
73 assert form.username.errors == [u'This field does not take email addresses.']
74 assert form.email.errors == [u'This field requires an email address.']
651403f0 75
651403f0 76 ## At this point there should be no users in the database ;)
7d503a89 77 assert User.query.count() == 0
651403f0
CAW
78
79 # Successful register
80 # -------------------
ae3bc7fa 81 template.clear_test_template_context()
1972a888
CAW
82 response = test_app.post(
83 '/auth/register/', {
766d9ae7 84 'username': u'happygirl',
1972a888 85 'password': 'iamsohappy',
1972a888
CAW
86 'email': 'happygrrl@example.org'})
87 response.follow()
88
651403f0 89 ## Did we redirect to the proper page? Use the right template?
7d503a89 90 assert urlparse.urlsplit(response.location)[2] == '/u/happygirl/'
04453ccf 91 assert 'mediagoblin/user_pages/user.html' in template.TEMPLATE_TEST_CONTEXT
1972a888 92
651403f0 93 ## Make sure user is in place
6e7ce8d1 94 new_user = mg_globals.database.User.find_one(
766d9ae7 95 {'username': u'happygirl'})
1972a888 96 assert new_user
7a3d00ec 97 assert new_user.status == u'needs_email_verification'
4facc7a0 98 assert new_user.email_verified == False
1972a888 99
f73f4c4b 100 ## Make sure user is logged in
ae3bc7fa 101 request = template.TEMPLATE_TEST_CONTEXT[
f73f4c4b 102 'mediagoblin/user_pages/user.html']['request']
5c2b8486 103 assert request.session['user_id'] == unicode(new_user.id)
f73f4c4b 104
1972a888 105 ## Make sure we get email confirmation, and try verifying
152a3bfa
AW
106 assert len(mail.EMAIL_TEST_INBOX) == 1
107 message = mail.EMAIL_TEST_INBOX.pop()
1972a888 108 assert message['To'] == 'happygrrl@example.org'
ae3bc7fa 109 email_context = template.TEMPLATE_TEST_CONTEXT[
1972a888
CAW
110 'mediagoblin/auth/verification_email.txt']
111 assert email_context['verification_url'] in message.get_payload(decode=True)
112
113 path = urlparse.urlsplit(email_context['verification_url'])[2]
114 get_params = urlparse.urlsplit(email_context['verification_url'])[3]
115 assert path == u'/auth/verify_email/'
116 parsed_get_params = urlparse.parse_qs(get_params)
117
118 ### user should have these same parameters
119 assert parsed_get_params['userid'] == [
5c2b8486 120 unicode(new_user.id)]
1972a888 121 assert parsed_get_params['token'] == [
00bb9550 122 new_user.verification_key]
757690cc 123
7b1e17ed 124 ## Try verifying with bs verification key, shouldn't work
ae3bc7fa 125 template.clear_test_template_context()
a656ccd5 126 response = test_app.get(
7b1e17ed 127 "/auth/verify_email/?userid=%s&token=total_bs" % unicode(
5c2b8486 128 new_user.id))
a656ccd5 129 response.follow()
ae3bc7fa 130 context = template.TEMPLATE_TEST_CONTEXT[
e054ae9b 131 'mediagoblin/user_pages/user.html']
a656ccd5
CAW
132 # assert context['verification_successful'] == True
133 # TODO: Would be good to test messages here when we can do so...
6e7ce8d1 134 new_user = mg_globals.database.User.find_one(
766d9ae7 135 {'username': u'happygirl'})
7b1e17ed 136 assert new_user
7a3d00ec 137 assert new_user.status == u'needs_email_verification'
4facc7a0 138 assert new_user.email_verified == False
7b1e17ed
CAW
139
140 ## Verify the email activation works
ae3bc7fa 141 template.clear_test_template_context()
a656ccd5
CAW
142 response = test_app.get("%s?%s" % (path, get_params))
143 response.follow()
ae3bc7fa 144 context = template.TEMPLATE_TEST_CONTEXT[
e054ae9b 145 'mediagoblin/user_pages/user.html']
a656ccd5
CAW
146 # assert context['verification_successful'] == True
147 # TODO: Would be good to test messages here when we can do so...
6e7ce8d1 148 new_user = mg_globals.database.User.find_one(
766d9ae7 149 {'username': u'happygirl'})
7b1e17ed 150 assert new_user
7a3d00ec 151 assert new_user.status == u'active'
4facc7a0 152 assert new_user.email_verified == True
1972a888 153
cb9bac0c
CAW
154 # Uniqueness checks
155 # -----------------
156 ## We shouldn't be able to register with that user twice
ae3bc7fa 157 template.clear_test_template_context()
8a869db8
CAW
158 response = test_app.post(
159 '/auth/register/', {
766d9ae7 160 'username': u'happygirl',
8a869db8 161 'password': 'iamsohappy2',
8a869db8 162 'email': 'happygrrl2@example.org'})
757690cc 163
ae3bc7fa 164 context = template.TEMPLATE_TEST_CONTEXT[
8a869db8
CAW
165 'mediagoblin/auth/register.html']
166 form = context['register_form']
167 assert form.username.errors == [
168 u'Sorry, a user with that name already exists.']
651403f0 169
8a869db8 170 ## TODO: Also check for double instances of an email address?
757690cc
CM
171
172
5c2ece74 173def test_authentication_views(test_app):
757690cc
CM
174 """
175 Test logging in and logging out
176 """
177 # Make a new user
9754802d 178 test_user = fixture_add_user(active_user=False)
757690cc
CM
179
180 # Get login
0a4cecdc 181 # ---------
757690cc 182 test_app.get('/auth/login/')
04453ccf 183 assert 'mediagoblin/auth/login.html' in template.TEMPLATE_TEST_CONTEXT
757690cc 184
0a4cecdc
CM
185 # Failed login - blank form
186 # -------------------------
ae3bc7fa 187 template.clear_test_template_context()
0a4cecdc 188 response = test_app.post('/auth/login/')
ae3bc7fa 189 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
0a4cecdc
CM
190 form = context['login_form']
191 assert form.username.errors == [u'This field is required.']
192 assert form.password.errors == [u'This field is required.']
193
194 # Failed login - blank user
195 # -------------------------
ae3bc7fa 196 template.clear_test_template_context()
0a4cecdc
CM
197 response = test_app.post(
198 '/auth/login/', {
199 'password': u'toast'})
ae3bc7fa 200 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
0a4cecdc
CM
201 form = context['login_form']
202 assert form.username.errors == [u'This field is required.']
203
204 # Failed login - blank password
205 # -----------------------------
ae3bc7fa 206 template.clear_test_template_context()
0a4cecdc
CM
207 response = test_app.post(
208 '/auth/login/', {
209 'username': u'chris'})
ae3bc7fa 210 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
0a4cecdc
CM
211 form = context['login_form']
212 assert form.password.errors == [u'This field is required.']
213
214 # Failed login - bad user
215 # -----------------------
ae3bc7fa 216 template.clear_test_template_context()
0a4cecdc
CM
217 response = test_app.post(
218 '/auth/login/', {
219 'username': u'steve',
220 'password': 'toast'})
ae3bc7fa 221 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
0a4cecdc
CM
222 assert context['login_failed']
223
224 # Failed login - bad password
225 # ---------------------------
ae3bc7fa 226 template.clear_test_template_context()
0a4cecdc
CM
227 response = test_app.post(
228 '/auth/login/', {
229 'username': u'chris',
a89df961 230 'password': 'jam_and_ham'})
ae3bc7fa 231 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
0a4cecdc
CM
232 assert context['login_failed']
233
234 # Successful login
235 # ----------------
ae3bc7fa 236 template.clear_test_template_context()
757690cc
CM
237 response = test_app.post(
238 '/auth/login/', {
239 'username': u'chris',
240 'password': 'toast'})
0a4cecdc
CM
241
242 # User should be redirected
757690cc 243 response.follow()
7d503a89 244 assert urlparse.urlsplit(response.location)[2] == '/'
04453ccf 245 assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
757690cc 246
0a4cecdc 247 # Make sure user is in the session
ae3bc7fa 248 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
0a4cecdc 249 session = context['request'].session
5c2b8486 250 assert session['user_id'] == unicode(test_user.id)
757690cc 251
0a4cecdc
CM
252 # Successful logout
253 # -----------------
ae3bc7fa 254 template.clear_test_template_context()
0a4cecdc
CM
255 response = test_app.get('/auth/logout/')
256
257 # Should be redirected to index page
258 response.follow()
7d503a89 259 assert urlparse.urlsplit(response.location)[2] == '/'
04453ccf 260 assert 'mediagoblin/root.html' in template.TEMPLATE_TEST_CONTEXT
0a4cecdc
CM
261
262 # Make sure the user is not in the session
ae3bc7fa 263 context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
0a4cecdc 264 session = context['request'].session
04453ccf 265 assert 'user_id' not in session
757690cc 266
12c231c8
CM
267 # User is redirected to custom URL if POST['next'] is set
268 # -------------------------------------------------------
ae3bc7fa 269 template.clear_test_template_context()
12c231c8
CM
270 response = test_app.post(
271 '/auth/login/', {
272 'username': u'chris',
273 'password': 'toast',
274 'next' : '/u/chris/'})
7d503a89 275 assert urlparse.urlsplit(response.location)[2] == '/u/chris/'