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