comparison rhodecode/model/forms.py @ 2776:63e58ef80ef1

Merge beta branch into stable
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 02 Sep 2012 21:19:54 +0200
parents a437a986d399 3ed4dae499d0
children f7a52d548fd0
comparison
equal deleted inserted replaced
2301:9d097c2592d3 2776:63e58ef80ef1
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
23 import re
24 import logging 22 import logging
25 import traceback
26 23
27 import formencode 24 import formencode
28 from formencode import All 25 from formencode import All
29 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
30 Email, Bool, StringBoolean, Set
31 26
32 from pylons.i18n.translation import _ 27 from pylons.i18n.translation import _
33 from webhelpers.pylonslib.secure_form import authentication_token 28
34 29 from rhodecode.model import validators as v
35 from rhodecode.config.routing import ADMIN_PREFIX
36 from rhodecode.lib.utils import repo_name_slug
37 from rhodecode.lib.auth import authenticate, get_crypt_password
38 from rhodecode.lib.exceptions import LdapImportError
39 from rhodecode.model.db import User, UsersGroup, RepoGroup, Repository
40 from rhodecode import BACKENDS 30 from rhodecode import BACKENDS
41 31
42 log = logging.getLogger(__name__) 32 log = logging.getLogger(__name__)
43 33
44 34
45 #this is needed to translate the messages using _() in validators
46 class State_obj(object):
47 _ = staticmethod(_)
48
49
50 #==============================================================================
51 # VALIDATORS
52 #==============================================================================
53 class ValidAuthToken(formencode.validators.FancyValidator):
54 messages = {'invalid_token': _('Token mismatch')}
55
56 def validate_python(self, value, state):
57
58 if value != authentication_token():
59 raise formencode.Invalid(
60 self.message('invalid_token',
61 state, search_number=value),
62 value,
63 state
64 )
65
66
67 def ValidUsername(edit, old_data):
68 class _ValidUsername(formencode.validators.FancyValidator):
69
70 def validate_python(self, value, state):
71 if value in ['default', 'new_user']:
72 raise formencode.Invalid(_('Invalid username'), value, state)
73 #check if user is unique
74 old_un = None
75 if edit:
76 old_un = User.get(old_data.get('user_id')).username
77
78 if old_un != value or not edit:
79 if User.get_by_username(value, case_insensitive=True):
80 raise formencode.Invalid(_('This username already '
81 'exists') , value, state)
82
83 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
84 raise formencode.Invalid(
85 _('Username may only contain alphanumeric characters '
86 'underscores, periods or dashes and must begin with '
87 'alphanumeric character'),
88 value,
89 state
90 )
91
92 return _ValidUsername
93
94
95 def ValidUsersGroup(edit, old_data):
96
97 class _ValidUsersGroup(formencode.validators.FancyValidator):
98
99 def validate_python(self, value, state):
100 if value in ['default']:
101 raise formencode.Invalid(_('Invalid group name'), value, state)
102 #check if group is unique
103 old_ugname = None
104 if edit:
105 old_ugname = UsersGroup.get(
106 old_data.get('users_group_id')).users_group_name
107
108 if old_ugname != value or not edit:
109 if UsersGroup.get_by_group_name(value, cache=False,
110 case_insensitive=True):
111 raise formencode.Invalid(_('This users group '
112 'already exists'), value,
113 state)
114
115 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
116 raise formencode.Invalid(
117 _('RepoGroup name may only contain alphanumeric characters '
118 'underscores, periods or dashes and must begin with '
119 'alphanumeric character'),
120 value,
121 state
122 )
123
124 return _ValidUsersGroup
125
126
127 def ValidReposGroup(edit, old_data):
128 class _ValidReposGroup(formencode.validators.FancyValidator):
129
130 def validate_python(self, value, state):
131 # TODO WRITE VALIDATIONS
132 group_name = value.get('group_name')
133 group_parent_id = value.get('group_parent_id')
134
135 # slugify repo group just in case :)
136 slug = repo_name_slug(group_name)
137
138 # check for parent of self
139 parent_of_self = lambda: (
140 old_data['group_id'] == int(group_parent_id)
141 if group_parent_id else False
142 )
143 if edit and parent_of_self():
144 e_dict = {
145 'group_parent_id': _('Cannot assign this group as parent')
146 }
147 raise formencode.Invalid('', value, state,
148 error_dict=e_dict)
149
150 old_gname = None
151 if edit:
152 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
153
154 if old_gname != group_name or not edit:
155
156 # check group
157 gr = RepoGroup.query()\
158 .filter(RepoGroup.group_name == slug)\
159 .filter(RepoGroup.group_parent_id == group_parent_id)\
160 .scalar()
161
162 if gr:
163 e_dict = {
164 'group_name': _('This group already exists')
165 }
166 raise formencode.Invalid('', value, state,
167 error_dict=e_dict)
168
169 # check for same repo
170 repo = Repository.query()\
171 .filter(Repository.repo_name == slug)\
172 .scalar()
173
174 if repo:
175 e_dict = {
176 'group_name': _('Repository with this name already exists')
177 }
178 raise formencode.Invalid('', value, state,
179 error_dict=e_dict)
180
181 return _ValidReposGroup
182
183
184 class ValidPassword(formencode.validators.FancyValidator):
185
186 def to_python(self, value, state):
187
188 if not value:
189 return
190
191 if value.get('password'):
192 try:
193 value['password'] = get_crypt_password(value['password'])
194 except UnicodeEncodeError:
195 e_dict = {'password': _('Invalid characters in password')}
196 raise formencode.Invalid('', value, state, error_dict=e_dict)
197
198 if value.get('password_confirmation'):
199 try:
200 value['password_confirmation'] = \
201 get_crypt_password(value['password_confirmation'])
202 except UnicodeEncodeError:
203 e_dict = {
204 'password_confirmation': _('Invalid characters in password')
205 }
206 raise formencode.Invalid('', value, state, error_dict=e_dict)
207
208 if value.get('new_password'):
209 try:
210 value['new_password'] = \
211 get_crypt_password(value['new_password'])
212 except UnicodeEncodeError:
213 e_dict = {'new_password': _('Invalid characters in password')}
214 raise formencode.Invalid('', value, state, error_dict=e_dict)
215
216 return value
217
218
219 class ValidPasswordsMatch(formencode.validators.FancyValidator):
220
221 def validate_python(self, value, state):
222
223 pass_val = value.get('password') or value.get('new_password')
224 if pass_val != value['password_confirmation']:
225 e_dict = {'password_confirmation':
226 _('Passwords do not match')}
227 raise formencode.Invalid('', value, state, error_dict=e_dict)
228
229
230 class ValidAuth(formencode.validators.FancyValidator):
231 messages = {
232 'invalid_password':_('invalid password'),
233 'invalid_login':_('invalid user name'),
234 'disabled_account':_('Your account is disabled')
235 }
236
237 # error mapping
238 e_dict = {'username': messages['invalid_login'],
239 'password': messages['invalid_password']}
240 e_dict_disable = {'username': messages['disabled_account']}
241
242 def validate_python(self, value, state):
243 password = value['password']
244 username = value['username']
245 user = User.get_by_username(username)
246
247 if authenticate(username, password):
248 return value
249 else:
250 if user and user.active is False:
251 log.warning('user %s is disabled' % username)
252 raise formencode.Invalid(
253 self.message('disabled_account',
254 state=State_obj),
255 value, state,
256 error_dict=self.e_dict_disable
257 )
258 else:
259 log.warning('user %s failed to authenticate' % username)
260 raise formencode.Invalid(
261 self.message('invalid_password',
262 state=State_obj), value, state,
263 error_dict=self.e_dict
264 )
265
266
267 class ValidRepoUser(formencode.validators.FancyValidator):
268
269 def to_python(self, value, state):
270 try:
271 User.query().filter(User.active == True)\
272 .filter(User.username == value).one()
273 except Exception:
274 raise formencode.Invalid(_('This username is not valid'),
275 value, state)
276 return value
277
278
279 def ValidRepoName(edit, old_data):
280 class _ValidRepoName(formencode.validators.FancyValidator):
281 def to_python(self, value, state):
282
283 repo_name = value.get('repo_name')
284
285 slug = repo_name_slug(repo_name)
286 if slug in [ADMIN_PREFIX, '']:
287 e_dict = {'repo_name': _('This repository name is disallowed')}
288 raise formencode.Invalid('', value, state, error_dict=e_dict)
289
290 if value.get('repo_group'):
291 gr = RepoGroup.get(value.get('repo_group'))
292 group_path = gr.full_path
293 # value needs to be aware of group name in order to check
294 # db key This is an actual just the name to store in the
295 # database
296 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
297
298 else:
299 group_path = ''
300 repo_name_full = repo_name
301
302 value['repo_name_full'] = repo_name_full
303 rename = old_data.get('repo_name') != repo_name_full
304 create = not edit
305 if rename or create:
306
307 if group_path != '':
308 if Repository.get_by_repo_name(repo_name_full):
309 e_dict = {
310 'repo_name': _('This repository already exists in '
311 'a group "%s"') % gr.group_name
312 }
313 raise formencode.Invalid('', value, state,
314 error_dict=e_dict)
315 elif RepoGroup.get_by_group_name(repo_name_full):
316 e_dict = {
317 'repo_name': _('There is a group with this name '
318 'already "%s"') % repo_name_full
319 }
320 raise formencode.Invalid('', value, state,
321 error_dict=e_dict)
322
323 elif Repository.get_by_repo_name(repo_name_full):
324 e_dict = {'repo_name': _('This repository '
325 'already exists')}
326 raise formencode.Invalid('', value, state,
327 error_dict=e_dict)
328
329 return value
330
331 return _ValidRepoName
332
333
334 def ValidForkName(*args, **kwargs):
335 return ValidRepoName(*args, **kwargs)
336
337
338 def SlugifyName():
339 class _SlugifyName(formencode.validators.FancyValidator):
340
341 def to_python(self, value, state):
342 return repo_name_slug(value)
343
344 return _SlugifyName
345
346
347 def ValidCloneUri():
348 from rhodecode.lib.utils import make_ui
349
350 def url_handler(repo_type, url, proto, ui=None):
351 if repo_type == 'hg':
352 from mercurial.httprepo import httprepository, httpsrepository
353 if proto == 'https':
354 httpsrepository(make_ui('db'), url).capabilities
355 elif proto == 'http':
356 httprepository(make_ui('db'), url).capabilities
357 elif repo_type == 'git':
358 #TODO: write a git url validator
359 pass
360
361 class _ValidCloneUri(formencode.validators.FancyValidator):
362
363 def to_python(self, value, state):
364
365 repo_type = value.get('repo_type')
366 url = value.get('clone_uri')
367 e_dict = {'clone_uri': _('invalid clone url')}
368
369 if not url:
370 pass
371 elif url.startswith('https'):
372 try:
373 url_handler(repo_type, url, 'https', make_ui('db'))
374 except Exception:
375 log.error(traceback.format_exc())
376 raise formencode.Invalid('', value, state, error_dict=e_dict)
377 elif url.startswith('http'):
378 try:
379 url_handler(repo_type, url, 'http', make_ui('db'))
380 except Exception:
381 log.error(traceback.format_exc())
382 raise formencode.Invalid('', value, state, error_dict=e_dict)
383 else:
384 e_dict = {'clone_uri': _('Invalid clone url, provide a '
385 'valid clone http\s url')}
386 raise formencode.Invalid('', value, state, error_dict=e_dict)
387
388 return value
389
390 return _ValidCloneUri
391
392
393 def ValidForkType(old_data):
394 class _ValidForkType(formencode.validators.FancyValidator):
395
396 def to_python(self, value, state):
397 if old_data['repo_type'] != value:
398 raise formencode.Invalid(_('Fork have to be the same '
399 'type as original'), value, state)
400
401 return value
402 return _ValidForkType
403
404
405 def ValidPerms(type_='repo'):
406 if type_ == 'group':
407 EMPTY_PERM = 'group.none'
408 elif type_ == 'repo':
409 EMPTY_PERM = 'repository.none'
410
411 class _ValidPerms(formencode.validators.FancyValidator):
412 messages = {
413 'perm_new_member_name':
414 _('This username or users group name is not valid')
415 }
416
417 def to_python(self, value, state):
418 perms_update = []
419 perms_new = []
420 # build a list of permission to update and new permission to create
421 for k, v in value.items():
422 # means new added member to permissions
423 if k.startswith('perm_new_member'):
424 new_perm = value.get('perm_new_member', False)
425 new_member = value.get('perm_new_member_name', False)
426 new_type = value.get('perm_new_member_type')
427
428 if new_member and new_perm:
429 if (new_member, new_perm, new_type) not in perms_new:
430 perms_new.append((new_member, new_perm, new_type))
431 elif k.startswith('u_perm_') or k.startswith('g_perm_'):
432 member = k[7:]
433 t = {'u': 'user',
434 'g': 'users_group'
435 }[k[0]]
436 if member == 'default':
437 if value.get('private'):
438 # set none for default when updating to private repo
439 v = EMPTY_PERM
440 perms_update.append((member, v, t))
441
442 value['perms_updates'] = perms_update
443 value['perms_new'] = perms_new
444
445 # update permissions
446 for k, v, t in perms_new:
447 try:
448 if t is 'user':
449 self.user_db = User.query()\
450 .filter(User.active == True)\
451 .filter(User.username == k).one()
452 if t is 'users_group':
453 self.user_db = UsersGroup.query()\
454 .filter(UsersGroup.users_group_active == True)\
455 .filter(UsersGroup.users_group_name == k).one()
456
457 except Exception:
458 msg = self.message('perm_new_member_name',
459 state=State_obj)
460 raise formencode.Invalid(
461 msg, value, state, error_dict={'perm_new_member_name': msg}
462 )
463 return value
464 return _ValidPerms
465
466
467 class ValidSettings(formencode.validators.FancyValidator):
468
469 def to_python(self, value, state):
470 # settings form can't edit user
471 if 'user' in value:
472 del['value']['user']
473 return value
474
475
476 class ValidPath(formencode.validators.FancyValidator):
477 def to_python(self, value, state):
478
479 if not os.path.isdir(value):
480 msg = _('This is not a valid path')
481 raise formencode.Invalid(msg, value, state,
482 error_dict={'paths_root_path': msg})
483 return value
484
485
486 def UniqSystemEmail(old_data):
487 class _UniqSystemEmail(formencode.validators.FancyValidator):
488 def to_python(self, value, state):
489 value = value.lower()
490 if (old_data.get('email') or '').lower() != value:
491 user = User.get_by_email(value, case_insensitive=True)
492 if user:
493 raise formencode.Invalid(
494 _("This e-mail address is already taken"), value, state
495 )
496 return value
497
498 return _UniqSystemEmail
499
500
501 class ValidSystemEmail(formencode.validators.FancyValidator):
502 def to_python(self, value, state):
503 value = value.lower()
504 user = User.get_by_email(value, case_insensitive=True)
505 if user is None:
506 raise formencode.Invalid(
507 _("This e-mail address doesn't exist."), value, state
508 )
509
510 return value
511
512
513 class LdapLibValidator(formencode.validators.FancyValidator):
514
515 def to_python(self, value, state):
516
517 try:
518 import ldap
519 except ImportError:
520 raise LdapImportError
521 return value
522
523
524 class AttrLoginValidator(formencode.validators.FancyValidator):
525
526 def to_python(self, value, state):
527
528 if not value or not isinstance(value, (str, unicode)):
529 raise formencode.Invalid(
530 _("The LDAP Login attribute of the CN must be specified - "
531 "this is the name of the attribute that is equivalent "
532 "to 'username'"), value, state
533 )
534
535 return value
536
537
538 #==============================================================================
539 # FORMS
540 #==============================================================================
541 class LoginForm(formencode.Schema): 35 class LoginForm(formencode.Schema):
542 allow_extra_fields = True 36 allow_extra_fields = True
543 filter_extra_fields = True 37 filter_extra_fields = True
544 username = UnicodeString( 38 username = v.UnicodeString(
545 strip=True, 39 strip=True,
546 min=1, 40 min=1,
547 not_empty=True, 41 not_empty=True,
548 messages={ 42 messages={
549 'empty': _('Please enter a login'), 43 'empty': _(u'Please enter a login'),
550 'tooShort': _('Enter a value %(min)i characters long or more')} 44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
551 ) 45 )
552 46
553 password = UnicodeString( 47 password = v.UnicodeString(
554 strip=False, 48 strip=False,
555 min=3, 49 min=3,
556 not_empty=True, 50 not_empty=True,
557 messages={ 51 messages={
558 'empty': _('Please enter a password'), 52 'empty': _(u'Please enter a password'),
559 'tooShort': _('Enter %(min)i characters or more')} 53 'tooShort': _(u'Enter %(min)i characters or more')}
560 ) 54 )
561 55
562 remember = StringBoolean(if_missing=False) 56 remember = v.StringBoolean(if_missing=False)
563 57
564 chained_validators = [ValidAuth] 58 chained_validators = [v.ValidAuth()]
565 59
566 60
567 def UserForm(edit=False, old_data={}): 61 def UserForm(edit=False, old_data={}):
568 class _UserForm(formencode.Schema): 62 class _UserForm(formencode.Schema):
569 allow_extra_fields = True 63 allow_extra_fields = True
570 filter_extra_fields = True 64 filter_extra_fields = True
571 username = All(UnicodeString(strip=True, min=1, not_empty=True), 65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
572 ValidUsername(edit, old_data)) 66 v.ValidUsername(edit, old_data))
573 if edit: 67 if edit:
574 new_password = All(UnicodeString(strip=False, min=6, not_empty=False)) 68 new_password = All(
575 password_confirmation = All(UnicodeString(strip=False, min=6, 69 v.ValidPassword(),
576 not_empty=False)) 70 v.UnicodeString(strip=False, min=6, not_empty=False)
577 admin = StringBoolean(if_missing=False) 71 )
72 password_confirmation = All(
73 v.ValidPassword(),
74 v.UnicodeString(strip=False, min=6, not_empty=False),
75 )
76 admin = v.StringBoolean(if_missing=False)
578 else: 77 else:
579 password = All(UnicodeString(strip=False, min=6, not_empty=True)) 78 password = All(
580 password_confirmation = All(UnicodeString(strip=False, min=6, 79 v.ValidPassword(),
581 not_empty=False)) 80 v.UnicodeString(strip=False, min=6, not_empty=True)
582 81 )
583 active = StringBoolean(if_missing=False) 82 password_confirmation = All(
584 name = UnicodeString(strip=True, min=1, not_empty=False) 83 v.ValidPassword(),
585 lastname = UnicodeString(strip=True, min=1, not_empty=False) 84 v.UnicodeString(strip=False, min=6, not_empty=False)
586 email = All(Email(not_empty=True), UniqSystemEmail(old_data)) 85 )
587 86
588 chained_validators = [ValidPasswordsMatch, ValidPassword] 87 active = v.StringBoolean(if_missing=False)
88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
91
92 chained_validators = [v.ValidPasswordsMatch()]
589 93
590 return _UserForm 94 return _UserForm
591 95
592 96
593 def UsersGroupForm(edit=False, old_data={}, available_members=[]): 97 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
594 class _UsersGroupForm(formencode.Schema): 98 class _UsersGroupForm(formencode.Schema):
595 allow_extra_fields = True 99 allow_extra_fields = True
596 filter_extra_fields = True 100 filter_extra_fields = True
597 101
598 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True), 102 users_group_name = All(
599 ValidUsersGroup(edit, old_data)) 103 v.UnicodeString(strip=True, min=1, not_empty=True),
600 104 v.ValidUsersGroup(edit, old_data)
601 users_group_active = StringBoolean(if_missing=False) 105 )
106
107 users_group_active = v.StringBoolean(if_missing=False)
602 108
603 if edit: 109 if edit:
604 users_group_members = OneOf(available_members, hideList=False, 110 users_group_members = v.OneOf(
111 available_members, hideList=False, testValueList=True,
112 if_missing=None, not_empty=False
113 )
114
115 return _UsersGroupForm
116
117
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
119 class _ReposGroupForm(formencode.Schema):
120 allow_extra_fields = True
121 filter_extra_fields = False
122
123 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
124 v.SlugifyName())
125 group_description = v.UnicodeString(strip=True, min=1,
126 not_empty=True)
127 group_parent_id = v.OneOf(available_groups, hideList=False,
605 testValueList=True, 128 testValueList=True,
606 if_missing=None, not_empty=False) 129 if_missing=None, not_empty=False)
607 130 enable_locking = v.StringBoolean(if_missing=False)
608 return _UsersGroupForm 131 chained_validators = [v.ValidReposGroup(edit, old_data),
609 132 v.ValidPerms('group')]
610
611 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
612 class _ReposGroupForm(formencode.Schema):
613 allow_extra_fields = True
614 filter_extra_fields = False
615
616 group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
617 SlugifyName())
618 group_description = UnicodeString(strip=True, min=1,
619 not_empty=True)
620 group_parent_id = OneOf(available_groups, hideList=False,
621 testValueList=True,
622 if_missing=None, not_empty=False)
623
624 chained_validators = [ValidReposGroup(edit, old_data), ValidPerms('group')]
625 133
626 return _ReposGroupForm 134 return _ReposGroupForm
627 135
628 136
629 def RegisterForm(edit=False, old_data={}): 137 def RegisterForm(edit=False, old_data={}):
630 class _RegisterForm(formencode.Schema): 138 class _RegisterForm(formencode.Schema):
631 allow_extra_fields = True 139 allow_extra_fields = True
632 filter_extra_fields = True 140 filter_extra_fields = True
633 username = All(ValidUsername(edit, old_data), 141 username = All(
634 UnicodeString(strip=True, min=1, not_empty=True)) 142 v.ValidUsername(edit, old_data),
635 password = All(UnicodeString(strip=False, min=6, not_empty=True)) 143 v.UnicodeString(strip=True, min=1, not_empty=True)
636 password_confirmation = All(UnicodeString(strip=False, min=6, not_empty=True)) 144 )
637 active = StringBoolean(if_missing=False) 145 password = All(
638 name = UnicodeString(strip=True, min=1, not_empty=False) 146 v.ValidPassword(),
639 lastname = UnicodeString(strip=True, min=1, not_empty=False) 147 v.UnicodeString(strip=False, min=6, not_empty=True)
640 email = All(Email(not_empty=True), UniqSystemEmail(old_data)) 148 )
641 149 password_confirmation = All(
642 chained_validators = [ValidPasswordsMatch, ValidPassword] 150 v.ValidPassword(),
151 v.UnicodeString(strip=False, min=6, not_empty=True)
152 )
153 active = v.StringBoolean(if_missing=False)
154 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
155 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
156 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
157
158 chained_validators = [v.ValidPasswordsMatch()]
643 159
644 return _RegisterForm 160 return _RegisterForm
645 161
646 162
647 def PasswordResetForm(): 163 def PasswordResetForm():
648 class _PasswordResetForm(formencode.Schema): 164 class _PasswordResetForm(formencode.Schema):
649 allow_extra_fields = True 165 allow_extra_fields = True
650 filter_extra_fields = True 166 filter_extra_fields = True
651 email = All(ValidSystemEmail(), Email(not_empty=True)) 167 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
652 return _PasswordResetForm 168 return _PasswordResetForm
653 169
654 170
655 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), 171 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
656 repo_groups=[]): 172 repo_groups=[], landing_revs=[]):
657 class _RepoForm(formencode.Schema): 173 class _RepoForm(formencode.Schema):
658 allow_extra_fields = True 174 allow_extra_fields = True
659 filter_extra_fields = False 175 filter_extra_fields = False
660 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), 176 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
661 SlugifyName()) 177 v.SlugifyName())
662 clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False)) 178 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
663 repo_group = OneOf(repo_groups, hideList=True) 179 repo_group = v.OneOf(repo_groups, hideList=True)
664 repo_type = OneOf(supported_backends) 180 repo_type = v.OneOf(supported_backends)
665 description = UnicodeString(strip=True, min=1, not_empty=True) 181 description = v.UnicodeString(strip=True, min=1, not_empty=False)
666 private = StringBoolean(if_missing=False) 182 private = v.StringBoolean(if_missing=False)
667 enable_statistics = StringBoolean(if_missing=False) 183 enable_statistics = v.StringBoolean(if_missing=False)
668 enable_downloads = StringBoolean(if_missing=False) 184 enable_downloads = v.StringBoolean(if_missing=False)
185 enable_locking = v.StringBoolean(if_missing=False)
186 landing_rev = v.OneOf(landing_revs, hideList=True)
669 187
670 if edit: 188 if edit:
671 #this is repo owner 189 #this is repo owner
672 user = All(UnicodeString(not_empty=True), ValidRepoUser) 190 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
673 191
674 chained_validators = [ValidCloneUri()(), 192 chained_validators = [v.ValidCloneUri(),
675 ValidRepoName(edit, old_data), 193 v.ValidRepoName(edit, old_data),
676 ValidPerms()] 194 v.ValidPerms()]
677 return _RepoForm 195 return _RepoForm
678 196
679 197
680 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), 198 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
681 repo_groups=[]): 199 repo_groups=[], landing_revs=[]):
682 class _RepoForkForm(formencode.Schema): 200 class _RepoForkForm(formencode.Schema):
683 allow_extra_fields = True 201 allow_extra_fields = True
684 filter_extra_fields = False 202 filter_extra_fields = False
685 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), 203 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
686 SlugifyName()) 204 v.SlugifyName())
687 repo_group = OneOf(repo_groups, hideList=True) 205 repo_group = v.OneOf(repo_groups, hideList=True)
688 repo_type = All(ValidForkType(old_data), OneOf(supported_backends)) 206 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
689 description = UnicodeString(strip=True, min=1, not_empty=True) 207 description = v.UnicodeString(strip=True, min=1, not_empty=True)
690 private = StringBoolean(if_missing=False) 208 private = v.StringBoolean(if_missing=False)
691 copy_permissions = StringBoolean(if_missing=False) 209 copy_permissions = v.StringBoolean(if_missing=False)
692 update_after_clone = StringBoolean(if_missing=False) 210 update_after_clone = v.StringBoolean(if_missing=False)
693 fork_parent_id = UnicodeString() 211 fork_parent_id = v.UnicodeString()
694 chained_validators = [ValidForkName(edit, old_data)] 212 chained_validators = [v.ValidForkName(edit, old_data)]
213 landing_rev = v.OneOf(landing_revs, hideList=True)
695 214
696 return _RepoForkForm 215 return _RepoForkForm
697 216
698 217
699 def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), 218 def RepoSettingsForm(edit=False, old_data={},
700 repo_groups=[]): 219 supported_backends=BACKENDS.keys(), repo_groups=[],
220 landing_revs=[]):
701 class _RepoForm(formencode.Schema): 221 class _RepoForm(formencode.Schema):
702 allow_extra_fields = True 222 allow_extra_fields = True
703 filter_extra_fields = False 223 filter_extra_fields = False
704 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), 224 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
705 SlugifyName()) 225 v.SlugifyName())
706 description = UnicodeString(strip=True, min=1, not_empty=True) 226 description = v.UnicodeString(strip=True, min=1, not_empty=True)
707 repo_group = OneOf(repo_groups, hideList=True) 227 repo_group = v.OneOf(repo_groups, hideList=True)
708 private = StringBoolean(if_missing=False) 228 private = v.StringBoolean(if_missing=False)
709 229 landing_rev = v.OneOf(landing_revs, hideList=True)
710 chained_validators = [ValidRepoName(edit, old_data), ValidPerms(), 230 chained_validators = [v.ValidRepoName(edit, old_data), v.ValidPerms(),
711 ValidSettings] 231 v.ValidSettings()]
712 return _RepoForm 232 return _RepoForm
713 233
714 234
715 def ApplicationSettingsForm(): 235 def ApplicationSettingsForm():
716 class _ApplicationSettingsForm(formencode.Schema): 236 class _ApplicationSettingsForm(formencode.Schema):
717 allow_extra_fields = True 237 allow_extra_fields = True
718 filter_extra_fields = False 238 filter_extra_fields = False
719 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True) 239 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
720 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True) 240 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
721 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False) 241 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
722 242
723 return _ApplicationSettingsForm 243 return _ApplicationSettingsForm
244
245
246 def ApplicationVisualisationForm():
247 class _ApplicationVisualisationForm(formencode.Schema):
248 allow_extra_fields = True
249 filter_extra_fields = False
250 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
251 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
252 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
253
254 return _ApplicationVisualisationForm
724 255
725 256
726 def ApplicationUiSettingsForm(): 257 def ApplicationUiSettingsForm():
727 class _ApplicationUiSettingsForm(formencode.Schema): 258 class _ApplicationUiSettingsForm(formencode.Schema):
728 allow_extra_fields = True 259 allow_extra_fields = True
729 filter_extra_fields = False 260 filter_extra_fields = False
730 web_push_ssl = OneOf(['true', 'false'], if_missing='false') 261 web_push_ssl = v.StringBoolean(if_missing=False)
731 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True)) 262 paths_root_path = All(
732 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False) 263 v.ValidPath(),
733 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False) 264 v.UnicodeString(strip=True, min=1, not_empty=True)
734 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False) 265 )
735 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False) 266 hooks_changegroup_update = v.StringBoolean(if_missing=False)
267 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
268 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
269 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
270
271 extensions_largefiles = v.StringBoolean(if_missing=False)
272 extensions_hgsubversion = v.StringBoolean(if_missing=False)
273 extensions_hggit = v.StringBoolean(if_missing=False)
736 274
737 return _ApplicationUiSettingsForm 275 return _ApplicationUiSettingsForm
738 276
739 277
740 def DefaultPermissionsForm(perms_choices, register_choices, create_choices): 278 def DefaultPermissionsForm(perms_choices, register_choices, create_choices,
279 fork_choices):
741 class _DefaultPermissionsForm(formencode.Schema): 280 class _DefaultPermissionsForm(formencode.Schema):
742 allow_extra_fields = True 281 allow_extra_fields = True
743 filter_extra_fields = True 282 filter_extra_fields = True
744 overwrite_default = StringBoolean(if_missing=False) 283 overwrite_default = v.StringBoolean(if_missing=False)
745 anonymous = OneOf(['True', 'False'], if_missing=False) 284 anonymous = v.StringBoolean(if_missing=False)
746 default_perm = OneOf(perms_choices) 285 default_perm = v.OneOf(perms_choices)
747 default_register = OneOf(register_choices) 286 default_register = v.OneOf(register_choices)
748 default_create = OneOf(create_choices) 287 default_create = v.OneOf(create_choices)
288 default_fork = v.OneOf(fork_choices)
749 289
750 return _DefaultPermissionsForm 290 return _DefaultPermissionsForm
751 291
752 292
753 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices, tls_kind_choices): 293 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
294 tls_kind_choices):
754 class _LdapSettingsForm(formencode.Schema): 295 class _LdapSettingsForm(formencode.Schema):
755 allow_extra_fields = True 296 allow_extra_fields = True
756 filter_extra_fields = True 297 filter_extra_fields = True
757 #pre_validators = [LdapLibValidator] 298 #pre_validators = [LdapLibValidator]
758 ldap_active = StringBoolean(if_missing=False) 299 ldap_active = v.StringBoolean(if_missing=False)
759 ldap_host = UnicodeString(strip=True,) 300 ldap_host = v.UnicodeString(strip=True,)
760 ldap_port = Number(strip=True,) 301 ldap_port = v.Number(strip=True,)
761 ldap_tls_kind = OneOf(tls_kind_choices) 302 ldap_tls_kind = v.OneOf(tls_kind_choices)
762 ldap_tls_reqcert = OneOf(tls_reqcert_choices) 303 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
763 ldap_dn_user = UnicodeString(strip=True,) 304 ldap_dn_user = v.UnicodeString(strip=True,)
764 ldap_dn_pass = UnicodeString(strip=True,) 305 ldap_dn_pass = v.UnicodeString(strip=True,)
765 ldap_base_dn = UnicodeString(strip=True,) 306 ldap_base_dn = v.UnicodeString(strip=True,)
766 ldap_filter = UnicodeString(strip=True,) 307 ldap_filter = v.UnicodeString(strip=True,)
767 ldap_search_scope = OneOf(search_scope_choices) 308 ldap_search_scope = v.OneOf(search_scope_choices)
768 ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,)) 309 ldap_attr_login = All(
769 ldap_attr_firstname = UnicodeString(strip=True,) 310 v.AttrLoginValidator(),
770 ldap_attr_lastname = UnicodeString(strip=True,) 311 v.UnicodeString(strip=True,)
771 ldap_attr_email = UnicodeString(strip=True,) 312 )
313 ldap_attr_firstname = v.UnicodeString(strip=True,)
314 ldap_attr_lastname = v.UnicodeString(strip=True,)
315 ldap_attr_email = v.UnicodeString(strip=True,)
772 316
773 return _LdapSettingsForm 317 return _LdapSettingsForm
318
319
320 def UserExtraEmailForm():
321 class _UserExtraEmailForm(formencode.Schema):
322 email = All(v.UniqSystemEmail(), v.Email)
323
324 return _UserExtraEmailForm
325
326
327 def PullRequestForm():
328 class _PullRequestForm(formencode.Schema):
329 allow_extra_fields = True
330 filter_extra_fields = True
331
332 user = v.UnicodeString(strip=True, required=True)
333 org_repo = v.UnicodeString(strip=True, required=True)
334 org_ref = v.UnicodeString(strip=True, required=True)
335 other_repo = v.UnicodeString(strip=True, required=True)
336 other_ref = v.UnicodeString(strip=True, required=True)
337 revisions = All(v.NotReviewedRevisions()(), v.UniqueList(not_empty=True))
338 review_members = v.UniqueList(not_empty=True)
339
340 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
341 pullrequest_desc = v.UnicodeString(strip=True, required=False)
342
343 return _PullRequestForm