##// END OF EJS Templates
fixed ldap form, it doesn't validate the baseDN until enable checkbox is set
marcink -
r1145:9a994632 default
parent child Browse files
Show More
@@ -1,105 +1,106
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.admin.ldap_settings
3 rhodecode.controllers.admin.ldap_settings
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 ldap controller for RhodeCode
6 ldap controller for RhodeCode
7
7
8 :created_on: Nov 26, 2010
8 :created_on: Nov 26, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software; you can redistribute it and/or
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27 import logging
27 import logging
28 import formencode
28 import formencode
29 import traceback
29 import traceback
30
30
31 from formencode import htmlfill
31 from formencode import htmlfill
32
32
33 from pylons import request, response, session, tmpl_context as c, url
33 from pylons import request, response, session, tmpl_context as c, url
34 from pylons.controllers.util import abort, redirect
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36
36
37 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.base import BaseController, render
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
40 from rhodecode.lib.auth_ldap import LdapImportError
40 from rhodecode.lib.auth_ldap import LdapImportError
41 from rhodecode.model.settings import SettingsModel
41 from rhodecode.model.settings import SettingsModel
42 from rhodecode.model.forms import LdapSettingsForm
42 from rhodecode.model.forms import LdapSettingsForm
43 from sqlalchemy.exc import DatabaseError
43 from sqlalchemy.exc import DatabaseError
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48
48
49 class LdapSettingsController(BaseController):
49 class LdapSettingsController(BaseController):
50
50
51 @LoginRequired()
51 @LoginRequired()
52 @HasPermissionAllDecorator('hg.admin')
52 @HasPermissionAllDecorator('hg.admin')
53 def __before__(self):
53 def __before__(self):
54 c.admin_user = session.get('admin_user')
54 c.admin_user = session.get('admin_user')
55 c.admin_username = session.get('admin_username')
55 c.admin_username = session.get('admin_username')
56 super(LdapSettingsController, self).__before__()
56 super(LdapSettingsController, self).__before__()
57
57
58 def index(self):
58 def index(self):
59 defaults = SettingsModel().get_ldap_settings()
59 defaults = SettingsModel().get_ldap_settings()
60
60
61 return htmlfill.render(
61 return htmlfill.render(
62 render('admin/ldap/ldap.html'),
62 render('admin/ldap/ldap.html'),
63 defaults=defaults,
63 defaults=defaults,
64 encoding="UTF-8",
64 encoding="UTF-8",
65 force_defaults=True,)
65 force_defaults=True,)
66
66
67 def ldap_settings(self):
67 def ldap_settings(self):
68 """POST ldap create and store ldap settings"""
68 """POST ldap create and store ldap settings"""
69
69
70 settings_model = SettingsModel()
70 settings_model = SettingsModel()
71 _form = LdapSettingsForm()()
71 post_data = dict(request.POST)
72 _form = LdapSettingsForm(post_data.get('ldap_active'))()
72
73
73 try:
74 try:
74 form_result = _form.to_python(dict(request.POST))
75 form_result = _form.to_python(post_data)
75 try:
76 try:
76
77
77 for k, v in form_result.items():
78 for k, v in form_result.items():
78 if k.startswith('ldap_'):
79 if k.startswith('ldap_'):
79 setting = settings_model.get(k)
80 setting = settings_model.get(k)
80 setting.app_settings_value = v
81 setting.app_settings_value = v
81 self.sa.add(setting)
82 self.sa.add(setting)
82
83
83 self.sa.commit()
84 self.sa.commit()
84 h.flash(_('Ldap settings updated successfully'),
85 h.flash(_('Ldap settings updated successfully'),
85 category='success')
86 category='success')
86 except (DatabaseError,):
87 except (DatabaseError,):
87 raise
88 raise
88 except LdapImportError:
89 except LdapImportError:
89 h.flash(_('Unable to activate ldap. The "python-ldap" library '
90 h.flash(_('Unable to activate ldap. The "python-ldap" library '
90 'is missing.'), category='warning')
91 'is missing.'), category='warning')
91
92
92 except formencode.Invalid, errors:
93 except formencode.Invalid, errors:
93
94
94 return htmlfill.render(
95 return htmlfill.render(
95 render('admin/ldap/ldap.html'),
96 render('admin/ldap/ldap.html'),
96 defaults=errors.value,
97 defaults=errors.value,
97 errors=errors.error_dict or {},
98 errors=errors.error_dict or {},
98 prefix_error=False,
99 prefix_error=False,
99 encoding="UTF-8")
100 encoding="UTF-8")
100 except Exception:
101 except Exception:
101 log.error(traceback.format_exc())
102 log.error(traceback.format_exc())
102 h.flash(_('error occurred during update of ldap settings'),
103 h.flash(_('error occurred during update of ldap settings'),
103 category='error')
104 category='error')
104
105
105 return redirect(url('ldap_home'))
106 return redirect(url('ldap_home'))
@@ -1,483 +1,486
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 import os
22 import os
23 import re
23 import re
24 import logging
24 import logging
25
25
26 import formencode
26 import formencode
27 from formencode import All
27 from formencode import All
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
28 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
29 Email, Bool, StringBoolean
29 Email, Bool, StringBoolean
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 import rhodecode.lib.helpers as h
33 import rhodecode.lib.helpers as h
34 from rhodecode.lib.auth import authenticate, get_crypt_password
34 from rhodecode.lib.auth import authenticate, get_crypt_password
35 from rhodecode.lib.exceptions import LdapImportError
35 from rhodecode.lib.exceptions import LdapImportError
36 from rhodecode.model import meta
36 from rhodecode.model import meta
37 from rhodecode.model.user import UserModel
37 from rhodecode.model.user import UserModel
38 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.db import User
39 from rhodecode.model.db import User
40 from rhodecode import BACKENDS
40 from rhodecode import BACKENDS
41
41
42 from webhelpers.pylonslib.secure_form import authentication_token
42 from webhelpers.pylonslib.secure_form import authentication_token
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46 #this is needed to translate the messages using _() in validators
46 #this is needed to translate the messages using _() in validators
47 class State_obj(object):
47 class State_obj(object):
48 _ = staticmethod(_)
48 _ = staticmethod(_)
49
49
50 #===============================================================================
50 #===============================================================================
51 # VALIDATORS
51 # VALIDATORS
52 #===============================================================================
52 #===============================================================================
53 class ValidAuthToken(formencode.validators.FancyValidator):
53 class ValidAuthToken(formencode.validators.FancyValidator):
54 messages = {'invalid_token':_('Token mismatch')}
54 messages = {'invalid_token':_('Token mismatch')}
55
55
56 def validate_python(self, value, state):
56 def validate_python(self, value, state):
57
57
58 if value != authentication_token():
58 if value != authentication_token():
59 raise formencode.Invalid(self.message('invalid_token', state,
59 raise formencode.Invalid(self.message('invalid_token', state,
60 search_number=value), value, state)
60 search_number=value), value, state)
61
61
62 def ValidUsername(edit, old_data):
62 def ValidUsername(edit, old_data):
63 class _ValidUsername(formencode.validators.FancyValidator):
63 class _ValidUsername(formencode.validators.FancyValidator):
64
64
65 def validate_python(self, value, state):
65 def validate_python(self, value, state):
66 if value in ['default', 'new_user']:
66 if value in ['default', 'new_user']:
67 raise formencode.Invalid(_('Invalid username'), value, state)
67 raise formencode.Invalid(_('Invalid username'), value, state)
68 #check if user is unique
68 #check if user is unique
69 old_un = None
69 old_un = None
70 if edit:
70 if edit:
71 old_un = UserModel().get(old_data.get('user_id')).username
71 old_un = UserModel().get(old_data.get('user_id')).username
72
72
73 if old_un != value or not edit:
73 if old_un != value or not edit:
74 if UserModel().get_by_username(value, cache=False,
74 if UserModel().get_by_username(value, cache=False,
75 case_insensitive=True):
75 case_insensitive=True):
76 raise formencode.Invalid(_('This username already exists') ,
76 raise formencode.Invalid(_('This username already exists') ,
77 value, state)
77 value, state)
78
78
79
79
80 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
80 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
81 raise formencode.Invalid(_('Username may only contain '
81 raise formencode.Invalid(_('Username may only contain '
82 'alphanumeric characters underscores, '
82 'alphanumeric characters underscores, '
83 'periods or dashes and must begin with '
83 'periods or dashes and must begin with '
84 'alphanumeric character'),
84 'alphanumeric character'),
85 value, state)
85 value, state)
86
86
87
87
88
88
89 return _ValidUsername
89 return _ValidUsername
90
90
91 class ValidPassword(formencode.validators.FancyValidator):
91 class ValidPassword(formencode.validators.FancyValidator):
92
92
93 def to_python(self, value, state):
93 def to_python(self, value, state):
94
94
95 if value:
95 if value:
96
96
97 if value.get('password'):
97 if value.get('password'):
98 try:
98 try:
99 value['password'] = get_crypt_password(value['password'])
99 value['password'] = get_crypt_password(value['password'])
100 except UnicodeEncodeError:
100 except UnicodeEncodeError:
101 e_dict = {'password':_('Invalid characters in password')}
101 e_dict = {'password':_('Invalid characters in password')}
102 raise formencode.Invalid('', value, state, error_dict=e_dict)
102 raise formencode.Invalid('', value, state, error_dict=e_dict)
103
103
104 if value.get('password_confirmation'):
104 if value.get('password_confirmation'):
105 try:
105 try:
106 value['password_confirmation'] = \
106 value['password_confirmation'] = \
107 get_crypt_password(value['password_confirmation'])
107 get_crypt_password(value['password_confirmation'])
108 except UnicodeEncodeError:
108 except UnicodeEncodeError:
109 e_dict = {'password_confirmation':_('Invalid characters in password')}
109 e_dict = {'password_confirmation':_('Invalid characters in password')}
110 raise formencode.Invalid('', value, state, error_dict=e_dict)
110 raise formencode.Invalid('', value, state, error_dict=e_dict)
111
111
112 if value.get('new_password'):
112 if value.get('new_password'):
113 try:
113 try:
114 value['new_password'] = \
114 value['new_password'] = \
115 get_crypt_password(value['new_password'])
115 get_crypt_password(value['new_password'])
116 except UnicodeEncodeError:
116 except UnicodeEncodeError:
117 e_dict = {'new_password':_('Invalid characters in password')}
117 e_dict = {'new_password':_('Invalid characters in password')}
118 raise formencode.Invalid('', value, state, error_dict=e_dict)
118 raise formencode.Invalid('', value, state, error_dict=e_dict)
119
119
120 return value
120 return value
121
121
122 class ValidPasswordsMatch(formencode.validators.FancyValidator):
122 class ValidPasswordsMatch(formencode.validators.FancyValidator):
123
123
124 def validate_python(self, value, state):
124 def validate_python(self, value, state):
125
125
126 if value['password'] != value['password_confirmation']:
126 if value['password'] != value['password_confirmation']:
127 e_dict = {'password_confirmation':
127 e_dict = {'password_confirmation':
128 _('Password do not match')}
128 _('Password do not match')}
129 raise formencode.Invalid('', value, state, error_dict=e_dict)
129 raise formencode.Invalid('', value, state, error_dict=e_dict)
130
130
131 class ValidAuth(formencode.validators.FancyValidator):
131 class ValidAuth(formencode.validators.FancyValidator):
132 messages = {
132 messages = {
133 'invalid_password':_('invalid password'),
133 'invalid_password':_('invalid password'),
134 'invalid_login':_('invalid user name'),
134 'invalid_login':_('invalid user name'),
135 'disabled_account':_('Your account is disabled')
135 'disabled_account':_('Your account is disabled')
136
136
137 }
137 }
138 #error mapping
138 #error mapping
139 e_dict = {'username':messages['invalid_login'],
139 e_dict = {'username':messages['invalid_login'],
140 'password':messages['invalid_password']}
140 'password':messages['invalid_password']}
141 e_dict_disable = {'username':messages['disabled_account']}
141 e_dict_disable = {'username':messages['disabled_account']}
142
142
143 def validate_python(self, value, state):
143 def validate_python(self, value, state):
144 password = value['password']
144 password = value['password']
145 username = value['username']
145 username = value['username']
146 user = UserModel().get_by_username(username)
146 user = UserModel().get_by_username(username)
147
147
148 if authenticate(username, password):
148 if authenticate(username, password):
149 return value
149 return value
150 else:
150 else:
151 if user and user.active is False:
151 if user and user.active is False:
152 log.warning('user %s is disabled', username)
152 log.warning('user %s is disabled', username)
153 raise formencode.Invalid(self.message('disabled_account',
153 raise formencode.Invalid(self.message('disabled_account',
154 state=State_obj),
154 state=State_obj),
155 value, state,
155 value, state,
156 error_dict=self.e_dict_disable)
156 error_dict=self.e_dict_disable)
157 else:
157 else:
158 log.warning('user %s not authenticated', username)
158 log.warning('user %s not authenticated', username)
159 raise formencode.Invalid(self.message('invalid_password',
159 raise formencode.Invalid(self.message('invalid_password',
160 state=State_obj), value, state,
160 state=State_obj), value, state,
161 error_dict=self.e_dict)
161 error_dict=self.e_dict)
162
162
163 class ValidRepoUser(formencode.validators.FancyValidator):
163 class ValidRepoUser(formencode.validators.FancyValidator):
164
164
165 def to_python(self, value, state):
165 def to_python(self, value, state):
166 sa = meta.Session()
166 sa = meta.Session()
167 try:
167 try:
168 self.user_db = sa.query(User)\
168 self.user_db = sa.query(User)\
169 .filter(User.active == True)\
169 .filter(User.active == True)\
170 .filter(User.username == value).one()
170 .filter(User.username == value).one()
171 except Exception:
171 except Exception:
172 raise formencode.Invalid(_('This username is not valid'),
172 raise formencode.Invalid(_('This username is not valid'),
173 value, state)
173 value, state)
174 finally:
174 finally:
175 meta.Session.remove()
175 meta.Session.remove()
176
176
177 return self.user_db.user_id
177 return self.user_db.user_id
178
178
179 def ValidRepoName(edit, old_data):
179 def ValidRepoName(edit, old_data):
180 class _ValidRepoName(formencode.validators.FancyValidator):
180 class _ValidRepoName(formencode.validators.FancyValidator):
181
181
182 def to_python(self, value, state):
182 def to_python(self, value, state):
183 slug = h.repo_name_slug(value)
183 slug = h.repo_name_slug(value)
184 if slug in ['_admin']:
184 if slug in ['_admin']:
185 raise formencode.Invalid(_('This repository name is disallowed'),
185 raise formencode.Invalid(_('This repository name is disallowed'),
186 value, state)
186 value, state)
187 if old_data.get('repo_name') != value or not edit:
187 if old_data.get('repo_name') != value or not edit:
188 if RepoModel().get_by_repo_name(slug, cache=False):
188 if RepoModel().get_by_repo_name(slug, cache=False):
189 raise formencode.Invalid(_('This repository already exists') ,
189 raise formencode.Invalid(_('This repository already exists') ,
190 value, state)
190 value, state)
191 return slug
191 return slug
192
192
193
193
194 return _ValidRepoName
194 return _ValidRepoName
195
195
196 def ValidForkType(old_data):
196 def ValidForkType(old_data):
197 class _ValidForkType(formencode.validators.FancyValidator):
197 class _ValidForkType(formencode.validators.FancyValidator):
198
198
199 def to_python(self, value, state):
199 def to_python(self, value, state):
200 if old_data['repo_type'] != value:
200 if old_data['repo_type'] != value:
201 raise formencode.Invalid(_('Fork have to be the same type as original'),
201 raise formencode.Invalid(_('Fork have to be the same type as original'),
202 value, state)
202 value, state)
203 return value
203 return value
204 return _ValidForkType
204 return _ValidForkType
205
205
206 class ValidPerms(formencode.validators.FancyValidator):
206 class ValidPerms(formencode.validators.FancyValidator):
207 messages = {'perm_new_user_name':_('This username is not valid')}
207 messages = {'perm_new_user_name':_('This username is not valid')}
208
208
209 def to_python(self, value, state):
209 def to_python(self, value, state):
210 perms_update = []
210 perms_update = []
211 perms_new = []
211 perms_new = []
212 #build a list of permission to update and new permission to create
212 #build a list of permission to update and new permission to create
213 for k, v in value.items():
213 for k, v in value.items():
214 if k.startswith('perm_'):
214 if k.startswith('perm_'):
215 if k.startswith('perm_new_user'):
215 if k.startswith('perm_new_user'):
216 new_perm = value.get('perm_new_user', False)
216 new_perm = value.get('perm_new_user', False)
217 new_user = value.get('perm_new_user_name', False)
217 new_user = value.get('perm_new_user_name', False)
218 if new_user and new_perm:
218 if new_user and new_perm:
219 if (new_user, new_perm) not in perms_new:
219 if (new_user, new_perm) not in perms_new:
220 perms_new.append((new_user, new_perm))
220 perms_new.append((new_user, new_perm))
221 else:
221 else:
222 usr = k[5:]
222 usr = k[5:]
223 if usr == 'default':
223 if usr == 'default':
224 if value['private']:
224 if value['private']:
225 #set none for default when updating to private repo
225 #set none for default when updating to private repo
226 v = 'repository.none'
226 v = 'repository.none'
227 perms_update.append((usr, v))
227 perms_update.append((usr, v))
228 value['perms_updates'] = perms_update
228 value['perms_updates'] = perms_update
229 value['perms_new'] = perms_new
229 value['perms_new'] = perms_new
230 sa = meta.Session
230 sa = meta.Session
231 for k, v in perms_new:
231 for k, v in perms_new:
232 try:
232 try:
233 self.user_db = sa.query(User)\
233 self.user_db = sa.query(User)\
234 .filter(User.active == True)\
234 .filter(User.active == True)\
235 .filter(User.username == k).one()
235 .filter(User.username == k).one()
236 except Exception:
236 except Exception:
237 msg = self.message('perm_new_user_name',
237 msg = self.message('perm_new_user_name',
238 state=State_obj)
238 state=State_obj)
239 raise formencode.Invalid(msg, value, state,
239 raise formencode.Invalid(msg, value, state,
240 error_dict={'perm_new_user_name':msg})
240 error_dict={'perm_new_user_name':msg})
241 return value
241 return value
242
242
243 class ValidSettings(formencode.validators.FancyValidator):
243 class ValidSettings(formencode.validators.FancyValidator):
244
244
245 def to_python(self, value, state):
245 def to_python(self, value, state):
246 #settings form can't edit user
246 #settings form can't edit user
247 if value.has_key('user'):
247 if value.has_key('user'):
248 del['value']['user']
248 del['value']['user']
249
249
250 return value
250 return value
251
251
252 class ValidPath(formencode.validators.FancyValidator):
252 class ValidPath(formencode.validators.FancyValidator):
253 def to_python(self, value, state):
253 def to_python(self, value, state):
254
254
255 if not os.path.isdir(value):
255 if not os.path.isdir(value):
256 msg = _('This is not a valid path')
256 msg = _('This is not a valid path')
257 raise formencode.Invalid(msg, value, state,
257 raise formencode.Invalid(msg, value, state,
258 error_dict={'paths_root_path':msg})
258 error_dict={'paths_root_path':msg})
259 return value
259 return value
260
260
261 def UniqSystemEmail(old_data):
261 def UniqSystemEmail(old_data):
262 class _UniqSystemEmail(formencode.validators.FancyValidator):
262 class _UniqSystemEmail(formencode.validators.FancyValidator):
263 def to_python(self, value, state):
263 def to_python(self, value, state):
264 value = value.lower()
264 value = value.lower()
265 if old_data.get('email') != value:
265 if old_data.get('email') != value:
266 sa = meta.Session()
266 sa = meta.Session()
267 try:
267 try:
268 user = sa.query(User).filter(User.email == value).scalar()
268 user = sa.query(User).filter(User.email == value).scalar()
269 if user:
269 if user:
270 raise formencode.Invalid(_("This e-mail address is already taken") ,
270 raise formencode.Invalid(_("This e-mail address is already taken") ,
271 value, state)
271 value, state)
272 finally:
272 finally:
273 meta.Session.remove()
273 meta.Session.remove()
274
274
275 return value
275 return value
276
276
277 return _UniqSystemEmail
277 return _UniqSystemEmail
278
278
279 class ValidSystemEmail(formencode.validators.FancyValidator):
279 class ValidSystemEmail(formencode.validators.FancyValidator):
280 def to_python(self, value, state):
280 def to_python(self, value, state):
281 value = value.lower()
281 value = value.lower()
282 sa = meta.Session
282 sa = meta.Session
283 try:
283 try:
284 user = sa.query(User).filter(User.email == value).scalar()
284 user = sa.query(User).filter(User.email == value).scalar()
285 if user is None:
285 if user is None:
286 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
286 raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
287 value, state)
287 value, state)
288 finally:
288 finally:
289 meta.Session.remove()
289 meta.Session.remove()
290
290
291 return value
291 return value
292
292
293 class LdapLibValidator(formencode.validators.FancyValidator):
293 class LdapLibValidator(formencode.validators.FancyValidator):
294
294
295 def to_python(self, value, state):
295 def to_python(self, value, state):
296
296
297 try:
297 try:
298 import ldap
298 import ldap
299 except ImportError:
299 except ImportError:
300 raise LdapImportError
300 raise LdapImportError
301 return value
301 return value
302
302
303 class BaseDnValidator(formencode.validators.FancyValidator):
303 def BaseDnValidator(ldap_enable):
304 class _BaseDnValidator(formencode.validators.FancyValidator):
304
305
305 def to_python(self, value, state):
306 def to_python(self, value, state):
306
307
308 if not ldap_enable:
309 return ''
307 try:
310 try:
308 value % {'user':'valid'}
311 value % {'user':'valid'}
309
312
310 if value.find('%(user)s') == -1:
313 if value.find('%(user)s') == -1:
311 raise formencode.Invalid(_("You need to specify %(user)s in "
314 raise formencode.Invalid(_("You need to specify %(user)s in "
312 "template for example uid=%(user)s "
315 "template for example uid=%(user)s "
313 ",dc=company...") ,
316 ",dc=company...") ,
314 value, state)
317 value, state)
315
318
316 except KeyError:
319 except KeyError:
317 raise formencode.Invalid(_("Wrong template used, only %(user)s "
320 raise formencode.Invalid(_("Wrong template used, only %(user)s "
318 "is an valid entry") ,
321 "is an valid entry") ,
319 value, state)
322 value, state)
320
323
321 return value
324 return value
322
325 return _BaseDnValidator
323 #===============================================================================
326 #===============================================================================
324 # FORMS
327 # FORMS
325 #===============================================================================
328 #===============================================================================
326 class LoginForm(formencode.Schema):
329 class LoginForm(formencode.Schema):
327 allow_extra_fields = True
330 allow_extra_fields = True
328 filter_extra_fields = True
331 filter_extra_fields = True
329 username = UnicodeString(
332 username = UnicodeString(
330 strip=True,
333 strip=True,
331 min=1,
334 min=1,
332 not_empty=True,
335 not_empty=True,
333 messages={
336 messages={
334 'empty':_('Please enter a login'),
337 'empty':_('Please enter a login'),
335 'tooShort':_('Enter a value %(min)i characters long or more')}
338 'tooShort':_('Enter a value %(min)i characters long or more')}
336 )
339 )
337
340
338 password = UnicodeString(
341 password = UnicodeString(
339 strip=True,
342 strip=True,
340 min=6,
343 min=6,
341 not_empty=True,
344 not_empty=True,
342 messages={
345 messages={
343 'empty':_('Please enter a password'),
346 'empty':_('Please enter a password'),
344 'tooShort':_('Enter %(min)i characters or more')}
347 'tooShort':_('Enter %(min)i characters or more')}
345 )
348 )
346
349
347
350
348 #chained validators have access to all data
351 #chained validators have access to all data
349 chained_validators = [ValidAuth]
352 chained_validators = [ValidAuth]
350
353
351 def UserForm(edit=False, old_data={}):
354 def UserForm(edit=False, old_data={}):
352 class _UserForm(formencode.Schema):
355 class _UserForm(formencode.Schema):
353 allow_extra_fields = True
356 allow_extra_fields = True
354 filter_extra_fields = True
357 filter_extra_fields = True
355 username = All(UnicodeString(strip=True, min=1, not_empty=True),
358 username = All(UnicodeString(strip=True, min=1, not_empty=True),
356 ValidUsername(edit, old_data))
359 ValidUsername(edit, old_data))
357 if edit:
360 if edit:
358 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
361 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
359 admin = StringBoolean(if_missing=False)
362 admin = StringBoolean(if_missing=False)
360 else:
363 else:
361 password = All(UnicodeString(strip=True, min=6, not_empty=True))
364 password = All(UnicodeString(strip=True, min=6, not_empty=True))
362 active = StringBoolean(if_missing=False)
365 active = StringBoolean(if_missing=False)
363 name = UnicodeString(strip=True, min=1, not_empty=True)
366 name = UnicodeString(strip=True, min=1, not_empty=True)
364 lastname = UnicodeString(strip=True, min=1, not_empty=True)
367 lastname = UnicodeString(strip=True, min=1, not_empty=True)
365 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
368 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
366
369
367 chained_validators = [ValidPassword]
370 chained_validators = [ValidPassword]
368
371
369 return _UserForm
372 return _UserForm
370
373
371 def RegisterForm(edit=False, old_data={}):
374 def RegisterForm(edit=False, old_data={}):
372 class _RegisterForm(formencode.Schema):
375 class _RegisterForm(formencode.Schema):
373 allow_extra_fields = True
376 allow_extra_fields = True
374 filter_extra_fields = True
377 filter_extra_fields = True
375 username = All(ValidUsername(edit, old_data),
378 username = All(ValidUsername(edit, old_data),
376 UnicodeString(strip=True, min=1, not_empty=True))
379 UnicodeString(strip=True, min=1, not_empty=True))
377 password = All(UnicodeString(strip=True, min=6, not_empty=True))
380 password = All(UnicodeString(strip=True, min=6, not_empty=True))
378 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
381 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
379 active = StringBoolean(if_missing=False)
382 active = StringBoolean(if_missing=False)
380 name = UnicodeString(strip=True, min=1, not_empty=True)
383 name = UnicodeString(strip=True, min=1, not_empty=True)
381 lastname = UnicodeString(strip=True, min=1, not_empty=True)
384 lastname = UnicodeString(strip=True, min=1, not_empty=True)
382 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
385 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
383
386
384 chained_validators = [ValidPasswordsMatch, ValidPassword]
387 chained_validators = [ValidPasswordsMatch, ValidPassword]
385
388
386 return _RegisterForm
389 return _RegisterForm
387
390
388 def PasswordResetForm():
391 def PasswordResetForm():
389 class _PasswordResetForm(formencode.Schema):
392 class _PasswordResetForm(formencode.Schema):
390 allow_extra_fields = True
393 allow_extra_fields = True
391 filter_extra_fields = True
394 filter_extra_fields = True
392 email = All(ValidSystemEmail(), Email(not_empty=True))
395 email = All(ValidSystemEmail(), Email(not_empty=True))
393 return _PasswordResetForm
396 return _PasswordResetForm
394
397
395 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
398 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
396 class _RepoForm(formencode.Schema):
399 class _RepoForm(formencode.Schema):
397 allow_extra_fields = True
400 allow_extra_fields = True
398 filter_extra_fields = False
401 filter_extra_fields = False
399 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
402 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
400 ValidRepoName(edit, old_data))
403 ValidRepoName(edit, old_data))
401 description = UnicodeString(strip=True, min=1, not_empty=True)
404 description = UnicodeString(strip=True, min=1, not_empty=True)
402 private = StringBoolean(if_missing=False)
405 private = StringBoolean(if_missing=False)
403 enable_statistics = StringBoolean(if_missing=False)
406 enable_statistics = StringBoolean(if_missing=False)
404 repo_type = OneOf(supported_backends)
407 repo_type = OneOf(supported_backends)
405 if edit:
408 if edit:
406 user = All(Int(not_empty=True), ValidRepoUser)
409 user = All(Int(not_empty=True), ValidRepoUser)
407
410
408 chained_validators = [ValidPerms]
411 chained_validators = [ValidPerms]
409 return _RepoForm
412 return _RepoForm
410
413
411 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
414 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
412 class _RepoForkForm(formencode.Schema):
415 class _RepoForkForm(formencode.Schema):
413 allow_extra_fields = True
416 allow_extra_fields = True
414 filter_extra_fields = False
417 filter_extra_fields = False
415 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
418 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
416 ValidRepoName(edit, old_data))
419 ValidRepoName(edit, old_data))
417 description = UnicodeString(strip=True, min=1, not_empty=True)
420 description = UnicodeString(strip=True, min=1, not_empty=True)
418 private = StringBoolean(if_missing=False)
421 private = StringBoolean(if_missing=False)
419 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
422 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
420 return _RepoForkForm
423 return _RepoForkForm
421
424
422 def RepoSettingsForm(edit=False, old_data={}):
425 def RepoSettingsForm(edit=False, old_data={}):
423 class _RepoForm(formencode.Schema):
426 class _RepoForm(formencode.Schema):
424 allow_extra_fields = True
427 allow_extra_fields = True
425 filter_extra_fields = False
428 filter_extra_fields = False
426 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
429 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
427 ValidRepoName(edit, old_data))
430 ValidRepoName(edit, old_data))
428 description = UnicodeString(strip=True, min=1, not_empty=True)
431 description = UnicodeString(strip=True, min=1, not_empty=True)
429 private = StringBoolean(if_missing=False)
432 private = StringBoolean(if_missing=False)
430
433
431 chained_validators = [ValidPerms, ValidSettings]
434 chained_validators = [ValidPerms, ValidSettings]
432 return _RepoForm
435 return _RepoForm
433
436
434
437
435 def ApplicationSettingsForm():
438 def ApplicationSettingsForm():
436 class _ApplicationSettingsForm(formencode.Schema):
439 class _ApplicationSettingsForm(formencode.Schema):
437 allow_extra_fields = True
440 allow_extra_fields = True
438 filter_extra_fields = False
441 filter_extra_fields = False
439 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
442 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
440 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
443 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
441
444
442 return _ApplicationSettingsForm
445 return _ApplicationSettingsForm
443
446
444 def ApplicationUiSettingsForm():
447 def ApplicationUiSettingsForm():
445 class _ApplicationUiSettingsForm(formencode.Schema):
448 class _ApplicationUiSettingsForm(formencode.Schema):
446 allow_extra_fields = True
449 allow_extra_fields = True
447 filter_extra_fields = False
450 filter_extra_fields = False
448 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
451 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
449 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
452 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
450 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
453 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
451 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
454 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
452 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
455 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
453 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
456 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
454
457
455 return _ApplicationUiSettingsForm
458 return _ApplicationUiSettingsForm
456
459
457 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
460 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
458 class _DefaultPermissionsForm(formencode.Schema):
461 class _DefaultPermissionsForm(formencode.Schema):
459 allow_extra_fields = True
462 allow_extra_fields = True
460 filter_extra_fields = True
463 filter_extra_fields = True
461 overwrite_default = StringBoolean(if_missing=False)
464 overwrite_default = StringBoolean(if_missing=False)
462 anonymous = OneOf(['True', 'False'], if_missing=False)
465 anonymous = OneOf(['True', 'False'], if_missing=False)
463 default_perm = OneOf(perms_choices)
466 default_perm = OneOf(perms_choices)
464 default_register = OneOf(register_choices)
467 default_register = OneOf(register_choices)
465 default_create = OneOf(create_choices)
468 default_create = OneOf(create_choices)
466
469
467 return _DefaultPermissionsForm
470 return _DefaultPermissionsForm
468
471
469
472
470 def LdapSettingsForm():
473 def LdapSettingsForm(ldap_enable):
471 class _LdapSettingsForm(formencode.Schema):
474 class _LdapSettingsForm(formencode.Schema):
472 allow_extra_fields = True
475 allow_extra_fields = True
473 filter_extra_fields = True
476 filter_extra_fields = True
474 pre_validators = [LdapLibValidator]
477 pre_validators = [LdapLibValidator]
475 ldap_active = StringBoolean(if_missing=False)
478 ldap_active = StringBoolean(if_missing=False)
476 ldap_host = UnicodeString(strip=True,)
479 ldap_host = UnicodeString(strip=True,)
477 ldap_port = Number(strip=True,)
480 ldap_port = Number(strip=True,)
478 ldap_ldaps = StringBoolean(if_missing=False)
481 ldap_ldaps = StringBoolean(if_missing=False)
479 ldap_dn_user = UnicodeString(strip=True,)
482 ldap_dn_user = UnicodeString(strip=True,)
480 ldap_dn_pass = UnicodeString(strip=True,)
483 ldap_dn_pass = UnicodeString(strip=True,)
481 ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
484 ldap_base_dn = All(BaseDnValidator(ldap_enable), UnicodeString(strip=True,))
482
485
483 return _LdapSettingsForm
486 return _LdapSettingsForm
General Comments 0
You need to be logged in to leave comments. Login now