diff --git a/rhodecode/lib/helpers.py b/rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py +++ b/rhodecode/lib/helpers.py @@ -51,6 +51,20 @@ from rhodecode.model.db import URL_SEP log = logging.getLogger(__name__) +html_escape_table = { + "&": "&", + '"': """, + "'": "'", + ">": ">", + "<": "<", +} + + +def html_escape(text): + """Produce entities within text.""" + return "".join(html_escape_table.get(c,c) for c in text) + + def shorter(text, size=20): postfix = '...' if len(text) > size: diff --git a/rhodecode/model/validators.py b/rhodecode/model/validators.py new file mode 100644 --- /dev/null +++ b/rhodecode/model/validators.py @@ -0,0 +1,592 @@ +""" +Set of generic validators +""" +import os +import re +import formencode +import logging +from pylons.i18n.translation import _ +from webhelpers.pylonslib.secure_form import authentication_token + +from formencode.validators import ( + UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set +) + +from rhodecode.lib.utils import repo_name_slug +from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User +from rhodecode.lib.auth import authenticate +from rhodecode.lib.exceptions import LdapImportError +from rhodecode.config.routing import ADMIN_PREFIX +# silence warnings and pylint +UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set + +log = logging.getLogger(__name__) + + +class StateObj(object): + """ + this is needed to translate the messages using _() in validators + """ + _ = staticmethod(_) + + +def M(self, key, state=None, **kwargs): + """ + returns string from self.message based on given key, + passed kw params are used to substitute %(named)s params inside + translated strings + + :param msg: + :param state: + """ + if state is None: + state = StateObj() + else: + state._ = staticmethod(_) + #inject validator into state object + return self.message(key, state, **kwargs) + + +def ValidUsername(edit=False, old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'username_exists': _(u'Username "%(username)s" already exists'), + 'system_invalid_username': + _(u'Username "%(username)s" is forbidden'), + 'invalid_username': + _(u'Username may only contain alphanumeric characters ' + 'underscores, periods or dashes and must begin with ' + 'alphanumeric character') + } + + def validate_python(self, value, state): + if value in ['default', 'new_user']: + msg = M(self, 'system_invalid_username', state, username=value) + raise formencode.Invalid(msg, value, state) + #check if user is unique + old_un = None + if edit: + old_un = User.get(old_data.get('user_id')).username + + if old_un != value or not edit: + if User.get_by_username(value, case_insensitive=True): + msg = M(self, 'username_exists', state, username=value) + raise formencode.Invalid(msg, value, state) + + if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: + msg = M(self, 'invalid_username', state) + raise formencode.Invalid(msg, value, state) + return _validator + + +def ValidRepoUser(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_username': _(u'Username %(username)s is not valid') + } + + def validate_python(self, value, state): + try: + User.query().filter(User.active == True)\ + .filter(User.username == value).one() + except Exception: + msg = M(self, 'invalid_username', state, username=value) + raise formencode.Invalid(msg, value, state, + error_dict=dict(username=msg) + ) + + return _validator + + +def ValidUsersGroup(edit=False, old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_group': _(u'Invalid users group name'), + 'group_exist': _(u'Users group "%(usersgroup)s" already exists'), + 'invalid_usersgroup_name': + _(u'users group name may only contain alphanumeric ' + 'characters underscores, periods or dashes and must begin ' + 'with alphanumeric character') + } + + def validate_python(self, value, state): + if value in ['default']: + msg = M(self, 'invalid_group', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(users_group_name=msg) + ) + #check if group is unique + old_ugname = None + if edit: + old_id = old_data.get('users_group_id') + old_ugname = UsersGroup.get(old_id).users_group_name + + if old_ugname != value or not edit: + is_existing_group = UsersGroup.get_by_group_name(value, + case_insensitive=True) + if is_existing_group: + msg = M(self, 'group_exist', state, usersgroup=value) + raise formencode.Invalid(msg, value, state, + error_dict=dict(users_group_name=msg) + ) + + if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: + msg = M(self, 'invalid_usersgroup_name', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(users_group_name=msg) + ) + + return _validator + + +def ValidReposGroup(edit=False, old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'group_parent_id': _(u'Cannot assign this group as parent'), + 'group_exists': _(u'Group "%(group_name)s" already exists'), + 'repo_exists': + _(u'Repository with name "%(group_name)s" already exists') + } + + def validate_python(self, value, state): + # TODO WRITE VALIDATIONS + group_name = value.get('group_name') + group_parent_id = value.get('group_parent_id') + + # slugify repo group just in case :) + slug = repo_name_slug(group_name) + + # check for parent of self + parent_of_self = lambda: ( + old_data['group_id'] == int(group_parent_id) + if group_parent_id else False + ) + if edit and parent_of_self(): + msg = M(self, 'group_parent_id', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(group_parent_id=msg) + ) + + old_gname = None + if edit: + old_gname = RepoGroup.get(old_data.get('group_id')).group_name + + if old_gname != group_name or not edit: + + # check group + gr = RepoGroup.query()\ + .filter(RepoGroup.group_name == slug)\ + .filter(RepoGroup.group_parent_id == group_parent_id)\ + .scalar() + + if gr: + msg = M(self, 'group_exists', state, group_name=slug) + raise formencode.Invalid(msg, value, state, + error_dict=dict(group_name=msg) + ) + + # check for same repo + repo = Repository.query()\ + .filter(Repository.repo_name == slug)\ + .scalar() + + if repo: + msg = M(self, 'repo_exists', state, group_name=slug) + raise formencode.Invalid(msg, value, state, + error_dict=dict(group_name=msg) + ) + + return _validator + + +def ValidPassword(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_password': + _(u'Invalid characters (non-ascii) in password') + } + + def validate_python(self, value, state): + try: + (value or '').decode('ascii') + except UnicodeError: + msg = M(self, 'invalid_password', state) + raise formencode.Invalid(msg, value, state,) + return _validator + + +def ValidPasswordsMatch(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'password_mismatch': _(u'Passwords do not match'), + } + + def validate_python(self, value, state): + + pass_val = value.get('password') or value.get('new_password') + if pass_val != value['password_confirmation']: + msg = M(self, 'password_mismatch', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(password_confirmation=msg) + ) + return _validator + + +def ValidAuth(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_password': _(u'invalid password'), + 'invalid_username': _(u'invalid user name'), + 'disabled_account': _(u'Your account is disabled') + } + + def validate_python(self, value, state): + password = value['password'] + username = value['username'] + + if not authenticate(username, password): + user = User.get_by_username(username) + if user and user.active is False: + log.warning('user %s is disabled' % username) + msg = M(self, 'disabled_account', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(username=msg) + ) + else: + log.warning('user %s failed to authenticate' % username) + msg = M(self, 'invalid_username', state) + msg2 = M(self, 'invalid_password', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(username=msg, password=msg2) + ) + return _validator + + +def ValidAuthToken(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_token': _(u'Token mismatch') + } + + def validate_python(self, value, state): + if value != authentication_token(): + msg = M(self, 'invalid_token', state) + raise formencode.Invalid(msg, value, state) + return _validator + + +def ValidRepoName(edit=False, old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_repo_name': + _(u'Repository name %(repo)s is disallowed'), + 'repository_exists': + _(u'Repository named %(repo)s already exists'), + 'repository_in_group_exists': _(u'Repository "%(repo)s" already ' + 'exists in group "%(group)s"'), + 'same_group_exists': _(u'Repositories group with name "%(repo)s" ' + 'already exists') + } + + def _to_python(self, value, state): + repo_name = repo_name_slug(value.get('repo_name', '')) + repo_group = value.get('repo_group') + if repo_group: + gr = RepoGroup.get(repo_group) + group_path = gr.full_path + group_name = gr.group_name + # value needs to be aware of group name in order to check + # db key This is an actual just the name to store in the + # database + repo_name_full = group_path + RepoGroup.url_sep() + repo_name + else: + group_name = group_path = '' + repo_name_full = repo_name + + value['repo_name'] = repo_name + value['repo_name_full'] = repo_name_full + value['group_path'] = group_path + value['group_name'] = group_name + return value + + def validate_python(self, value, state): + + repo_name = value.get('repo_name') + repo_name_full = value.get('repo_name_full') + group_path = value.get('group_path') + group_name = value.get('group_name') + + if repo_name in [ADMIN_PREFIX, '']: + msg = M(self, 'invalid_repo_name', state, repo=repo_name) + raise formencode.Invalid(msg, value, state, + error_dict=dict(repo_name=msg) + ) + + rename = old_data.get('repo_name') != repo_name_full + create = not edit + if rename or create: + + if group_path != '': + if Repository.get_by_repo_name(repo_name_full): + msg = M(self, 'repository_in_group_exists', state, + repo=repo_name, group=group_name) + raise formencode.Invalid(msg, value, state, + error_dict=dict(repo_name=msg) + ) + elif RepoGroup.get_by_group_name(repo_name_full): + msg = M(self, 'same_group_exists', state, + repo=repo_name) + raise formencode.Invalid(msg, value, state, + error_dict=dict(repo_name=msg) + ) + + elif Repository.get_by_repo_name(repo_name_full): + msg = M(self, 'repository_exists', state, + repo=repo_name) + raise formencode.Invalid(msg, value, state, + error_dict=dict(repo_name=msg) + ) + return value + return _validator + + +def ValidForkName(*args, **kwargs): + return ValidRepoName(*args, **kwargs) + + +def SlugifyName(): + class _validator(formencode.validators.FancyValidator): + + def _to_python(self, value, state): + return repo_name_slug(value) + + def validate_python(self, value, state): + pass + + return _validator + + +def ValidCloneUri(): + from rhodecode.lib.utils import make_ui + + def url_handler(repo_type, url, proto, ui=None): + if repo_type == 'hg': + from mercurial.httprepo import httprepository, httpsrepository + if proto == 'https': + httpsrepository(make_ui('db'), url).capabilities + elif proto == 'http': + httprepository(make_ui('db'), url).capabilities + elif repo_type == 'git': + #TODO: write a git url validator + pass + + class _validator(formencode.validators.FancyValidator): + messages = { + 'clone_uri': _(u'invalid clone url'), + 'invalid_clone_uri': _(u'Invalid clone url, provide a ' + 'valid clone http\s url') + } + + def validate_python(self, value, state): + repo_type = value.get('repo_type') + url = value.get('clone_uri') + + if not url: + pass + elif url.startswith('https') or url.startswith('http'): + _type = 'https' if url.startswith('https') else 'http' + try: + url_handler(repo_type, url, _type, make_ui('db')) + except Exception: + log.exception('Url validation failed') + msg = M(self, 'clone_uri') + raise formencode.Invalid(msg, value, state, + error_dict=dict(clone_uri=msg) + ) + else: + msg = M(self, 'invalid_clone_uri', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(clone_uri=msg) + ) + return _validator + + +def ValidForkType(old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_fork_type': _(u'Fork have to be the same type as parent') + } + + def validate_python(self, value, state): + if old_data['repo_type'] != value: + msg = M(self, 'invalid_fork_type', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(repo_type=msg) + ) + return _validator + + +def ValidPerms(type_='repo'): + if type_ == 'group': + EMPTY_PERM = 'group.none' + elif type_ == 'repo': + EMPTY_PERM = 'repository.none' + + class _validator(formencode.validators.FancyValidator): + messages = { + 'perm_new_member_name': + _(u'This username or users group name is not valid') + } + + def to_python(self, value, state): + perms_update = [] + perms_new = [] + # build a list of permission to update and new permission to create + for k, v in value.items(): + # means new added member to permissions + if k.startswith('perm_new_member'): + new_perm = value.get('perm_new_member', False) + new_member = value.get('perm_new_member_name', False) + new_type = value.get('perm_new_member_type') + + if new_member and new_perm: + if (new_member, new_perm, new_type) not in perms_new: + perms_new.append((new_member, new_perm, new_type)) + elif k.startswith('u_perm_') or k.startswith('g_perm_'): + member = k[7:] + t = {'u': 'user', + 'g': 'users_group' + }[k[0]] + if member == 'default': + if value.get('private'): + # set none for default when updating to + # private repo + v = EMPTY_PERM + perms_update.append((member, v, t)) + + value['perms_updates'] = perms_update + value['perms_new'] = perms_new + + # update permissions + for k, v, t in perms_new: + try: + if t is 'user': + self.user_db = User.query()\ + .filter(User.active == True)\ + .filter(User.username == k).one() + if t is 'users_group': + self.user_db = UsersGroup.query()\ + .filter(UsersGroup.users_group_active == True)\ + .filter(UsersGroup.users_group_name == k).one() + + except Exception: + log.exception('Updated permission failed') + msg = M(self, 'perm_new_member_type', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(perm_new_member_name=msg) + ) + return value + return _validator + + +def ValidSettings(): + class _validator(formencode.validators.FancyValidator): + def _to_python(self, value, state): + # settings form can't edit user + if 'user' in value: + del value['user'] + return value + + def validate_python(self, value, state): + pass + return _validator + + +def ValidPath(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_path': _(u'This is not a valid path') + } + + def validate_python(self, value, state): + if not os.path.isdir(value): + msg = M(self, 'invalid_path', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(paths_root_path=msg) + ) + return _validator + + +def UniqSystemEmail(old_data={}): + class _validator(formencode.validators.FancyValidator): + messages = { + 'email_taken': _(u'This e-mail address is already taken') + } + + def _to_python(self, value, state): + return value.lower() + + def validate_python(self, value, state): + if (old_data.get('email') or '').lower() != value: + user = User.get_by_email(value, case_insensitive=True) + if user: + msg = M(self, 'email_taken', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(email=msg) + ) + return _validator + + +def ValidSystemEmail(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'non_existing_email': _(u'e-mail "%(email)s" does not exist.') + } + + def _to_python(self, value, state): + return value.lower() + + def validate_python(self, value, state): + user = User.get_by_email(value, case_insensitive=True) + if user is None: + msg = M(self, 'non_existing_email', state, email=value) + raise formencode.Invalid(msg, value, state, + error_dict=dict(email=msg) + ) + + return _validator + + +def LdapLibValidator(): + class _validator(formencode.validators.FancyValidator): + messages = { + + } + + def validate_python(self, value, state): + try: + import ldap + ldap # pyflakes silence ! + except ImportError: + raise LdapImportError() + + return _validator + + +def AttrLoginValidator(): + class _validator(formencode.validators.FancyValidator): + messages = { + 'invalid_cn': + _(u'The LDAP Login attribute of the CN must be specified - ' + 'this is the name of the attribute that is equivalent ' + 'to "username"') + } + + def validate_python(self, value, state): + if not value or not isinstance(value, (str, unicode)): + msg = M(self, 'invalid_cn', state) + raise formencode.Invalid(msg, value, state, + error_dict=dict(ldap_attr_login=msg) + ) + + return _validator diff --git a/rhodecode/tests/__init__.py b/rhodecode/tests/__init__.py --- a/rhodecode/tests/__init__.py +++ b/rhodecode/tests/__init__.py @@ -27,7 +27,8 @@ from webtest import TestApp from rhodecode import is_windows from rhodecode.model.meta import Session from rhodecode.model.db import User - +from rhodecode.tests.nose_parametrized import parameterized + import pylons.test @@ -38,9 +39,9 @@ if not is_windows: log = logging.getLogger(__name__) __all__ = [ - 'environ', 'url', 'get_new_dir', 'TestController', 'TESTS_TMP_PATH', - 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', - 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_REGULAR_LOGIN', + 'parameterized', 'environ', 'url', 'get_new_dir', 'TestController', + 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', + 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS', 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN', 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO', 'TEST_HG_REPO_CLONE', @@ -54,6 +55,7 @@ log = logging.getLogger(__name__) ##RUNNING DESIRED TESTS # nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account # nosetests --pdb --pdb-failures +# nosetests --with-coverage --cover-package=rhodecode.model.validators rhodecode.tests.test_validators environ = {} #SOME GLOBALS FOR TESTS diff --git a/rhodecode/tests/test_validators.py b/rhodecode/tests/test_validators.py new file mode 100644 --- /dev/null +++ b/rhodecode/tests/test_validators.py @@ -0,0 +1,222 @@ +# -*- coding: utf-8 -*- +import unittest +import formencode + +from rhodecode.tests import * + +from rhodecode.model import validators as v +from rhodecode.model.users_group import UsersGroupModel + +from rhodecode.model.meta import Session +from rhodecode.model.repos_group import ReposGroupModel +from rhodecode.config.routing import ADMIN_PREFIX + + +class TestReposGroups(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_Message_extractor(self): + validator = v.ValidUsername() + self.assertRaises(formencode.Invalid, validator.to_python, 'default') + + class StateObj(object): + pass + + self.assertRaises(formencode.Invalid, + validator.to_python, 'default', StateObj) + + def test_ValidUsername(self): + validator = v.ValidUsername() + + self.assertRaises(formencode.Invalid, validator.to_python, 'default') + self.assertRaises(formencode.Invalid, validator.to_python, 'new_user') + self.assertRaises(formencode.Invalid, validator.to_python, '.,') + self.assertRaises(formencode.Invalid, validator.to_python, + TEST_USER_ADMIN_LOGIN) + self.assertEqual('test', validator.to_python('test')) + + validator = v.ValidUsername(edit=True, old_data={'user_id': 1}) + + def test_ValidRepoUser(self): + validator = v.ValidRepoUser() + self.assertRaises(formencode.Invalid, validator.to_python, 'nouser') + self.assertEqual(TEST_USER_ADMIN_LOGIN, + validator.to_python(TEST_USER_ADMIN_LOGIN)) + + def test_ValidUsersGroup(self): + validator = v.ValidUsersGroup() + self.assertRaises(formencode.Invalid, validator.to_python, 'default') + self.assertRaises(formencode.Invalid, validator.to_python, '.,') + + gr = UsersGroupModel().create('test') + gr2 = UsersGroupModel().create('tes2') + Session.commit() + self.assertRaises(formencode.Invalid, validator.to_python, 'test') + assert gr.users_group_id != None + validator = v.ValidUsersGroup(edit=True, + old_data={'users_group_id': + gr2.users_group_id}) + + self.assertRaises(formencode.Invalid, validator.to_python, 'test') + self.assertRaises(formencode.Invalid, validator.to_python, 'TesT') + self.assertRaises(formencode.Invalid, validator.to_python, 'TEST') + UsersGroupModel().delete(gr) + UsersGroupModel().delete(gr2) + Session.commit() + + def test_ValidReposGroup(self): + validator = v.ValidReposGroup() + model = ReposGroupModel() + self.assertRaises(formencode.Invalid, validator.to_python, + {'group_name': HG_REPO, }) + gr = model.create(group_name='test_gr', group_description='desc', + parent=None, + just_db=True) + self.assertRaises(formencode.Invalid, + validator.to_python, {'group_name': gr.group_name, }) + + validator = v.ValidReposGroup(edit=True, + old_data={'group_id': gr.group_id}) + self.assertRaises(formencode.Invalid, + validator.to_python, { + 'group_name': gr.group_name + 'n', + 'group_parent_id': gr.group_id + }) + model.delete(gr) + + def test_ValidPassword(self): + validator = v.ValidPassword() + self.assertEqual('lol', validator.to_python('lol')) + self.assertEqual(None, validator.to_python(None)) + self.assertRaises(formencode.Invalid, validator.to_python, 'ąćżź') + + def test_ValidPasswordsMatch(self): + validator = v.ValidPasswordsMatch() + self.assertRaises(formencode.Invalid, + validator.to_python, {'password': 'pass', + 'password_confirmation': 'pass2'}) + + self.assertRaises(formencode.Invalid, + validator.to_python, {'new_password': 'pass', + 'password_confirmation': 'pass2'}) + + self.assertEqual({'new_password': 'pass', + 'password_confirmation': 'pass'}, + validator.to_python({'new_password': 'pass', + 'password_confirmation': 'pass'})) + + self.assertEqual({'password': 'pass', + 'password_confirmation': 'pass'}, + validator.to_python({'password': 'pass', + 'password_confirmation': 'pass'})) + + def test_ValidAuth(self): + validator = v.ValidAuth() + valid_creds = { + 'username': TEST_USER_REGULAR2_LOGIN, + 'password': TEST_USER_REGULAR2_PASS, + } + invalid_creds = { + 'username': 'err', + 'password': 'err', + } + self.assertEqual(valid_creds, validator.to_python(valid_creds)) + self.assertRaises(formencode.Invalid, + validator.to_python, invalid_creds) + + def test_ValidAuthToken(self): + validator = v.ValidAuthToken() + # this is untestable without a threadlocal +# self.assertRaises(formencode.Invalid, +# validator.to_python, 'BadToken') + validator + + def test_ValidRepoName(self): + validator = v.ValidRepoName() + + self.assertRaises(formencode.Invalid, + validator.to_python, {'repo_name': ''}) + + self.assertRaises(formencode.Invalid, + validator.to_python, {'repo_name': HG_REPO}) + + gr = ReposGroupModel().create(group_name='group_test', + group_description='desc', + parent=None,) + self.assertRaises(formencode.Invalid, + validator.to_python, {'repo_name': gr.group_name}) + + #TODO: write an error case for that ie. create a repo withinh a group +# self.assertRaises(formencode.Invalid, +# validator.to_python, {'repo_name': 'some', +# 'repo_group': gr.group_id}) + + def test_ValidForkName(self): + # this uses ValidRepoName validator + assert True + + @parameterized.expand([ + ('test', 'test'), ('lolz!', 'lolz'), (' aavv', 'aavv'), + ('ala ma kota', 'ala-ma-kota'), ('@nooo', 'nooo'), + ('$!haha lolz !', 'haha-lolz'), ('$$$$$', ''), ('{}OK!', 'OK'), + ('/]re po', 're-po')]) + def test_SlugifyName(self, name, expected): + validator = v.SlugifyName() + self.assertEqual(expected, validator.to_python(name)) + + def test_ValidCloneUri(self): + assert False + + def test_ValidForkType(self): + validator = v.ValidForkType(old_data={'repo_type': 'hg'}) + self.assertEqual('hg', validator.to_python('hg')) + self.assertRaises(formencode.Invalid, validator.to_python, 'git') + + def test_ValidPerms(self): + assert False + + def test_ValidSettings(self): + validator = v.ValidSettings() + self.assertEqual({'pass': 'pass'}, + validator.to_python(value={'user': 'test', + 'pass': 'pass'})) + + self.assertEqual({'user2': 'test', 'pass': 'pass'}, + validator.to_python(value={'user2': 'test', + 'pass': 'pass'})) + + def test_ValidPath(self): + validator = v.ValidPath() + self.assertEqual(TESTS_TMP_PATH, + validator.to_python(TESTS_TMP_PATH)) + self.assertRaises(formencode.Invalid, validator.to_python, + '/no_such_dir') + + def test_UniqSystemEmail(self): + validator = v.UniqSystemEmail(old_data={}) + + self.assertEqual('mail@python.org', + validator.to_python('MaiL@Python.org')) + + email = TEST_USER_REGULAR2_EMAIL + self.assertRaises(formencode.Invalid, validator.to_python, email) + + def test_ValidSystemEmail(self): + validator = v.ValidSystemEmail() + email = TEST_USER_REGULAR2_EMAIL + + self.assertEqual(email, validator.to_python(email)) + self.assertRaises(formencode.Invalid, validator.to_python, 'err') + + def test_LdapLibValidator(self): + validator = v.LdapLibValidator() + self.assertRaises(v.LdapImportError, validator.to_python, 'err') + + def test_AttrLoginValidator(self): + validator = v.AttrLoginValidator() + self.assertRaises(formencode.Invalid, validator.to_python, 123)