# -*- coding: utf-8 -*- from __future__ import with_statement import mock from rhodecode.tests import * from rhodecode.tests.fixture import Fixture from rhodecode.lib.utils2 import generate_api_key from rhodecode.lib.auth import check_password from rhodecode.lib import helpers as h from rhodecode.model.api_key import ApiKeyModel from rhodecode.model import validators from rhodecode.model.db import User, Notification from rhodecode.model.meta import Session fixture = Fixture() class TestLoginController(TestController): def tearDown(self): for n in Notification.query().all(): Session().delete(n) Session().commit() self.assertEqual(Notification.query().all(), []) def test_index(self): response = self.app.get(url(controller='login', action='index')) self.assertEqual(response.status, '200 OK') # Test response... def test_login_admin_ok(self): response = self.app.post(url(controller='login', action='index'), {'username': 'test_admin', 'password': 'test12'}) self.assertEqual(response.status, '302 Found') self.assertEqual(response.session['rhodecode_user'].get('username'), 'test_admin') response = response.follow() response.mustcontain('/%s' % HG_REPO) def test_login_regular_ok(self): response = self.app.post(url(controller='login', action='index'), {'username': 'test_regular', 'password': 'test12'}) self.assertEqual(response.status, '302 Found') self.assertEqual(response.session['rhodecode_user'].get('username'), 'test_regular') response = response.follow() response.mustcontain('/%s' % HG_REPO) def test_login_ok_came_from(self): test_came_from = '/_admin/users' response = self.app.post(url(controller='login', action='index', came_from=test_came_from), {'username': 'test_admin', 'password': 'test12'}) self.assertEqual(response.status, '302 Found') response = response.follow() self.assertEqual(response.status, '200 OK') response.mustcontain('Users administration') @parameterized.expand([ ('data:text/html,',), ('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') def test_login_short_password(self): response = self.app.post(url(controller='login', action='index'), {'username': 'test_admin', 'password': 'as'}) self.assertEqual(response.status, '200 OK') response.mustcontain('Enter 3 characters or more') def test_login_wrong_username_password(self): response = self.app.post(url(controller='login', action='index'), {'username': 'error', 'password': 'test12'}) response.mustcontain('invalid user name') response.mustcontain('invalid password') #========================================================================== # REGISTRATIONS #========================================================================== def test_register(self): response = self.app.get(url(controller='login', action='register')) response.mustcontain('Sign Up') def test_register_err_same_username(self): uname = 'test_admin' response = self.app.post(url(controller='login', action='register'), {'username': uname, 'password': 'test12', 'password_confirmation': 'test12', 'email': 'goodmail@domain.com', 'firstname': 'test', 'lastname': 'test'}) msg = validators.ValidUsername()._messages['username_exists'] msg = h.html_escape(msg % {'username': uname}) response.mustcontain(msg) def test_register_err_same_email(self): response = self.app.post(url(controller='login', action='register'), {'username': 'test_admin_0', 'password': 'test12', 'password_confirmation': 'test12', 'email': 'test_admin@mail.com', 'firstname': 'test', 'lastname': 'test'}) msg = validators.UniqSystemEmail()()._messages['email_taken'] response.mustcontain(msg) def test_register_err_same_email_case_sensitive(self): response = self.app.post(url(controller='login', action='register'), {'username': 'test_admin_1', 'password': 'test12', 'password_confirmation': 'test12', 'email': 'TesT_Admin@mail.COM', 'firstname': 'test', 'lastname': 'test'}) msg = validators.UniqSystemEmail()()._messages['email_taken'] response.mustcontain(msg) def test_register_err_wrong_data(self): response = self.app.post(url(controller='login', action='register'), {'username': 'xs', 'password': 'test', 'password_confirmation': 'test', 'email': 'goodmailm', 'firstname': 'test', 'lastname': 'test'}) self.assertEqual(response.status, '200 OK') response.mustcontain('An email address must contain a single @') response.mustcontain('Enter a value 6 characters long or more') def test_register_err_username(self): response = self.app.post(url(controller='login', action='register'), {'username': 'error user', 'password': 'test12', 'password_confirmation': 'test12', 'email': 'goodmailm', 'firstname': 'test', 'lastname': 'test'}) response.mustcontain('An email address must contain a single @') response.mustcontain('Username may only contain ' 'alphanumeric characters underscores, ' 'periods or dashes and must begin with ' 'alphanumeric character') def test_register_err_case_sensitive(self): usr = 'Test_Admin' response = self.app.post(url(controller='login', action='register'), {'username': usr, 'password': 'test12', 'password_confirmation': 'test12', 'email': 'goodmailm', 'firstname': 'test', 'lastname': 'test'}) 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) def test_register_special_chars(self): response = self.app.post(url(controller='login', action='register'), {'username': 'xxxaxn', 'password': 'ąćźżąśśśś', 'password_confirmation': 'ąćźżąśśśś', 'email': 'goodmailm@test.plx', 'firstname': 'test', 'lastname': 'test'}) msg = validators.ValidPassword()._messages['invalid_password'] response.mustcontain(msg) def test_register_password_mismatch(self): response = self.app.post(url(controller='login', action='register'), {'username': 'xs', 'password': '123qwe', 'password_confirmation': 'qwe123', 'email': 'goodmailm@test.plxa', 'firstname': 'test', 'lastname': 'test'}) msg = validators.ValidPasswordsMatch()._messages['password_mismatch'] response.mustcontain(msg) def test_register_ok(self): username = 'test_regular4' password = 'qweqwe' email = 'marcin@test.com' name = 'testname' lastname = 'testlastname' response = self.app.post(url(controller='login', action='register'), {'username': username, 'password': password, 'password_confirmation': password, 'email': email, 'firstname': name, 'lastname': lastname, 'admin': True}) # This should be overriden self.assertEqual(response.status, '302 Found') self.checkSessionFlash(response, 'You have successfully registered into RhodeCode') ret = Session().query(User).filter(User.username == 'test_regular4').one() 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) def test_forgot_password_wrong_mail(self): bad_email = 'marcin@wrongmail.org' response = self.app.post( url(controller='login', action='password_reset'), {'email': bad_email, } ) msg = validators.ValidSystemEmail()._messages['non_existing_email'] msg = h.html_escape(msg % {'email': bad_email}) response.mustcontain() def test_forgot_password(self): response = self.app.get(url(controller='login', action='password_reset')) self.assertEqual(response.status, '200 OK') username = 'test_password_reset_1' password = 'qweqwe' email = 'marcin@python-works.com' name = 'passwd' lastname = 'reset' new = User() new.username = username new.password = password new.email = email new.name = name new.lastname = lastname new.api_key = generate_api_key(username) Session().add(new) Session().commit() response = self.app.post(url(controller='login', action='password_reset'), {'email': email, }) 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 key = User.get_by_username(username).api_key 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() 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)