##// END OF EJS Templates
allow underscores in usernames. Helps creating special internal users
marcink -
r3914:424b6c71 beta
parent child Browse files
Show More
@@ -1,827 +1,827 b''
1 1 """
2 2 Set of generic validators
3 3 """
4 4 import os
5 5 import re
6 6 import formencode
7 7 import logging
8 8 from collections import defaultdict
9 9 from pylons.i18n.translation import _
10 10 from webhelpers.pylonslib.secure_form import authentication_token
11 11
12 12 from formencode.validators import (
13 13 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
14 14 NotEmpty, IPAddress, CIDR, String, FancyValidator
15 15 )
16 16 from rhodecode.lib.compat import OrderedSet
17 17 from rhodecode.lib import ipaddr
18 18 from rhodecode.lib.utils import repo_name_slug
19 19 from rhodecode.lib.utils2 import safe_int, str2bool
20 20 from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
21 21 ChangesetStatus
22 22 from rhodecode.lib.exceptions import LdapImportError
23 23 from rhodecode.config.routing import ADMIN_PREFIX
24 24 from rhodecode.lib.auth import HasReposGroupPermissionAny, HasPermissionAny
25 25
26 26 # silence warnings and pylint
27 27 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \
28 28 NotEmpty, IPAddress, CIDR, String, FancyValidator
29 29
30 30 log = logging.getLogger(__name__)
31 31
32 32
33 33 class UniqueList(formencode.FancyValidator):
34 34 """
35 35 Unique List !
36 36 """
37 37 messages = dict(
38 38 empty=_('Value cannot be an empty list'),
39 39 missing_value=_('Value cannot be an empty list'),
40 40 )
41 41
42 42 def _to_python(self, value, state):
43 43 if isinstance(value, list):
44 44 return value
45 45 elif isinstance(value, set):
46 46 return list(value)
47 47 elif isinstance(value, tuple):
48 48 return list(value)
49 49 elif value is None:
50 50 return []
51 51 else:
52 52 return [value]
53 53
54 54 def empty_value(self, value):
55 55 return []
56 56
57 57
58 58 class StateObj(object):
59 59 """
60 60 this is needed to translate the messages using _() in validators
61 61 """
62 62 _ = staticmethod(_)
63 63
64 64
65 65 def M(self, key, state=None, **kwargs):
66 66 """
67 67 returns string from self.message based on given key,
68 68 passed kw params are used to substitute %(named)s params inside
69 69 translated strings
70 70
71 71 :param msg:
72 72 :param state:
73 73 """
74 74 if state is None:
75 75 state = StateObj()
76 76 else:
77 77 state._ = staticmethod(_)
78 78 #inject validator into state object
79 79 return self.message(key, state, **kwargs)
80 80
81 81
82 82 def ValidUsername(edit=False, old_data={}):
83 83 class _validator(formencode.validators.FancyValidator):
84 84 messages = {
85 85 'username_exists': _(u'Username "%(username)s" already exists'),
86 86 'system_invalid_username':
87 87 _(u'Username "%(username)s" is forbidden'),
88 88 'invalid_username':
89 89 _(u'Username may only contain alphanumeric characters '
90 90 'underscores, periods or dashes and must begin with '
91 'alphanumeric character')
91 'alphanumeric character or underscore')
92 92 }
93 93
94 94 def validate_python(self, value, state):
95 95 if value in ['default', 'new_user']:
96 96 msg = M(self, 'system_invalid_username', state, username=value)
97 97 raise formencode.Invalid(msg, value, state)
98 98 #check if user is unique
99 99 old_un = None
100 100 if edit:
101 101 old_un = User.get(old_data.get('user_id')).username
102 102
103 103 if old_un != value or not edit:
104 104 if User.get_by_username(value, case_insensitive=True):
105 105 msg = M(self, 'username_exists', state, username=value)
106 106 raise formencode.Invalid(msg, value, state)
107 107
108 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*$', value) is None:
108 if re.match(r'^[a-zA-Z0-9\_]{1}[a-zA-Z0-9\-\_\.]*$', value) is None:
109 109 msg = M(self, 'invalid_username', state)
110 110 raise formencode.Invalid(msg, value, state)
111 111 return _validator
112 112
113 113
114 114 def ValidRepoUser():
115 115 class _validator(formencode.validators.FancyValidator):
116 116 messages = {
117 117 'invalid_username': _(u'Username %(username)s is not valid')
118 118 }
119 119
120 120 def validate_python(self, value, state):
121 121 try:
122 122 User.query().filter(User.active == True)\
123 123 .filter(User.username == value).one()
124 124 except Exception:
125 125 msg = M(self, 'invalid_username', state, username=value)
126 126 raise formencode.Invalid(msg, value, state,
127 127 error_dict=dict(username=msg)
128 128 )
129 129
130 130 return _validator
131 131
132 132
133 133 def ValidUserGroup(edit=False, old_data={}):
134 134 class _validator(formencode.validators.FancyValidator):
135 135 messages = {
136 136 'invalid_group': _(u'Invalid user group name'),
137 137 'group_exist': _(u'User group "%(usergroup)s" already exists'),
138 138 'invalid_usergroup_name':
139 139 _(u'user group name may only contain alphanumeric '
140 140 'characters underscores, periods or dashes and must begin '
141 141 'with alphanumeric character')
142 142 }
143 143
144 144 def validate_python(self, value, state):
145 145 if value in ['default']:
146 146 msg = M(self, 'invalid_group', state)
147 147 raise formencode.Invalid(msg, value, state,
148 148 error_dict=dict(users_group_name=msg)
149 149 )
150 150 #check if group is unique
151 151 old_ugname = None
152 152 if edit:
153 153 old_id = old_data.get('users_group_id')
154 154 old_ugname = UserGroup.get(old_id).users_group_name
155 155
156 156 if old_ugname != value or not edit:
157 157 is_existing_group = UserGroup.get_by_group_name(value,
158 158 case_insensitive=True)
159 159 if is_existing_group:
160 160 msg = M(self, 'group_exist', state, usergroup=value)
161 161 raise formencode.Invalid(msg, value, state,
162 162 error_dict=dict(users_group_name=msg)
163 163 )
164 164
165 165 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
166 166 msg = M(self, 'invalid_usergroup_name', state)
167 167 raise formencode.Invalid(msg, value, state,
168 168 error_dict=dict(users_group_name=msg)
169 169 )
170 170
171 171 return _validator
172 172
173 173
174 174 def ValidReposGroup(edit=False, old_data={}):
175 175 class _validator(formencode.validators.FancyValidator):
176 176 messages = {
177 177 'group_parent_id': _(u'Cannot assign this group as parent'),
178 178 'group_exists': _(u'Group "%(group_name)s" already exists'),
179 179 'repo_exists':
180 180 _(u'Repository with name "%(group_name)s" already exists')
181 181 }
182 182
183 183 def validate_python(self, value, state):
184 184 # TODO WRITE VALIDATIONS
185 185 group_name = value.get('group_name')
186 186 group_parent_id = value.get('group_parent_id')
187 187
188 188 # slugify repo group just in case :)
189 189 slug = repo_name_slug(group_name)
190 190
191 191 # check for parent of self
192 192 parent_of_self = lambda: (
193 193 old_data['group_id'] == int(group_parent_id)
194 194 if group_parent_id else False
195 195 )
196 196 if edit and parent_of_self():
197 197 msg = M(self, 'group_parent_id', state)
198 198 raise formencode.Invalid(msg, value, state,
199 199 error_dict=dict(group_parent_id=msg)
200 200 )
201 201
202 202 old_gname = None
203 203 if edit:
204 204 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
205 205
206 206 if old_gname != group_name or not edit:
207 207
208 208 # check group
209 209 gr = RepoGroup.query()\
210 210 .filter(RepoGroup.group_name == slug)\
211 211 .filter(RepoGroup.group_parent_id == group_parent_id)\
212 212 .scalar()
213 213
214 214 if gr:
215 215 msg = M(self, 'group_exists', state, group_name=slug)
216 216 raise formencode.Invalid(msg, value, state,
217 217 error_dict=dict(group_name=msg)
218 218 )
219 219
220 220 # check for same repo
221 221 repo = Repository.query()\
222 222 .filter(Repository.repo_name == slug)\
223 223 .scalar()
224 224
225 225 if repo:
226 226 msg = M(self, 'repo_exists', state, group_name=slug)
227 227 raise formencode.Invalid(msg, value, state,
228 228 error_dict=dict(group_name=msg)
229 229 )
230 230
231 231 return _validator
232 232
233 233
234 234 def ValidPassword():
235 235 class _validator(formencode.validators.FancyValidator):
236 236 messages = {
237 237 'invalid_password':
238 238 _(u'Invalid characters (non-ascii) in password')
239 239 }
240 240
241 241 def validate_python(self, value, state):
242 242 try:
243 243 (value or '').decode('ascii')
244 244 except UnicodeError:
245 245 msg = M(self, 'invalid_password', state)
246 246 raise formencode.Invalid(msg, value, state,)
247 247 return _validator
248 248
249 249
250 250 def ValidPasswordsMatch():
251 251 class _validator(formencode.validators.FancyValidator):
252 252 messages = {
253 253 'password_mismatch': _(u'Passwords do not match'),
254 254 }
255 255
256 256 def validate_python(self, value, state):
257 257
258 258 pass_val = value.get('password') or value.get('new_password')
259 259 if pass_val != value['password_confirmation']:
260 260 msg = M(self, 'password_mismatch', state)
261 261 raise formencode.Invalid(msg, value, state,
262 262 error_dict=dict(password_confirmation=msg)
263 263 )
264 264 return _validator
265 265
266 266
267 267 def ValidAuth():
268 268 class _validator(formencode.validators.FancyValidator):
269 269 messages = {
270 270 'invalid_password': _(u'invalid password'),
271 271 'invalid_username': _(u'invalid user name'),
272 272 'disabled_account': _(u'Your account is disabled')
273 273 }
274 274
275 275 def validate_python(self, value, state):
276 276 from rhodecode.lib.auth import authenticate
277 277
278 278 password = value['password']
279 279 username = value['username']
280 280
281 281 if not authenticate(username, password):
282 282 user = User.get_by_username(username)
283 283 if user and not user.active:
284 284 log.warning('user %s is disabled' % username)
285 285 msg = M(self, 'disabled_account', state)
286 286 raise formencode.Invalid(msg, value, state,
287 287 error_dict=dict(username=msg)
288 288 )
289 289 else:
290 290 log.warning('user %s failed to authenticate' % username)
291 291 msg = M(self, 'invalid_username', state)
292 292 msg2 = M(self, 'invalid_password', state)
293 293 raise formencode.Invalid(msg, value, state,
294 294 error_dict=dict(username=msg, password=msg2)
295 295 )
296 296 return _validator
297 297
298 298
299 299 def ValidAuthToken():
300 300 class _validator(formencode.validators.FancyValidator):
301 301 messages = {
302 302 'invalid_token': _(u'Token mismatch')
303 303 }
304 304
305 305 def validate_python(self, value, state):
306 306 if value != authentication_token():
307 307 msg = M(self, 'invalid_token', state)
308 308 raise formencode.Invalid(msg, value, state)
309 309 return _validator
310 310
311 311
312 312 def ValidRepoName(edit=False, old_data={}):
313 313 class _validator(formencode.validators.FancyValidator):
314 314 messages = {
315 315 'invalid_repo_name':
316 316 _(u'Repository name %(repo)s is disallowed'),
317 317 'repository_exists':
318 318 _(u'Repository named %(repo)s already exists'),
319 319 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
320 320 'exists in group "%(group)s"'),
321 321 'same_group_exists': _(u'Repository group with name "%(repo)s" '
322 322 'already exists')
323 323 }
324 324
325 325 def _to_python(self, value, state):
326 326 repo_name = repo_name_slug(value.get('repo_name', ''))
327 327 repo_group = value.get('repo_group')
328 328 if repo_group:
329 329 gr = RepoGroup.get(repo_group)
330 330 group_path = gr.full_path
331 331 group_name = gr.group_name
332 332 # value needs to be aware of group name in order to check
333 333 # db key This is an actual just the name to store in the
334 334 # database
335 335 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
336 336 else:
337 337 group_name = group_path = ''
338 338 repo_name_full = repo_name
339 339
340 340 value['repo_name'] = repo_name
341 341 value['repo_name_full'] = repo_name_full
342 342 value['group_path'] = group_path
343 343 value['group_name'] = group_name
344 344 return value
345 345
346 346 def validate_python(self, value, state):
347 347
348 348 repo_name = value.get('repo_name')
349 349 repo_name_full = value.get('repo_name_full')
350 350 group_path = value.get('group_path')
351 351 group_name = value.get('group_name')
352 352
353 353 if repo_name in [ADMIN_PREFIX, '']:
354 354 msg = M(self, 'invalid_repo_name', state, repo=repo_name)
355 355 raise formencode.Invalid(msg, value, state,
356 356 error_dict=dict(repo_name=msg)
357 357 )
358 358
359 359 rename = old_data.get('repo_name') != repo_name_full
360 360 create = not edit
361 361 if rename or create:
362 362
363 363 if group_path != '':
364 364 if Repository.get_by_repo_name(repo_name_full):
365 365 msg = M(self, 'repository_in_group_exists', state,
366 366 repo=repo_name, group=group_name)
367 367 raise formencode.Invalid(msg, value, state,
368 368 error_dict=dict(repo_name=msg)
369 369 )
370 370 elif RepoGroup.get_by_group_name(repo_name_full):
371 371 msg = M(self, 'same_group_exists', state,
372 372 repo=repo_name)
373 373 raise formencode.Invalid(msg, value, state,
374 374 error_dict=dict(repo_name=msg)
375 375 )
376 376
377 377 elif Repository.get_by_repo_name(repo_name_full):
378 378 msg = M(self, 'repository_exists', state,
379 379 repo=repo_name)
380 380 raise formencode.Invalid(msg, value, state,
381 381 error_dict=dict(repo_name=msg)
382 382 )
383 383 return value
384 384 return _validator
385 385
386 386
387 387 def ValidForkName(*args, **kwargs):
388 388 return ValidRepoName(*args, **kwargs)
389 389
390 390
391 391 def SlugifyName():
392 392 class _validator(formencode.validators.FancyValidator):
393 393
394 394 def _to_python(self, value, state):
395 395 return repo_name_slug(value)
396 396
397 397 def validate_python(self, value, state):
398 398 pass
399 399
400 400 return _validator
401 401
402 402
403 403 def ValidCloneUri():
404 404 from rhodecode.lib.utils import make_ui
405 405
406 406 def url_handler(repo_type, url, ui=None):
407 407 if repo_type == 'hg':
408 408 from rhodecode.lib.vcs.backends.hg.repository import MercurialRepository
409 409 from mercurial.httppeer import httppeer
410 410 if url.startswith('http'):
411 411 ## initially check if it's at least the proper URL
412 412 ## or does it pass basic auth
413 413 MercurialRepository._check_url(url)
414 414 httppeer(ui, url)._capabilities()
415 415 elif url.startswith('svn+http'):
416 416 from hgsubversion.svnrepo import svnremoterepo
417 417 svnremoterepo(ui, url).capabilities
418 418 elif url.startswith('git+http'):
419 419 raise NotImplementedError()
420 420 else:
421 421 raise Exception('clone from URI %s not allowed' % (url))
422 422
423 423 elif repo_type == 'git':
424 424 from rhodecode.lib.vcs.backends.git.repository import GitRepository
425 425 if url.startswith('http'):
426 426 ## initially check if it's at least the proper URL
427 427 ## or does it pass basic auth
428 428 GitRepository._check_url(url)
429 429 elif url.startswith('svn+http'):
430 430 raise NotImplementedError()
431 431 elif url.startswith('hg+http'):
432 432 raise NotImplementedError()
433 433 else:
434 434 raise Exception('clone from URI %s not allowed' % (url))
435 435
436 436 class _validator(formencode.validators.FancyValidator):
437 437 messages = {
438 438 'clone_uri': _(u'invalid clone url'),
439 439 'invalid_clone_uri': _(u'Invalid clone url, provide a '
440 440 'valid clone http(s)/svn+http(s) url')
441 441 }
442 442
443 443 def validate_python(self, value, state):
444 444 repo_type = value.get('repo_type')
445 445 url = value.get('clone_uri')
446 446
447 447 if not url:
448 448 pass
449 449 else:
450 450 try:
451 451 url_handler(repo_type, url, make_ui('db', clear_session=False))
452 452 except Exception:
453 453 log.exception('Url validation failed')
454 454 msg = M(self, 'clone_uri')
455 455 raise formencode.Invalid(msg, value, state,
456 456 error_dict=dict(clone_uri=msg)
457 457 )
458 458 return _validator
459 459
460 460
461 461 def ValidForkType(old_data={}):
462 462 class _validator(formencode.validators.FancyValidator):
463 463 messages = {
464 464 'invalid_fork_type': _(u'Fork have to be the same type as parent')
465 465 }
466 466
467 467 def validate_python(self, value, state):
468 468 if old_data['repo_type'] != value:
469 469 msg = M(self, 'invalid_fork_type', state)
470 470 raise formencode.Invalid(msg, value, state,
471 471 error_dict=dict(repo_type=msg)
472 472 )
473 473 return _validator
474 474
475 475
476 476 def CanWriteGroup(old_data=None):
477 477 class _validator(formencode.validators.FancyValidator):
478 478 messages = {
479 479 'permission_denied': _(u"You don't have permissions "
480 480 "to create repository in this group"),
481 481 'permission_denied_root': _(u"no permission to create repository "
482 482 "in root location")
483 483 }
484 484
485 485 def _to_python(self, value, state):
486 486 #root location
487 487 if value in [-1, "-1"]:
488 488 return None
489 489 return value
490 490
491 491 def validate_python(self, value, state):
492 492 gr = RepoGroup.get(value)
493 493 gr_name = gr.group_name if gr else None # None means ROOT location
494 494 val = HasReposGroupPermissionAny('group.write', 'group.admin')
495 495 can_create_repos = HasPermissionAny('hg.admin', 'hg.create.repository')
496 496 forbidden = not val(gr_name, 'can write into group validator')
497 497 value_changed = True # old_data['repo_group'].get('group_id') != safe_int(value)
498 498 if value_changed: # do check if we changed the value
499 499 #parent group need to be existing
500 500 if gr and forbidden:
501 501 msg = M(self, 'permission_denied', state)
502 502 raise formencode.Invalid(msg, value, state,
503 503 error_dict=dict(repo_type=msg)
504 504 )
505 505 ## check if we can write to root location !
506 506 elif gr is None and not can_create_repos():
507 507 msg = M(self, 'permission_denied_root', state)
508 508 raise formencode.Invalid(msg, value, state,
509 509 error_dict=dict(repo_type=msg)
510 510 )
511 511
512 512 return _validator
513 513
514 514
515 515 def CanCreateGroup(can_create_in_root=False):
516 516 class _validator(formencode.validators.FancyValidator):
517 517 messages = {
518 518 'permission_denied': _(u"You don't have permissions "
519 519 "to create a group in this location")
520 520 }
521 521
522 522 def to_python(self, value, state):
523 523 #root location
524 524 if value in [-1, "-1"]:
525 525 return None
526 526 return value
527 527
528 528 def validate_python(self, value, state):
529 529 gr = RepoGroup.get(value)
530 530 gr_name = gr.group_name if gr else None # None means ROOT location
531 531
532 532 if can_create_in_root and gr is None:
533 533 #we can create in root, we're fine no validations required
534 534 return
535 535
536 536 forbidden_in_root = gr is None and not can_create_in_root
537 537 val = HasReposGroupPermissionAny('group.admin')
538 538 forbidden = not val(gr_name, 'can create group validator')
539 539 if forbidden_in_root or forbidden:
540 540 msg = M(self, 'permission_denied', state)
541 541 raise formencode.Invalid(msg, value, state,
542 542 error_dict=dict(group_parent_id=msg)
543 543 )
544 544
545 545 return _validator
546 546
547 547
548 548 def ValidPerms(type_='repo'):
549 549 if type_ == 'repo_group':
550 550 EMPTY_PERM = 'group.none'
551 551 elif type_ == 'repo':
552 552 EMPTY_PERM = 'repository.none'
553 553 elif type_ == 'user_group':
554 554 EMPTY_PERM = 'usergroup.none'
555 555
556 556 class _validator(formencode.validators.FancyValidator):
557 557 messages = {
558 558 'perm_new_member_name':
559 559 _(u'This username or user group name is not valid')
560 560 }
561 561
562 562 def to_python(self, value, state):
563 563 perms_update = OrderedSet()
564 564 perms_new = OrderedSet()
565 565 # build a list of permission to update and new permission to create
566 566
567 567 #CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using
568 568 new_perms_group = defaultdict(dict)
569 569 for k, v in value.copy().iteritems():
570 570 if k.startswith('perm_new_member'):
571 571 del value[k]
572 572 _type, part = k.split('perm_new_member_')
573 573 args = part.split('_')
574 574 if len(args) == 1:
575 575 new_perms_group[args[0]]['perm'] = v
576 576 elif len(args) == 2:
577 577 _key, pos = args
578 578 new_perms_group[pos][_key] = v
579 579
580 580 # fill new permissions in order of how they were added
581 581 for k in sorted(map(int, new_perms_group.keys())):
582 582 perm_dict = new_perms_group[str(k)]
583 583 new_member = perm_dict.get('name')
584 584 new_perm = perm_dict.get('perm')
585 585 new_type = perm_dict.get('type')
586 586 if new_member and new_perm and new_type:
587 587 perms_new.add((new_member, new_perm, new_type))
588 588
589 589 for k, v in value.iteritems():
590 590 if k.startswith('u_perm_') or k.startswith('g_perm_'):
591 591 member = k[7:]
592 592 t = {'u': 'user',
593 593 'g': 'users_group'
594 594 }[k[0]]
595 595 if member == 'default':
596 596 if str2bool(value.get('repo_private')):
597 597 # set none for default when updating to
598 598 # private repo protects agains form manipulation
599 599 v = EMPTY_PERM
600 600 perms_update.add((member, v, t))
601 601
602 602 value['perms_updates'] = list(perms_update)
603 603 value['perms_new'] = list(perms_new)
604 604
605 605 # update permissions
606 606 for k, v, t in perms_new:
607 607 try:
608 608 if t is 'user':
609 609 self.user_db = User.query()\
610 610 .filter(User.active == True)\
611 611 .filter(User.username == k).one()
612 612 if t is 'users_group':
613 613 self.user_db = UserGroup.query()\
614 614 .filter(UserGroup.users_group_active == True)\
615 615 .filter(UserGroup.users_group_name == k).one()
616 616
617 617 except Exception:
618 618 log.exception('Updated permission failed')
619 619 msg = M(self, 'perm_new_member_type', state)
620 620 raise formencode.Invalid(msg, value, state,
621 621 error_dict=dict(perm_new_member_name=msg)
622 622 )
623 623 return value
624 624 return _validator
625 625
626 626
627 627 def ValidSettings():
628 628 class _validator(formencode.validators.FancyValidator):
629 629 def _to_python(self, value, state):
630 630 # settings form for users that are not admin
631 631 # can't edit certain parameters, it's extra backup if they mangle
632 632 # with forms
633 633
634 634 forbidden_params = [
635 635 'user', 'repo_type', 'repo_enable_locking',
636 636 'repo_enable_downloads', 'repo_enable_statistics'
637 637 ]
638 638
639 639 for param in forbidden_params:
640 640 if param in value:
641 641 del value[param]
642 642 return value
643 643
644 644 def validate_python(self, value, state):
645 645 pass
646 646 return _validator
647 647
648 648
649 649 def ValidPath():
650 650 class _validator(formencode.validators.FancyValidator):
651 651 messages = {
652 652 'invalid_path': _(u'This is not a valid path')
653 653 }
654 654
655 655 def validate_python(self, value, state):
656 656 if not os.path.isdir(value):
657 657 msg = M(self, 'invalid_path', state)
658 658 raise formencode.Invalid(msg, value, state,
659 659 error_dict=dict(paths_root_path=msg)
660 660 )
661 661 return _validator
662 662
663 663
664 664 def UniqSystemEmail(old_data={}):
665 665 class _validator(formencode.validators.FancyValidator):
666 666 messages = {
667 667 'email_taken': _(u'This e-mail address is already taken')
668 668 }
669 669
670 670 def _to_python(self, value, state):
671 671 return value.lower()
672 672
673 673 def validate_python(self, value, state):
674 674 if (old_data.get('email') or '').lower() != value:
675 675 user = User.get_by_email(value, case_insensitive=True)
676 676 if user:
677 677 msg = M(self, 'email_taken', state)
678 678 raise formencode.Invalid(msg, value, state,
679 679 error_dict=dict(email=msg)
680 680 )
681 681 return _validator
682 682
683 683
684 684 def ValidSystemEmail():
685 685 class _validator(formencode.validators.FancyValidator):
686 686 messages = {
687 687 'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
688 688 }
689 689
690 690 def _to_python(self, value, state):
691 691 return value.lower()
692 692
693 693 def validate_python(self, value, state):
694 694 user = User.get_by_email(value, case_insensitive=True)
695 695 if user is None:
696 696 msg = M(self, 'non_existing_email', state, email=value)
697 697 raise formencode.Invalid(msg, value, state,
698 698 error_dict=dict(email=msg)
699 699 )
700 700
701 701 return _validator
702 702
703 703
704 704 def LdapLibValidator():
705 705 class _validator(formencode.validators.FancyValidator):
706 706 messages = {
707 707
708 708 }
709 709
710 710 def validate_python(self, value, state):
711 711 try:
712 712 import ldap
713 713 ldap # pyflakes silence !
714 714 except ImportError:
715 715 raise LdapImportError()
716 716
717 717 return _validator
718 718
719 719
720 720 def AttrLoginValidator():
721 721 class _validator(formencode.validators.FancyValidator):
722 722 messages = {
723 723 'invalid_cn':
724 724 _(u'The LDAP Login attribute of the CN must be specified - '
725 725 'this is the name of the attribute that is equivalent '
726 726 'to "username"')
727 727 }
728 728 messages['empty'] = messages['invalid_cn']
729 729
730 730 return _validator
731 731
732 732
733 733 def NotReviewedRevisions(repo_id):
734 734 class _validator(formencode.validators.FancyValidator):
735 735 messages = {
736 736 'rev_already_reviewed':
737 737 _(u'Revisions %(revs)s are already part of pull request '
738 738 'or have set status')
739 739 }
740 740
741 741 def validate_python(self, value, state):
742 742 # check revisions if they are not reviewed, or a part of another
743 743 # pull request
744 744 statuses = ChangesetStatus.query()\
745 745 .filter(ChangesetStatus.revision.in_(value))\
746 746 .filter(ChangesetStatus.repo_id == repo_id)\
747 747 .all()
748 748
749 749 errors = []
750 750 for cs in statuses:
751 751 if cs.pull_request_id:
752 752 errors.append(['pull_req', cs.revision[:12]])
753 753 elif cs.status:
754 754 errors.append(['status', cs.revision[:12]])
755 755
756 756 if errors:
757 757 revs = ','.join([x[1] for x in errors])
758 758 msg = M(self, 'rev_already_reviewed', state, revs=revs)
759 759 raise formencode.Invalid(msg, value, state,
760 760 error_dict=dict(revisions=revs)
761 761 )
762 762
763 763 return _validator
764 764
765 765
766 766 def ValidIp():
767 767 class _validator(CIDR):
768 768 messages = dict(
769 769 badFormat=_('Please enter a valid IPv4 or IpV6 address'),
770 770 illegalBits=_('The network size (bits) must be within the range'
771 771 ' of 0-32 (not %(bits)r)')
772 772 )
773 773
774 774 def to_python(self, value, state):
775 775 v = super(_validator, self).to_python(value, state)
776 776 v = v.strip()
777 777 net = ipaddr.IPNetwork(address=v)
778 778 if isinstance(net, ipaddr.IPv4Network):
779 779 #if IPv4 doesn't end with a mask, add /32
780 780 if '/' not in value:
781 781 v += '/32'
782 782 if isinstance(net, ipaddr.IPv6Network):
783 783 #if IPv6 doesn't end with a mask, add /128
784 784 if '/' not in value:
785 785 v += '/128'
786 786 return v
787 787
788 788 def validate_python(self, value, state):
789 789 try:
790 790 addr = value.strip()
791 791 #this raises an ValueError if address is not IpV4 or IpV6
792 792 ipaddr.IPNetwork(address=addr)
793 793 except ValueError:
794 794 raise formencode.Invalid(self.message('badFormat', state),
795 795 value, state)
796 796
797 797 return _validator
798 798
799 799
800 800 def FieldKey():
801 801 class _validator(formencode.validators.FancyValidator):
802 802 messages = dict(
803 803 badFormat=_('Key name can only consist of letters, '
804 804 'underscore, dash or numbers')
805 805 )
806 806
807 807 def validate_python(self, value, state):
808 808 if not re.match('[a-zA-Z0-9_-]+$', value):
809 809 raise formencode.Invalid(self.message('badFormat', state),
810 810 value, state)
811 811 return _validator
812 812
813 813
814 814 def BasePath():
815 815 class _validator(formencode.validators.FancyValidator):
816 816 messages = dict(
817 817 badPath=_('Filename cannot be inside a directory')
818 818 )
819 819
820 820 def _to_python(self, value, state):
821 821 return value
822 822
823 823 def validate_python(self, value, state):
824 824 if value != os.path.basename(value):
825 825 raise formencode.Invalid(self.message('badPath', state),
826 826 value, state)
827 827 return _validator
General Comments 0
You need to be logged in to leave comments. Login now