##// END OF EJS Templates
remove redundant logic
domruf -
r2701:24c5d902 beta
parent child Browse files
Show More
@@ -1,608 +1,590 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 pylons.i18n.translation import _
9 9 from webhelpers.pylonslib.secure_form import authentication_token
10 10
11 11 from formencode.validators import (
12 12 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set
13 13 )
14 14
15 15 from rhodecode.lib.utils import repo_name_slug
16 16 from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User
17 17 from rhodecode.lib.exceptions import LdapImportError
18 18 from rhodecode.config.routing import ADMIN_PREFIX
19 19 # silence warnings and pylint
20 20 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set
21 21
22 22 log = logging.getLogger(__name__)
23 23
24 24
25 25 class StateObj(object):
26 26 """
27 27 this is needed to translate the messages using _() in validators
28 28 """
29 29 _ = staticmethod(_)
30 30
31 31
32 32 def M(self, key, state=None, **kwargs):
33 33 """
34 34 returns string from self.message based on given key,
35 35 passed kw params are used to substitute %(named)s params inside
36 36 translated strings
37 37
38 38 :param msg:
39 39 :param state:
40 40 """
41 41 if state is None:
42 42 state = StateObj()
43 43 else:
44 44 state._ = staticmethod(_)
45 45 #inject validator into state object
46 46 return self.message(key, state, **kwargs)
47 47
48 48
49 49 def ValidUsername(edit=False, old_data={}):
50 50 class _validator(formencode.validators.FancyValidator):
51 51 messages = {
52 52 'username_exists': _(u'Username "%(username)s" already exists'),
53 53 'system_invalid_username':
54 54 _(u'Username "%(username)s" is forbidden'),
55 55 'invalid_username':
56 56 _(u'Username may only contain alphanumeric characters '
57 57 'underscores, periods or dashes and must begin with '
58 58 'alphanumeric character')
59 59 }
60 60
61 61 def validate_python(self, value, state):
62 62 if value in ['default', 'new_user']:
63 63 msg = M(self, 'system_invalid_username', state, username=value)
64 64 raise formencode.Invalid(msg, value, state)
65 65 #check if user is unique
66 66 old_un = None
67 67 if edit:
68 68 old_un = User.get(old_data.get('user_id')).username
69 69
70 70 if old_un != value or not edit:
71 71 if User.get_by_username(value, case_insensitive=True):
72 72 msg = M(self, 'username_exists', state, username=value)
73 73 raise formencode.Invalid(msg, value, state)
74 74
75 75 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
76 76 msg = M(self, 'invalid_username', state)
77 77 raise formencode.Invalid(msg, value, state)
78 78 return _validator
79 79
80 80
81 81 def ValidRepoUser():
82 82 class _validator(formencode.validators.FancyValidator):
83 83 messages = {
84 84 'invalid_username': _(u'Username %(username)s is not valid')
85 85 }
86 86
87 87 def validate_python(self, value, state):
88 88 try:
89 89 User.query().filter(User.active == True)\
90 90 .filter(User.username == value).one()
91 91 except Exception:
92 92 msg = M(self, 'invalid_username', state, username=value)
93 93 raise formencode.Invalid(msg, value, state,
94 94 error_dict=dict(username=msg)
95 95 )
96 96
97 97 return _validator
98 98
99 99
100 100 def ValidUsersGroup(edit=False, old_data={}):
101 101 class _validator(formencode.validators.FancyValidator):
102 102 messages = {
103 103 'invalid_group': _(u'Invalid users group name'),
104 104 'group_exist': _(u'Users group "%(usersgroup)s" already exists'),
105 105 'invalid_usersgroup_name':
106 106 _(u'users group name may only contain alphanumeric '
107 107 'characters underscores, periods or dashes and must begin '
108 108 'with alphanumeric character')
109 109 }
110 110
111 111 def validate_python(self, value, state):
112 112 if value in ['default']:
113 113 msg = M(self, 'invalid_group', state)
114 114 raise formencode.Invalid(msg, value, state,
115 115 error_dict=dict(users_group_name=msg)
116 116 )
117 117 #check if group is unique
118 118 old_ugname = None
119 119 if edit:
120 120 old_id = old_data.get('users_group_id')
121 121 old_ugname = UsersGroup.get(old_id).users_group_name
122 122
123 123 if old_ugname != value or not edit:
124 124 is_existing_group = UsersGroup.get_by_group_name(value,
125 125 case_insensitive=True)
126 126 if is_existing_group:
127 127 msg = M(self, 'group_exist', state, usersgroup=value)
128 128 raise formencode.Invalid(msg, value, state,
129 129 error_dict=dict(users_group_name=msg)
130 130 )
131 131
132 132 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
133 133 msg = M(self, 'invalid_usersgroup_name', state)
134 134 raise formencode.Invalid(msg, value, state,
135 135 error_dict=dict(users_group_name=msg)
136 136 )
137 137
138 138 return _validator
139 139
140 140
141 141 def ValidReposGroup(edit=False, old_data={}):
142 142 class _validator(formencode.validators.FancyValidator):
143 143 messages = {
144 144 'group_parent_id': _(u'Cannot assign this group as parent'),
145 145 'group_exists': _(u'Group "%(group_name)s" already exists'),
146 146 'repo_exists':
147 147 _(u'Repository with name "%(group_name)s" already exists')
148 148 }
149 149
150 150 def validate_python(self, value, state):
151 151 # TODO WRITE VALIDATIONS
152 152 group_name = value.get('group_name')
153 153 group_parent_id = value.get('group_parent_id')
154 154
155 155 # slugify repo group just in case :)
156 156 slug = repo_name_slug(group_name)
157 157
158 158 # check for parent of self
159 159 parent_of_self = lambda: (
160 160 old_data['group_id'] == int(group_parent_id)
161 161 if group_parent_id else False
162 162 )
163 163 if edit and parent_of_self():
164 164 msg = M(self, 'group_parent_id', state)
165 165 raise formencode.Invalid(msg, value, state,
166 166 error_dict=dict(group_parent_id=msg)
167 167 )
168 168
169 169 old_gname = None
170 170 if edit:
171 171 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
172 172
173 173 if old_gname != group_name or not edit:
174 174
175 175 # check group
176 176 gr = RepoGroup.query()\
177 177 .filter(RepoGroup.group_name == slug)\
178 178 .filter(RepoGroup.group_parent_id == group_parent_id)\
179 179 .scalar()
180 180
181 181 if gr:
182 182 msg = M(self, 'group_exists', state, group_name=slug)
183 183 raise formencode.Invalid(msg, value, state,
184 184 error_dict=dict(group_name=msg)
185 185 )
186 186
187 187 # check for same repo
188 188 repo = Repository.query()\
189 189 .filter(Repository.repo_name == slug)\
190 190 .scalar()
191 191
192 192 if repo:
193 193 msg = M(self, 'repo_exists', state, group_name=slug)
194 194 raise formencode.Invalid(msg, value, state,
195 195 error_dict=dict(group_name=msg)
196 196 )
197 197
198 198 return _validator
199 199
200 200
201 201 def ValidPassword():
202 202 class _validator(formencode.validators.FancyValidator):
203 203 messages = {
204 204 'invalid_password':
205 205 _(u'Invalid characters (non-ascii) in password')
206 206 }
207 207
208 208 def validate_python(self, value, state):
209 209 try:
210 210 (value or '').decode('ascii')
211 211 except UnicodeError:
212 212 msg = M(self, 'invalid_password', state)
213 213 raise formencode.Invalid(msg, value, state,)
214 214 return _validator
215 215
216 216
217 217 def ValidPasswordsMatch():
218 218 class _validator(formencode.validators.FancyValidator):
219 219 messages = {
220 220 'password_mismatch': _(u'Passwords do not match'),
221 221 }
222 222
223 223 def validate_python(self, value, state):
224 224
225 225 pass_val = value.get('password') or value.get('new_password')
226 226 if pass_val != value['password_confirmation']:
227 227 msg = M(self, 'password_mismatch', state)
228 228 raise formencode.Invalid(msg, value, state,
229 229 error_dict=dict(password_confirmation=msg)
230 230 )
231 231 return _validator
232 232
233 233
234 234 def ValidAuth():
235 235 class _validator(formencode.validators.FancyValidator):
236 236 messages = {
237 237 'invalid_password': _(u'invalid password'),
238 238 'invalid_username': _(u'invalid user name'),
239 239 'disabled_account': _(u'Your account is disabled')
240 240 }
241 241
242 242 def validate_python(self, value, state):
243 243 from rhodecode.lib.auth import authenticate
244 244
245 245 password = value['password']
246 246 username = value['username']
247 247
248 248 if not authenticate(username, password):
249 249 user = User.get_by_username(username)
250 250 if user and user.active is False:
251 251 log.warning('user %s is disabled' % username)
252 252 msg = M(self, 'disabled_account', state)
253 253 raise formencode.Invalid(msg, value, state,
254 254 error_dict=dict(username=msg)
255 255 )
256 256 else:
257 257 log.warning('user %s failed to authenticate' % username)
258 258 msg = M(self, 'invalid_username', state)
259 259 msg2 = M(self, 'invalid_password', state)
260 260 raise formencode.Invalid(msg, value, state,
261 261 error_dict=dict(username=msg, password=msg2)
262 262 )
263 263 return _validator
264 264
265 265
266 266 def ValidAuthToken():
267 267 class _validator(formencode.validators.FancyValidator):
268 268 messages = {
269 269 'invalid_token': _(u'Token mismatch')
270 270 }
271 271
272 272 def validate_python(self, value, state):
273 273 if value != authentication_token():
274 274 msg = M(self, 'invalid_token', state)
275 275 raise formencode.Invalid(msg, value, state)
276 276 return _validator
277 277
278 278
279 279 def ValidRepoName(edit=False, old_data={}):
280 280 class _validator(formencode.validators.FancyValidator):
281 281 messages = {
282 282 'invalid_repo_name':
283 283 _(u'Repository name %(repo)s is disallowed'),
284 284 'repository_exists':
285 285 _(u'Repository named %(repo)s already exists'),
286 286 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
287 287 'exists in group "%(group)s"'),
288 288 'same_group_exists': _(u'Repositories group with name "%(repo)s" '
289 289 'already exists')
290 290 }
291 291
292 292 def _to_python(self, value, state):
293 293 repo_name = repo_name_slug(value.get('repo_name', ''))
294 294 repo_group = value.get('repo_group')
295 295 if repo_group:
296 296 gr = RepoGroup.get(repo_group)
297 297 group_path = gr.full_path
298 298 group_name = gr.group_name
299 299 # value needs to be aware of group name in order to check
300 300 # db key This is an actual just the name to store in the
301 301 # database
302 302 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
303 303 else:
304 304 group_name = group_path = ''
305 305 repo_name_full = repo_name
306 306
307 307 value['repo_name'] = repo_name
308 308 value['repo_name_full'] = repo_name_full
309 309 value['group_path'] = group_path
310 310 value['group_name'] = group_name
311 311 return value
312 312
313 313 def validate_python(self, value, state):
314 314
315 315 repo_name = value.get('repo_name')
316 316 repo_name_full = value.get('repo_name_full')
317 317 group_path = value.get('group_path')
318 318 group_name = value.get('group_name')
319 319
320 320 if repo_name in [ADMIN_PREFIX, '']:
321 321 msg = M(self, 'invalid_repo_name', state, repo=repo_name)
322 322 raise formencode.Invalid(msg, value, state,
323 323 error_dict=dict(repo_name=msg)
324 324 )
325 325
326 326 rename = old_data.get('repo_name') != repo_name_full
327 327 create = not edit
328 328 if rename or create:
329 329
330 330 if group_path != '':
331 331 if Repository.get_by_repo_name(repo_name_full):
332 332 msg = M(self, 'repository_in_group_exists', state,
333 333 repo=repo_name, group=group_name)
334 334 raise formencode.Invalid(msg, value, state,
335 335 error_dict=dict(repo_name=msg)
336 336 )
337 337 elif RepoGroup.get_by_group_name(repo_name_full):
338 338 msg = M(self, 'same_group_exists', state,
339 339 repo=repo_name)
340 340 raise formencode.Invalid(msg, value, state,
341 341 error_dict=dict(repo_name=msg)
342 342 )
343 343
344 344 elif Repository.get_by_repo_name(repo_name_full):
345 345 msg = M(self, 'repository_exists', state,
346 346 repo=repo_name)
347 347 raise formencode.Invalid(msg, value, state,
348 348 error_dict=dict(repo_name=msg)
349 349 )
350 350 return value
351 351 return _validator
352 352
353 353
354 354 def ValidForkName(*args, **kwargs):
355 355 return ValidRepoName(*args, **kwargs)
356 356
357 357
358 358 def SlugifyName():
359 359 class _validator(formencode.validators.FancyValidator):
360 360
361 361 def _to_python(self, value, state):
362 362 return repo_name_slug(value)
363 363
364 364 def validate_python(self, value, state):
365 365 pass
366 366
367 367 return _validator
368 368
369 369
370 370 def ValidCloneUri():
371 371 from rhodecode.lib.utils import make_ui
372 372
373 def url_handler(repo_type, url, proto, ui=None):
373 def url_handler(repo_type, url, ui=None):
374 374 if repo_type == 'hg':
375 375 from mercurial.httprepo import httprepository, httpsrepository
376 if proto == 'https':
376 if url.startswith('https'):
377 377 httpsrepository(make_ui('db'), url).capabilities
378 elif proto == 'http':
378 elif url.startswith('http'):
379 379 httprepository(make_ui('db'), url).capabilities
380 elif proto == 'svn+http':
380 elif url.startswith('svn+http'):
381 from hgsubversion.svnrepo import svnremoterepo
381 382 svnremoterepo(make_ui('db'), url).capabilities
382 383 elif repo_type == 'git':
383 384 #TODO: write a git url validator
384 385 pass
385 386
386 387 class _validator(formencode.validators.FancyValidator):
387 388 messages = {
388 389 'clone_uri': _(u'invalid clone url'),
389 390 'invalid_clone_uri': _(u'Invalid clone url, provide a '
390 391 'valid clone http(s)/svn+http(s) url')
391 392 }
392 393
393 394 def validate_python(self, value, state):
394 395 repo_type = value.get('repo_type')
395 396 url = value.get('clone_uri')
396 397
397 398 if not url:
398 399 pass
399 elif url.startswith('https') or \
400 url.startswith('http') or \
401 url.startswith('svn+http'):
402 if url.startswith('https'):
403 _type = 'https'
404 elif url.startswith('http'):
405 _type = 'http'
406 elif url.startswith('svn+http'):
407 try:
408 from hgsubversion.svnrepo import svnremoterepo
409 global svnremoterepo
410 except ImportError:
411 raise formencode.Invalid(_('invalid clone url: hgsubversion '
412 'is not installed'), value, state)
413 _type = 'svn+http'
400 else:
414 401 try:
415 url_handler(repo_type, url, _type, make_ui('db'))
402 url_handler(repo_type, url, make_ui('db'))
416 403 except Exception:
417 404 log.exception('Url validation failed')
418 405 msg = M(self, 'clone_uri')
419 406 raise formencode.Invalid(msg, value, state,
420 407 error_dict=dict(clone_uri=msg)
421 408 )
422 else:
423 msg = M(self, 'invalid_clone_uri', state)
424 raise formencode.Invalid(msg, value, state,
425 error_dict=dict(clone_uri=msg)
426 )
427 409 return _validator
428 410
429 411
430 412 def ValidForkType(old_data={}):
431 413 class _validator(formencode.validators.FancyValidator):
432 414 messages = {
433 415 'invalid_fork_type': _(u'Fork have to be the same type as parent')
434 416 }
435 417
436 418 def validate_python(self, value, state):
437 419 if old_data['repo_type'] != value:
438 420 msg = M(self, 'invalid_fork_type', state)
439 421 raise formencode.Invalid(msg, value, state,
440 422 error_dict=dict(repo_type=msg)
441 423 )
442 424 return _validator
443 425
444 426
445 427 def ValidPerms(type_='repo'):
446 428 if type_ == 'group':
447 429 EMPTY_PERM = 'group.none'
448 430 elif type_ == 'repo':
449 431 EMPTY_PERM = 'repository.none'
450 432
451 433 class _validator(formencode.validators.FancyValidator):
452 434 messages = {
453 435 'perm_new_member_name':
454 436 _(u'This username or users group name is not valid')
455 437 }
456 438
457 439 def to_python(self, value, state):
458 440 perms_update = []
459 441 perms_new = []
460 442 # build a list of permission to update and new permission to create
461 443 for k, v in value.items():
462 444 # means new added member to permissions
463 445 if k.startswith('perm_new_member'):
464 446 new_perm = value.get('perm_new_member', False)
465 447 new_member = value.get('perm_new_member_name', False)
466 448 new_type = value.get('perm_new_member_type')
467 449
468 450 if new_member and new_perm:
469 451 if (new_member, new_perm, new_type) not in perms_new:
470 452 perms_new.append((new_member, new_perm, new_type))
471 453 elif k.startswith('u_perm_') or k.startswith('g_perm_'):
472 454 member = k[7:]
473 455 t = {'u': 'user',
474 456 'g': 'users_group'
475 457 }[k[0]]
476 458 if member == 'default':
477 459 if value.get('private'):
478 460 # set none for default when updating to
479 461 # private repo
480 462 v = EMPTY_PERM
481 463 perms_update.append((member, v, t))
482 464
483 465 value['perms_updates'] = perms_update
484 466 value['perms_new'] = perms_new
485 467
486 468 # update permissions
487 469 for k, v, t in perms_new:
488 470 try:
489 471 if t is 'user':
490 472 self.user_db = User.query()\
491 473 .filter(User.active == True)\
492 474 .filter(User.username == k).one()
493 475 if t is 'users_group':
494 476 self.user_db = UsersGroup.query()\
495 477 .filter(UsersGroup.users_group_active == True)\
496 478 .filter(UsersGroup.users_group_name == k).one()
497 479
498 480 except Exception:
499 481 log.exception('Updated permission failed')
500 482 msg = M(self, 'perm_new_member_type', state)
501 483 raise formencode.Invalid(msg, value, state,
502 484 error_dict=dict(perm_new_member_name=msg)
503 485 )
504 486 return value
505 487 return _validator
506 488
507 489
508 490 def ValidSettings():
509 491 class _validator(formencode.validators.FancyValidator):
510 492 def _to_python(self, value, state):
511 493 # settings form can't edit user
512 494 if 'user' in value:
513 495 del value['user']
514 496 return value
515 497
516 498 def validate_python(self, value, state):
517 499 pass
518 500 return _validator
519 501
520 502
521 503 def ValidPath():
522 504 class _validator(formencode.validators.FancyValidator):
523 505 messages = {
524 506 'invalid_path': _(u'This is not a valid path')
525 507 }
526 508
527 509 def validate_python(self, value, state):
528 510 if not os.path.isdir(value):
529 511 msg = M(self, 'invalid_path', state)
530 512 raise formencode.Invalid(msg, value, state,
531 513 error_dict=dict(paths_root_path=msg)
532 514 )
533 515 return _validator
534 516
535 517
536 518 def UniqSystemEmail(old_data={}):
537 519 class _validator(formencode.validators.FancyValidator):
538 520 messages = {
539 521 'email_taken': _(u'This e-mail address is already taken')
540 522 }
541 523
542 524 def _to_python(self, value, state):
543 525 return value.lower()
544 526
545 527 def validate_python(self, value, state):
546 528 if (old_data.get('email') or '').lower() != value:
547 529 user = User.get_by_email(value, case_insensitive=True)
548 530 if user:
549 531 msg = M(self, 'email_taken', state)
550 532 raise formencode.Invalid(msg, value, state,
551 533 error_dict=dict(email=msg)
552 534 )
553 535 return _validator
554 536
555 537
556 538 def ValidSystemEmail():
557 539 class _validator(formencode.validators.FancyValidator):
558 540 messages = {
559 541 'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
560 542 }
561 543
562 544 def _to_python(self, value, state):
563 545 return value.lower()
564 546
565 547 def validate_python(self, value, state):
566 548 user = User.get_by_email(value, case_insensitive=True)
567 549 if user is None:
568 550 msg = M(self, 'non_existing_email', state, email=value)
569 551 raise formencode.Invalid(msg, value, state,
570 552 error_dict=dict(email=msg)
571 553 )
572 554
573 555 return _validator
574 556
575 557
576 558 def LdapLibValidator():
577 559 class _validator(formencode.validators.FancyValidator):
578 560 messages = {
579 561
580 562 }
581 563
582 564 def validate_python(self, value, state):
583 565 try:
584 566 import ldap
585 567 ldap # pyflakes silence !
586 568 except ImportError:
587 569 raise LdapImportError()
588 570
589 571 return _validator
590 572
591 573
592 574 def AttrLoginValidator():
593 575 class _validator(formencode.validators.FancyValidator):
594 576 messages = {
595 577 'invalid_cn':
596 578 _(u'The LDAP Login attribute of the CN must be specified - '
597 579 'this is the name of the attribute that is equivalent '
598 580 'to "username"')
599 581 }
600 582
601 583 def validate_python(self, value, state):
602 584 if not value or not isinstance(value, (str, unicode)):
603 585 msg = M(self, 'invalid_cn', state)
604 586 raise formencode.Invalid(msg, value, state,
605 587 error_dict=dict(ldap_attr_login=msg)
606 588 )
607 589
608 590 return _validator
General Comments 0
You need to be logged in to leave comments. Login now