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