test_login.py
375 lines
| 16.8 KiB
| text/x-python
|
PythonLexer
r728 | # -*- coding: utf-8 -*- | |||
|
r4116 | from __future__ import with_statement | ||
import mock | ||||
r547 | from rhodecode.tests import * | |||
|
r4116 | from rhodecode.tests.fixture import Fixture | ||
r2109 | from rhodecode.lib.utils2 import generate_api_key | |||
r547 | from rhodecode.lib.auth import check_password | |||
r2467 | from rhodecode.lib import helpers as h | |||
|
r4116 | from rhodecode.model.api_key import ApiKeyModel | ||
r2467 | from rhodecode.model import validators | |||
|
r4116 | from rhodecode.model.db import User, Notification | ||
r3797 | from rhodecode.model.meta import Session | |||
r547 | ||||
|
r4116 | fixture = Fixture() | ||
r2109 | ||||
r547 | class TestLoginController(TestController): | |||
r1732 | def tearDown(self): | |||
for n in Notification.query().all(): | ||||
r3797 | Session().delete(n) | |||
r1732 | ||||
r3797 | Session().commit() | |||
r1732 | self.assertEqual(Notification.query().all(), []) | |||
r547 | def test_index(self): | |||
response = self.app.get(url(controller='login', action='index')) | ||||
r1418 | self.assertEqual(response.status, '200 OK') | |||
r547 | # Test response... | |||
def test_login_admin_ok(self): | ||||
response = self.app.post(url(controller='login', action='index'), | ||||
r2467 | {'username': 'test_admin', | |||
'password': 'test12'}) | ||||
r1418 | self.assertEqual(response.status, '302 Found') | |||
r2467 | self.assertEqual(response.session['rhodecode_user'].get('username'), | |||
r1418 | 'test_admin') | |||
r547 | response = response.follow() | |||
r3630 | response.mustcontain('/%s' % HG_REPO) | |||
r659 | ||||
r547 | def test_login_regular_ok(self): | |||
response = self.app.post(url(controller='login', action='index'), | ||||
r2467 | {'username': 'test_regular', | |||
'password': 'test12'}) | ||||
r1418 | ||||
self.assertEqual(response.status, '302 Found') | ||||
r2467 | self.assertEqual(response.session['rhodecode_user'].get('username'), | |||
r1418 | 'test_regular') | |||
r547 | response = response.follow() | |||
r3630 | response.mustcontain('/%s' % HG_REPO) | |||
r659 | ||||
r547 | def test_login_ok_came_from(self): | |||
test_came_from = '/_admin/users' | ||||
r1418 | response = self.app.post(url(controller='login', action='index', | |||
came_from=test_came_from), | ||||
r2467 | {'username': 'test_admin', | |||
'password': 'test12'}) | ||||
r1418 | self.assertEqual(response.status, '302 Found') | |||
r547 | response = response.follow() | |||
r659 | ||||
r1418 | self.assertEqual(response.status, '200 OK') | |||
r3630 | response.mustcontain('Users administration') | |||
r659 | ||||
r2679 | @parameterized.expand([ | |||
('data:text/html,<script>window.alert("xss")</script>',), | ||||
('mailto:test@rhodecode.org',), | ||||
('file:///etc/passwd',), | ||||
('ftp://some.ftp.server',), | ||||
('http://other.domain',), | ||||
]) | ||||
def test_login_bad_came_froms(self, url_came_from): | ||||
response = self.app.post(url(controller='login', action='index', | ||||
came_from=url_came_from), | ||||
{'username': 'test_admin', | ||||
'password': 'test12'}) | ||||
self.assertEqual(response.status, '302 Found') | ||||
self.assertEqual(response._environ['paste.testing_variables'] | ||||
['tmpl_context'].came_from, '/') | ||||
response = response.follow() | ||||
self.assertEqual(response.status, '200 OK') | ||||
r547 | def test_login_short_password(self): | |||
response = self.app.post(url(controller='login', action='index'), | ||||
r2467 | {'username': 'test_admin', | |||
'password': 'as'}) | ||||
r1366 | self.assertEqual(response.status, '200 OK') | |||
r1418 | ||||
r3630 | response.mustcontain('Enter 3 characters or more') | |||
r547 | ||||
def test_login_wrong_username_password(self): | ||||
response = self.app.post(url(controller='login', action='index'), | ||||
r2467 | {'username': 'error', | |||
'password': 'test12'}) | ||||
r659 | ||||
r3630 | response.mustcontain('invalid user name') | |||
response.mustcontain('invalid password') | ||||
r659 | ||||
r723 | #========================================================================== | |||
# REGISTRATIONS | ||||
#========================================================================== | ||||
r547 | def test_register(self): | |||
response = self.app.get(url(controller='login', action='register')) | ||||
|
r4116 | response.mustcontain('Sign Up') | ||
r659 | ||||
r547 | def test_register_err_same_username(self): | |||
r2467 | uname = 'test_admin' | |||
r547 | response = self.app.post(url(controller='login', action='register'), | |||
r2467 | {'username': uname, | |||
'password': 'test12', | ||||
'password_confirmation': 'test12', | ||||
'email': 'goodmail@domain.com', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
r659 | ||||
r2467 | msg = validators.ValidUsername()._messages['username_exists'] | |||
msg = h.html_escape(msg % {'username': uname}) | ||||
response.mustcontain(msg) | ||||
r659 | ||||
r745 | def test_register_err_same_email(self): | |||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'test_admin_0', | |||
'password': 'test12', | ||||
'password_confirmation': 'test12', | ||||
'email': 'test_admin@mail.com', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
r745 | ||||
r2467 | msg = validators.UniqSystemEmail()()._messages['email_taken'] | |||
response.mustcontain(msg) | ||||
r745 | ||||
def test_register_err_same_email_case_sensitive(self): | ||||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'test_admin_1', | |||
'password': 'test12', | ||||
'password_confirmation': 'test12', | ||||
'email': 'TesT_Admin@mail.COM', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
msg = validators.UniqSystemEmail()()._messages['email_taken'] | ||||
response.mustcontain(msg) | ||||
r745 | ||||
r547 | def test_register_err_wrong_data(self): | |||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'xs', | |||
'password': 'test', | ||||
'password_confirmation': 'test', | ||||
'email': 'goodmailm', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
self.assertEqual(response.status, '200 OK') | ||||
r2248 | response.mustcontain('An email address must contain a single @') | |||
response.mustcontain('Enter a value 6 characters long or more') | ||||
r659 | ||||
r745 | def test_register_err_username(self): | |||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'error user', | |||
'password': 'test12', | ||||
'password_confirmation': 'test12', | ||||
'email': 'goodmailm', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
r745 | ||||
r2248 | response.mustcontain('An email address must contain a single @') | |||
response.mustcontain('Username may only contain ' | ||||
r1021 | 'alphanumeric characters underscores, ' | |||
'periods or dashes and must begin with ' | ||||
r2248 | 'alphanumeric character') | |||
r745 | ||||
def test_register_err_case_sensitive(self): | ||||
r2467 | usr = 'Test_Admin' | |||
r745 | response = self.app.post(url(controller='login', action='register'), | |||
r2467 | {'username': usr, | |||
'password': 'test12', | ||||
'password_confirmation': 'test12', | ||||
'email': 'goodmailm', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
r745 | ||||
r2467 | response.mustcontain('An email address must contain a single @') | |||
msg = validators.ValidUsername()._messages['username_exists'] | ||||
msg = h.html_escape(msg % {'username': usr}) | ||||
response.mustcontain(msg) | ||||
r745 | ||||
r723 | def test_register_special_chars(self): | |||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'xxxaxn', | |||
'password': 'ąćźżąśśśś', | ||||
'password_confirmation': 'ąćźżąśśśś', | ||||
'email': 'goodmailm@test.plx', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
r723 | ||||
r2467 | msg = validators.ValidPassword()._messages['invalid_password'] | |||
response.mustcontain(msg) | ||||
r723 | ||||
def test_register_password_mismatch(self): | ||||
response = self.app.post(url(controller='login', action='register'), | ||||
r2467 | {'username': 'xs', | |||
'password': '123qwe', | ||||
'password_confirmation': 'qwe123', | ||||
'email': 'goodmailm@test.plxa', | ||||
r2595 | 'firstname': 'test', | |||
r2467 | 'lastname': 'test'}) | |||
msg = validators.ValidPasswordsMatch()._messages['password_mismatch'] | ||||
response.mustcontain(msg) | ||||
r659 | ||||
r547 | def test_register_ok(self): | |||
username = 'test_regular4' | ||||
password = 'qweqwe' | ||||
email = 'marcin@test.com' | ||||
name = 'testname' | ||||
lastname = 'testlastname' | ||||
r659 | ||||
r547 | response = self.app.post(url(controller='login', action='register'), | |||
r2467 | {'username': username, | |||
'password': password, | ||||
'password_confirmation': password, | ||||
'email': email, | ||||
r2595 | 'firstname': name, | |||
r2467 | 'lastname': lastname, | |||
'admin': True}) # This should be overriden | ||||
r2248 | self.assertEqual(response.status, '302 Found') | |||
r3377 | self.checkSessionFlash(response, 'You have successfully registered into RhodeCode') | |||
r659 | ||||
r3797 | ret = Session().query(User).filter(User.username == 'test_regular4').one() | |||
r2248 | self.assertEqual(ret.username, username) | |||
self.assertEqual(check_password(password, ret.password), True) | ||||
self.assertEqual(ret.email, email) | ||||
self.assertEqual(ret.name, name) | ||||
self.assertEqual(ret.lastname, lastname) | ||||
self.assertNotEqual(ret.api_key, None) | ||||
self.assertEqual(ret.admin, False) | ||||
r659 | ||||
def test_forgot_password_wrong_mail(self): | ||||
r2467 | bad_email = 'marcin@wrongmail.org' | |||
r2248 | response = self.app.post( | |||
url(controller='login', action='password_reset'), | ||||
r2467 | {'email': bad_email, } | |||
r2248 | ) | |||
r659 | ||||
r2467 | msg = validators.ValidSystemEmail()._messages['non_existing_email'] | |||
msg = h.html_escape(msg % {'email': bad_email}) | ||||
response.mustcontain() | ||||
r659 | ||||
r547 | def test_forgot_password(self): | |||
r1418 | response = self.app.get(url(controller='login', | |||
action='password_reset')) | ||||
r2248 | self.assertEqual(response.status, '200 OK') | |||
r547 | ||||
username = 'test_password_reset_1' | ||||
password = 'qweqwe' | ||||
email = 'marcin@python-works.com' | ||||
name = 'passwd' | ||||
lastname = 'reset' | ||||
r659 | ||||
r1418 | new = User() | |||
new.username = username | ||||
new.password = password | ||||
new.email = email | ||||
new.name = name | ||||
new.lastname = lastname | ||||
new.api_key = generate_api_key(username) | ||||
r3797 | Session().add(new) | |||
Session().commit() | ||||
r1418 | ||||
response = self.app.post(url(controller='login', | ||||
action='password_reset'), | ||||
r2467 | {'email': email, }) | |||
r1418 | ||||
self.checkSessionFlash(response, 'Your password reset link was sent') | ||||
response = response.follow() | ||||
# BAD KEY | ||||
key = "bad" | ||||
response = self.app.get(url(controller='login', | ||||
action='password_reset_confirmation', | ||||
key=key)) | ||||
self.assertEqual(response.status, '302 Found') | ||||
self.assertTrue(response.location.endswith(url('reset_password'))) | ||||
# GOOD KEY | ||||
r1530 | key = User.get_by_username(username).api_key | |||
r1418 | response = self.app.get(url(controller='login', | |||
action='password_reset_confirmation', | ||||
key=key)) | ||||
self.assertEqual(response.status, '302 Found') | ||||
self.assertTrue(response.location.endswith(url('login_home'))) | ||||
self.checkSessionFlash(response, | ||||
('Your password reset was successful, ' | ||||
'new password has been sent to your email')) | ||||
response = response.follow() | ||||
|
r4116 | |||
def _get_api_whitelist(self, values=None): | ||||
config = {'api_access_controllers_whitelist': values or []} | ||||
return config | ||||
@parameterized.expand([ | ||||
('none', None), | ||||
('empty_string', ''), | ||||
('fake_number', '123456'), | ||||
('proper_api_key', None) | ||||
]) | ||||
def test_access_not_whitelisted_page_via_api_key(self, test_name, api_key): | ||||
whitelist = self._get_api_whitelist([]) | ||||
with mock.patch('rhodecode.CONFIG', whitelist): | ||||
self.assertEqual([], | ||||
whitelist['api_access_controllers_whitelist']) | ||||
if test_name == 'proper_api_key': | ||||
#use builtin if api_key is None | ||||
api_key = User.get_first_admin().api_key | ||||
with fixture.anon_access(False): | ||||
self.app.get(url(controller='changeset', | ||||
action='changeset_raw', | ||||
repo_name=HG_REPO, revision='tip', api_key=api_key), | ||||
status=302) | ||||
@parameterized.expand([ | ||||
('none', None, 302), | ||||
('empty_string', '', 302), | ||||
('fake_number', '123456', 302), | ||||
('proper_api_key', None, 200) | ||||
]) | ||||
def test_access_whitelisted_page_via_api_key(self, test_name, api_key, code): | ||||
whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw']) | ||||
with mock.patch('rhodecode.CONFIG', whitelist): | ||||
self.assertEqual(['ChangesetController:changeset_raw'], | ||||
whitelist['api_access_controllers_whitelist']) | ||||
if test_name == 'proper_api_key': | ||||
api_key = User.get_first_admin().api_key | ||||
with fixture.anon_access(False): | ||||
self.app.get(url(controller='changeset', | ||||
action='changeset_raw', | ||||
repo_name=HG_REPO, revision='tip', api_key=api_key), | ||||
status=code) | ||||
def test_access_page_via_extra_api_key(self): | ||||
whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw']) | ||||
with mock.patch('rhodecode.CONFIG', whitelist): | ||||
self.assertEqual(['ChangesetController:changeset_raw'], | ||||
whitelist['api_access_controllers_whitelist']) | ||||
new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, 'test') | ||||
Session().commit() | ||||
with fixture.anon_access(False): | ||||
self.app.get(url(controller='changeset', | ||||
action='changeset_raw', | ||||
repo_name=HG_REPO, revision='tip', api_key=new_api_key.api_key), | ||||
status=200) | ||||
def test_access_page_via_expired_api_key(self): | ||||
whitelist = self._get_api_whitelist(['ChangesetController:changeset_raw']) | ||||
with mock.patch('rhodecode.CONFIG', whitelist): | ||||
self.assertEqual(['ChangesetController:changeset_raw'], | ||||
whitelist['api_access_controllers_whitelist']) | ||||
new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, 'test') | ||||
Session().commit() | ||||
#patch the api key and make it expired | ||||
new_api_key.expires = 0 | ||||
Session().add(new_api_key) | ||||
Session().commit() | ||||
with fixture.anon_access(False): | ||||
self.app.get(url(controller='changeset', | ||||
action='changeset_raw', | ||||
repo_name=HG_REPO, revision='tip', | ||||
api_key=new_api_key.api_key), | ||||
status=302) | ||||