##// END OF EJS Templates
login: add support link to disabled password reset page
lisaq -
r1038:1703d7ca default
parent child Browse files
Show More
@@ -1,83 +1,88 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/root.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Sign In')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <style>body{background-color:#eeeeee;}</style>
12 12 <div class="loginbox">
13 13 <div class="header">
14 14 <div id="header-inner" class="title">
15 15 <div id="logo">
16 16 <div class="logo-wrapper">
17 17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 18 </div>
19 19 %if c.rhodecode_name:
20 20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 21 %endif
22 22 </div>
23 23 </div>
24 24 </div>
25 25
26 26 <div class="loginwrapper">
27 27 <div class="left-column">
28 28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 29 </div>
30 30 <%block name="above_login_button" />
31 31 <div id="login" class="right-column">
32 32 <!-- login -->
33 33 <div class="sign-in-title">
34 34 <h1>${_('Sign In')}</h1>
35 35 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
36 36 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
37 37 %endif
38 38 </div>
39 39 <div class="inner form">
40 40 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
41 41
42 42 <label for="username">${_('Username')}:</label>
43 43 ${h.text('username', class_='focus', value=defaults.get('username'))}
44 44 %if 'username' in errors:
45 45 <span class="error-message">${errors.get('username')}</span>
46 46 <br />
47 47 %endif
48 48
49 49 <label for="password">${_('Password')}:</label>
50 50 ${h.password('password', class_='focus')}
51 51 %if 'password' in errors:
52 52 <span class="error-message">${errors.get('password')}</span>
53 53 <br />
54 54 %endif
55 55
56 56 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
57 57 <label class="checkbox" for="remember">${_('Remember me')}</label>
58 58
59 59 %if h.HasPermissionAny('hg.password_reset.enabled')():
60 60 <p class="links">
61 61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'), class_='pwd_reset')}
62 62 </p>
63 63 %elif h.HasPermissionAny('hg.password_reset.hidden')():
64 64 <p class="help-block">
65 ${_('Contact an administrator if you have forgotten your password.')}
65 ${_('Password reset is disabled. Please contact ')}
66 % if c.visual.rhodecode_support_url:
67 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
68 ${_('or')}
69 % endif
70 ${_('an administrator if you need help.')}
66 71 </p>
67 %endif
72 %endif
68 73
69 74
70 75 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
71 76
72 77 ${h.end_form()}
73 78 <script type="text/javascript">
74 79 $(document).ready(function(){
75 80 $('#username').focus();
76 81 })
77 82 </script>
78 83 </div>
79 84 <!-- end login -->
80 85 <%block name="below_login_button" />
81 86 </div>
82 87 </div>
83 88 </div>
@@ -1,83 +1,90 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/root.html"/>
3 3
4 4 <%def name="title()">
5 ${_('Create an Account')}
5 ${_('Reset Password')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10 <style>body{background-color:#eeeeee;}</style>
11 11
12 12 <div class="loginbox">
13 13 <div class="header">
14 14 <div id="header-inner" class="title">
15 15 <div id="logo">
16 16 <div class="logo-wrapper">
17 17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 18 </div>
19 19 %if c.rhodecode_name:
20 20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 21 %endif
22 22 </div>
23 23 </div>
24 24 </div>
25 25
26 26 <div class="loginwrapper">
27 27 <div class="left-column">
28 28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 29 </div>
30 30
31 31 %if h.HasPermissionAny('hg.password_reset.disabled')():
32 32 <div class="right-column">
33 <p>${_('Password reset has been disabled.')}</p>
33 <p>
34 ${_('Password reset is disabled. Please contact ')}
35 % if c.visual.rhodecode_support_url:
36 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
37 ${_('or')}
38 % endif
39 ${_('an administrator if you need help.')}
40 </p>
34 41 </div>
35 42 %else:
36 43 <div id="register" class="right-column">
37 44 <!-- login -->
38 45 <div class="sign-in-title">
39 46 <h1>${_('Reset your Password')}</h1>
40 47 <h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
41 48 </div>
42 49 <div class="inner form">
43 50 ${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
44 51 <label for="email">${_('Email Address')}:</label>
45 52 ${h.text('email', defaults.get('email'))}
46 53 %if 'email' in errors:
47 54 <span class="error-message">${errors.get('email')}</span>
48 55 <br />
49 56 %endif
50 57
51 58 %if captcha_active:
52 59 <div class="login-captcha"
53 60 <label for="email">${_('Captcha')}:</label>
54 61 ${h.hidden('recaptcha_field')}
55 62 <div id="recaptcha"></div>
56 63 %if 'recaptcha_field' in errors:
57 64 <span class="error-message">${errors.get('recaptcha_field')}</span>
58 65 <br />
59 66 %endif
60 67 </div>
61 68 %endif
62 69
63 70 ${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
64 71 <div class="activation_msg">${_('Password reset link will be sent to matching email address')}</div>
65 72
66 73 ${h.end_form()}
67 74 </div>
68 75 </div>
69 76 %endif
70 77 </div>
71 78 </div>
72 79
73 80 %if captcha_active:
74 81 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
75 82 %endif
76 83 <script type="text/javascript">
77 84 $(document).ready(function(){
78 85 $('#email').focus();
79 86 %if captcha_active:
80 87 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
81 88 %endif
82 89 });
83 90 </script>
@@ -1,588 +1,588 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import urlparse
22 22
23 23 import mock
24 24 import pytest
25 25
26 26 from rhodecode.config.routing import ADMIN_PREFIX
27 27 from rhodecode.tests import (
28 28 TestController, assert_session_flash, clear_all_caches, url,
29 29 HG_REPO, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
30 30 from rhodecode.tests.fixture import Fixture
31 31 from rhodecode.tests.utils import AssertResponse, get_session_from_response
32 32 from rhodecode.lib.auth import check_password, generate_auth_token
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.model.auth_token import AuthTokenModel
35 35 from rhodecode.model import validators
36 36 from rhodecode.model.db import User, Notification
37 37 from rhodecode.model.meta import Session
38 38
39 39 fixture = Fixture()
40 40
41 41 # Hardcode URLs because we don't have a request object to use
42 42 # pyramids URL generation methods.
43 43 index_url = '/'
44 44 login_url = ADMIN_PREFIX + '/login'
45 45 logut_url = ADMIN_PREFIX + '/logout'
46 46 register_url = ADMIN_PREFIX + '/register'
47 47 pwd_reset_url = ADMIN_PREFIX + '/password_reset'
48 48 pwd_reset_confirm_url = ADMIN_PREFIX + '/password_reset_confirmation'
49 49
50 50
51 51 @pytest.mark.usefixtures('app')
52 52 class TestLoginController:
53 53 destroy_users = set()
54 54
55 55 @classmethod
56 56 def teardown_class(cls):
57 57 fixture.destroy_users(cls.destroy_users)
58 58
59 59 def teardown_method(self, method):
60 60 for n in Notification.query().all():
61 61 Session().delete(n)
62 62
63 63 Session().commit()
64 64 assert Notification.query().all() == []
65 65
66 66 def test_index(self):
67 67 response = self.app.get(login_url)
68 68 assert response.status == '200 OK'
69 69 # Test response...
70 70
71 71 def test_login_admin_ok(self):
72 72 response = self.app.post(login_url,
73 73 {'username': 'test_admin',
74 74 'password': 'test12'})
75 75 assert response.status == '302 Found'
76 76 session = get_session_from_response(response)
77 77 username = session['rhodecode_user'].get('username')
78 78 assert username == 'test_admin'
79 79 response = response.follow()
80 80 response.mustcontain('/%s' % HG_REPO)
81 81
82 82 def test_login_regular_ok(self):
83 83 response = self.app.post(login_url,
84 84 {'username': 'test_regular',
85 85 'password': 'test12'})
86 86
87 87 assert response.status == '302 Found'
88 88 session = get_session_from_response(response)
89 89 username = session['rhodecode_user'].get('username')
90 90 assert username == 'test_regular'
91 91 response = response.follow()
92 92 response.mustcontain('/%s' % HG_REPO)
93 93
94 94 def test_login_ok_came_from(self):
95 95 test_came_from = '/_admin/users?branch=stable'
96 96 _url = '{}?came_from={}'.format(login_url, test_came_from)
97 97 response = self.app.post(
98 98 _url, {'username': 'test_admin', 'password': 'test12'})
99 99 assert response.status == '302 Found'
100 100 assert 'branch=stable' in response.location
101 101 response = response.follow()
102 102
103 103 assert response.status == '200 OK'
104 104 response.mustcontain('Users administration')
105 105
106 106 def test_redirect_to_login_with_get_args(self):
107 107 with fixture.anon_access(False):
108 108 kwargs = {'branch': 'stable'}
109 109 response = self.app.get(
110 110 url('summary_home', repo_name=HG_REPO, **kwargs))
111 111 assert response.status == '302 Found'
112 112 response_query = urlparse.parse_qsl(response.location)
113 113 assert 'branch=stable' in response_query[0][1]
114 114
115 115 def test_login_form_with_get_args(self):
116 116 _url = '{}?came_from=/_admin/users,branch=stable'.format(login_url)
117 117 response = self.app.get(_url)
118 118 assert 'branch%3Dstable' in response.form.action
119 119
120 120 @pytest.mark.parametrize("url_came_from", [
121 121 'data:text/html,<script>window.alert("xss")</script>',
122 122 'mailto:test@rhodecode.org',
123 123 'file:///etc/passwd',
124 124 'ftp://some.ftp.server',
125 125 'http://other.domain',
126 126 '/\r\nX-Forwarded-Host: http://example.org',
127 127 ])
128 128 def test_login_bad_came_froms(self, url_came_from):
129 129 _url = '{}?came_from={}'.format(login_url, url_came_from)
130 130 response = self.app.post(
131 131 _url,
132 132 {'username': 'test_admin', 'password': 'test12'})
133 133 assert response.status == '302 Found'
134 134 response = response.follow()
135 135 assert response.status == '200 OK'
136 136 assert response.request.path == '/'
137 137
138 138 def test_login_short_password(self):
139 139 response = self.app.post(login_url,
140 140 {'username': 'test_admin',
141 141 'password': 'as'})
142 142 assert response.status == '200 OK'
143 143
144 144 response.mustcontain('Enter 3 characters or more')
145 145
146 146 def test_login_wrong_non_ascii_password(self, user_regular):
147 147 response = self.app.post(
148 148 login_url,
149 149 {'username': user_regular.username,
150 150 'password': u'invalid-non-asci\xe4'.encode('utf8')})
151 151
152 152 response.mustcontain('invalid user name')
153 153 response.mustcontain('invalid password')
154 154
155 155 def test_login_with_non_ascii_password(self, user_util):
156 156 password = u'valid-non-ascii\xe4'
157 157 user = user_util.create_user(password=password)
158 158 response = self.app.post(
159 159 login_url,
160 160 {'username': user.username,
161 161 'password': password.encode('utf-8')})
162 162 assert response.status_code == 302
163 163
164 164 def test_login_wrong_username_password(self):
165 165 response = self.app.post(login_url,
166 166 {'username': 'error',
167 167 'password': 'test12'})
168 168
169 169 response.mustcontain('invalid user name')
170 170 response.mustcontain('invalid password')
171 171
172 172 def test_login_admin_ok_password_migration(self, real_crypto_backend):
173 173 from rhodecode.lib import auth
174 174
175 175 # create new user, with sha256 password
176 176 temp_user = 'test_admin_sha256'
177 177 user = fixture.create_user(temp_user)
178 178 user.password = auth._RhodeCodeCryptoSha256().hash_create(
179 179 b'test123')
180 180 Session().add(user)
181 181 Session().commit()
182 182 self.destroy_users.add(temp_user)
183 183 response = self.app.post(login_url,
184 184 {'username': temp_user,
185 185 'password': 'test123'})
186 186
187 187 assert response.status == '302 Found'
188 188 session = get_session_from_response(response)
189 189 username = session['rhodecode_user'].get('username')
190 190 assert username == temp_user
191 191 response = response.follow()
192 192 response.mustcontain('/%s' % HG_REPO)
193 193
194 194 # new password should be bcrypted, after log-in and transfer
195 195 user = User.get_by_username(temp_user)
196 196 assert user.password.startswith('$')
197 197
198 198 # REGISTRATIONS
199 199 def test_register(self):
200 200 response = self.app.get(register_url)
201 201 response.mustcontain('Create an Account')
202 202
203 203 def test_register_err_same_username(self):
204 204 uname = 'test_admin'
205 205 response = self.app.post(
206 206 register_url,
207 207 {
208 208 'username': uname,
209 209 'password': 'test12',
210 210 'password_confirmation': 'test12',
211 211 'email': 'goodmail@domain.com',
212 212 'firstname': 'test',
213 213 'lastname': 'test'
214 214 }
215 215 )
216 216
217 217 assertr = AssertResponse(response)
218 218 msg = validators.ValidUsername()._messages['username_exists']
219 219 msg = msg % {'username': uname}
220 220 assertr.element_contains('#username+.error-message', msg)
221 221
222 222 def test_register_err_same_email(self):
223 223 response = self.app.post(
224 224 register_url,
225 225 {
226 226 'username': 'test_admin_0',
227 227 'password': 'test12',
228 228 'password_confirmation': 'test12',
229 229 'email': 'test_admin@mail.com',
230 230 'firstname': 'test',
231 231 'lastname': 'test'
232 232 }
233 233 )
234 234
235 235 assertr = AssertResponse(response)
236 236 msg = validators.UniqSystemEmail()()._messages['email_taken']
237 237 assertr.element_contains('#email+.error-message', msg)
238 238
239 239 def test_register_err_same_email_case_sensitive(self):
240 240 response = self.app.post(
241 241 register_url,
242 242 {
243 243 'username': 'test_admin_1',
244 244 'password': 'test12',
245 245 'password_confirmation': 'test12',
246 246 'email': 'TesT_Admin@mail.COM',
247 247 'firstname': 'test',
248 248 'lastname': 'test'
249 249 }
250 250 )
251 251 assertr = AssertResponse(response)
252 252 msg = validators.UniqSystemEmail()()._messages['email_taken']
253 253 assertr.element_contains('#email+.error-message', msg)
254 254
255 255 def test_register_err_wrong_data(self):
256 256 response = self.app.post(
257 257 register_url,
258 258 {
259 259 'username': 'xs',
260 260 'password': 'test',
261 261 'password_confirmation': 'test',
262 262 'email': 'goodmailm',
263 263 'firstname': 'test',
264 264 'lastname': 'test'
265 265 }
266 266 )
267 267 assert response.status == '200 OK'
268 268 response.mustcontain('An email address must contain a single @')
269 269 response.mustcontain('Enter a value 6 characters long or more')
270 270
271 271 def test_register_err_username(self):
272 272 response = self.app.post(
273 273 register_url,
274 274 {
275 275 'username': 'error user',
276 276 'password': 'test12',
277 277 'password_confirmation': 'test12',
278 278 'email': 'goodmailm',
279 279 'firstname': 'test',
280 280 'lastname': 'test'
281 281 }
282 282 )
283 283
284 284 response.mustcontain('An email address must contain a single @')
285 285 response.mustcontain(
286 286 'Username may only contain '
287 287 'alphanumeric characters underscores, '
288 288 'periods or dashes and must begin with '
289 289 'alphanumeric character')
290 290
291 291 def test_register_err_case_sensitive(self):
292 292 usr = 'Test_Admin'
293 293 response = self.app.post(
294 294 register_url,
295 295 {
296 296 'username': usr,
297 297 'password': 'test12',
298 298 'password_confirmation': 'test12',
299 299 'email': 'goodmailm',
300 300 'firstname': 'test',
301 301 'lastname': 'test'
302 302 }
303 303 )
304 304
305 305 assertr = AssertResponse(response)
306 306 msg = validators.ValidUsername()._messages['username_exists']
307 307 msg = msg % {'username': usr}
308 308 assertr.element_contains('#username+.error-message', msg)
309 309
310 310 def test_register_special_chars(self):
311 311 response = self.app.post(
312 312 register_url,
313 313 {
314 314 'username': 'xxxaxn',
315 315 'password': 'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
316 316 'password_confirmation': 'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
317 317 'email': 'goodmailm@test.plx',
318 318 'firstname': 'test',
319 319 'lastname': 'test'
320 320 }
321 321 )
322 322
323 323 msg = validators.ValidPassword()._messages['invalid_password']
324 324 response.mustcontain(msg)
325 325
326 326 def test_register_password_mismatch(self):
327 327 response = self.app.post(
328 328 register_url,
329 329 {
330 330 'username': 'xs',
331 331 'password': '123qwe',
332 332 'password_confirmation': 'qwe123',
333 333 'email': 'goodmailm@test.plxa',
334 334 'firstname': 'test',
335 335 'lastname': 'test'
336 336 }
337 337 )
338 338 msg = validators.ValidPasswordsMatch()._messages['password_mismatch']
339 339 response.mustcontain(msg)
340 340
341 341 def test_register_ok(self):
342 342 username = 'test_regular4'
343 343 password = 'qweqwe'
344 344 email = 'marcin@test.com'
345 345 name = 'testname'
346 346 lastname = 'testlastname'
347 347
348 348 response = self.app.post(
349 349 register_url,
350 350 {
351 351 'username': username,
352 352 'password': password,
353 353 'password_confirmation': password,
354 354 'email': email,
355 355 'firstname': name,
356 356 'lastname': lastname,
357 357 'admin': True
358 358 }
359 359 ) # This should be overriden
360 360 assert response.status == '302 Found'
361 361 assert_session_flash(
362 362 response, 'You have successfully registered with RhodeCode')
363 363
364 364 ret = Session().query(User).filter(
365 365 User.username == 'test_regular4').one()
366 366 assert ret.username == username
367 367 assert check_password(password, ret.password)
368 368 assert ret.email == email
369 369 assert ret.name == name
370 370 assert ret.lastname == lastname
371 371 assert ret.api_key is not None
372 372 assert not ret.admin
373 373
374 374 def test_forgot_password_wrong_mail(self):
375 375 bad_email = 'marcin@wrongmail.org'
376 376 response = self.app.post(
377 377 pwd_reset_url,
378 378 {'email': bad_email, }
379 379 )
380 380
381 381 msg = validators.ValidSystemEmail()._messages['non_existing_email']
382 382 msg = h.html_escape(msg % {'email': bad_email})
383 383 response.mustcontain()
384 384
385 385 def test_forgot_password(self):
386 386 response = self.app.get(pwd_reset_url)
387 387 assert response.status == '200 OK'
388 388
389 389 username = 'test_password_reset_1'
390 390 password = 'qweqwe'
391 391 email = 'marcin@python-works.com'
392 392 name = 'passwd'
393 393 lastname = 'reset'
394 394
395 395 new = User()
396 396 new.username = username
397 397 new.password = password
398 398 new.email = email
399 399 new.name = name
400 400 new.lastname = lastname
401 401 new.api_key = generate_auth_token(username)
402 402 Session().add(new)
403 403 Session().commit()
404 404
405 405 response = self.app.post(pwd_reset_url,
406 406 {'email': email, })
407 407
408 408 assert_session_flash(
409 409 response, 'Your password reset link was sent')
410 410
411 411 response = response.follow()
412 412
413 413 # BAD KEY
414 414
415 415 key = "bad"
416 416 confirm_url = '{}?key={}'.format(pwd_reset_confirm_url, key)
417 417 response = self.app.get(confirm_url)
418 418 assert response.status == '302 Found'
419 419 assert response.location.endswith(pwd_reset_url)
420 420
421 421 # GOOD KEY
422 422
423 423 key = User.get_by_username(username).api_key
424 424 confirm_url = '{}?key={}'.format(pwd_reset_confirm_url, key)
425 425 response = self.app.get(confirm_url)
426 426 assert response.status == '302 Found'
427 427 assert response.location.endswith(login_url)
428 428
429 429 assert_session_flash(
430 430 response,
431 431 'Your password reset was successful, '
432 432 'a new password has been sent to your email')
433 433
434 434 response = response.follow()
435 435
436 436 def _get_api_whitelist(self, values=None):
437 437 config = {'api_access_controllers_whitelist': values or []}
438 438 return config
439 439
440 440 @pytest.mark.parametrize("test_name, auth_token", [
441 441 ('none', None),
442 442 ('empty_string', ''),
443 443 ('fake_number', '123456'),
444 444 ('proper_auth_token', None)
445 445 ])
446 446 def test_access_not_whitelisted_page_via_auth_token(self, test_name,
447 447 auth_token):
448 448 whitelist = self._get_api_whitelist([])
449 449 with mock.patch.dict('rhodecode.CONFIG', whitelist):
450 450 assert [] == whitelist['api_access_controllers_whitelist']
451 451 if test_name == 'proper_auth_token':
452 452 # use builtin if api_key is None
453 453 auth_token = User.get_first_super_admin().api_key
454 454
455 455 with fixture.anon_access(False):
456 456 self.app.get(url(controller='changeset',
457 457 action='changeset_raw',
458 458 repo_name=HG_REPO, revision='tip',
459 459 api_key=auth_token),
460 460 status=302)
461 461
462 462 @pytest.mark.parametrize("test_name, auth_token, code", [
463 463 ('none', None, 302),
464 464 ('empty_string', '', 302),
465 465 ('fake_number', '123456', 302),
466 466 ('proper_auth_token', None, 200)
467 467 ])
468 468 def test_access_whitelisted_page_via_auth_token(self, test_name,
469 469 auth_token, code):
470 470 whitelist = self._get_api_whitelist(
471 471 ['ChangesetController:changeset_raw'])
472 472 with mock.patch.dict('rhodecode.CONFIG', whitelist):
473 473 assert ['ChangesetController:changeset_raw'] == \
474 474 whitelist['api_access_controllers_whitelist']
475 475 if test_name == 'proper_auth_token':
476 476 auth_token = User.get_first_super_admin().api_key
477 477
478 478 with fixture.anon_access(False):
479 479 self.app.get(url(controller='changeset',
480 480 action='changeset_raw',
481 481 repo_name=HG_REPO, revision='tip',
482 482 api_key=auth_token),
483 483 status=code)
484 484
485 485 def test_access_page_via_extra_auth_token(self):
486 486 whitelist = self._get_api_whitelist(
487 487 ['ChangesetController:changeset_raw'])
488 488 with mock.patch.dict('rhodecode.CONFIG', whitelist):
489 489 assert ['ChangesetController:changeset_raw'] == \
490 490 whitelist['api_access_controllers_whitelist']
491 491
492 492 new_auth_token = AuthTokenModel().create(
493 493 TEST_USER_ADMIN_LOGIN, 'test')
494 494 Session().commit()
495 495 with fixture.anon_access(False):
496 496 self.app.get(url(controller='changeset',
497 497 action='changeset_raw',
498 498 repo_name=HG_REPO, revision='tip',
499 499 api_key=new_auth_token.api_key),
500 500 status=200)
501 501
502 502 def test_access_page_via_expired_auth_token(self):
503 503 whitelist = self._get_api_whitelist(
504 504 ['ChangesetController:changeset_raw'])
505 505 with mock.patch.dict('rhodecode.CONFIG', whitelist):
506 506 assert ['ChangesetController:changeset_raw'] == \
507 507 whitelist['api_access_controllers_whitelist']
508 508
509 509 new_auth_token = AuthTokenModel().create(
510 510 TEST_USER_ADMIN_LOGIN, 'test')
511 511 Session().commit()
512 512 # patch the api key and make it expired
513 513 new_auth_token.expires = 0
514 514 Session().add(new_auth_token)
515 515 Session().commit()
516 516 with fixture.anon_access(False):
517 517 self.app.get(url(controller='changeset',
518 518 action='changeset_raw',
519 519 repo_name=HG_REPO, revision='tip',
520 520 api_key=new_auth_token.api_key),
521 521 status=302)
522 522
523 523
524 524 class TestPasswordReset(TestController):
525 525
526 526 @pytest.mark.parametrize(
527 527 'pwd_reset_setting, show_link, show_reset', [
528 528 ('hg.password_reset.enabled', True, True),
529 529 ('hg.password_reset.hidden', False, True),
530 530 ('hg.password_reset.disabled', False, False),
531 531 ])
532 532 def test_password_reset_settings(
533 533 self, pwd_reset_setting, show_link, show_reset):
534 534 clear_all_caches()
535 535 self.log_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
536 536 params = {
537 537 'csrf_token': self.csrf_token,
538 538 'anonymous': 'True',
539 539 'default_register': 'hg.register.auto_activate',
540 540 'default_register_message': '',
541 541 'default_password_reset': pwd_reset_setting,
542 542 'default_extern_activate': 'hg.extern_activate.auto',
543 543 }
544 544 resp = self.app.post(url('admin_permissions_application'), params=params)
545 545 self.logout_user()
546 546
547 547 login_page = self.app.get(login_url)
548 548 asr_login = AssertResponse(login_page)
549 549 index_page = self.app.get(index_url)
550 550 asr_index = AssertResponse(index_page)
551 551
552 552 if show_link:
553 553 asr_login.one_element_exists('a.pwd_reset')
554 554 asr_index.one_element_exists('a.pwd_reset')
555 555 else:
556 556 asr_login.no_element_exists('a.pwd_reset')
557 557 asr_index.no_element_exists('a.pwd_reset')
558 558
559 559 pwdreset_page = self.app.get(pwd_reset_url)
560 560
561 561 asr_reset = AssertResponse(pwdreset_page)
562 562 if show_reset:
563 563 assert 'Send password reset email' in pwdreset_page
564 564 asr_reset.one_element_exists('#email')
565 565 asr_reset.one_element_exists('#send')
566 566 else:
567 assert 'Password reset has been disabled.' in pwdreset_page
567 assert 'Password reset is disabled.' in pwdreset_page
568 568 asr_reset.no_element_exists('#email')
569 569 asr_reset.no_element_exists('#send')
570 570
571 571 def test_password_form_disabled(self):
572 572 self.log_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
573 573 params = {
574 574 'csrf_token': self.csrf_token,
575 575 'anonymous': 'True',
576 576 'default_register': 'hg.register.auto_activate',
577 577 'default_register_message': '',
578 578 'default_password_reset': 'hg.password_reset.disabled',
579 579 'default_extern_activate': 'hg.extern_activate.auto',
580 580 }
581 581 self.app.post(url('admin_permissions_application'), params=params)
582 582 self.logout_user()
583 583
584 584 pwdreset_page = self.app.post(
585 585 pwd_reset_url,
586 586 {'email': 'lisa@rhodecode.com',}
587 587 )
588 assert 'Password reset has been disabled.' in pwdreset_page
588 assert 'Password reset is disabled.' in pwdreset_page
General Comments 0
You need to be logged in to leave comments. Login now