##// END OF EJS Templates
fixed issue with remote repos on git
marcink -
r2053:e121e10d beta
parent child Browse files
Show More
@@ -1,531 +1,532 b''
1 1 .. _changelog:
2 2
3 3 Changelog
4 4 =========
5 5
6 6
7 7 1.3.2 (**2012-XX-XX**)
8 8 ----------------------
9 9
10 10 :status: in-progress
11 11 :branch: beta
12 12
13 13 news
14 14 ++++
15 15
16 16
17 17 fixes
18 18 +++++
19 19
20 20 - fixed git protocol issues with repos-groups
21 - fixed git remote repos validator that prevented from cloning remote git repos
21 22
22 23 1.3.1 (**2012-02-27**)
23 24 ----------------------
24 25
25 26 news
26 27 ++++
27 28
28 29
29 30 fixes
30 31 +++++
31 32
32 33 - redirection loop occurs when remember-me wasn't checked during login
33 34 - fixes issues with git blob history generation
34 35 - don't fetch branch for git in file history dropdown. Causes unneeded slowness
35 36
36 37 1.3.0 (**2012-02-26**)
37 38 ----------------------
38 39
39 40 news
40 41 ++++
41 42
42 43 - code review, inspired by github code-comments
43 44 - #215 rst and markdown README files support
44 45 - #252 Container-based and proxy pass-through authentication support
45 46 - #44 branch browser. Filtering of changelog by branches
46 47 - mercurial bookmarks support
47 48 - new hover top menu, optimized to add maximum size for important views
48 49 - configurable clone url template with possibility to specify protocol like
49 50 ssh:// or http:// and also manually alter other parts of clone_url.
50 51 - enabled largefiles extension by default
51 52 - optimized summary file pages and saved a lot of unused space in them
52 53 - #239 option to manually mark repository as fork
53 54 - #320 mapping of commit authors to RhodeCode users
54 55 - #304 hashes are displayed using monospace font
55 56 - diff configuration, toggle white lines and context lines
56 57 - #307 configurable diffs, whitespace toggle, increasing context lines
57 58 - sorting on branches, tags and bookmarks using YUI datatable
58 59 - improved file filter on files page
59 60 - implements #330 api method for listing nodes ar particular revision
60 61 - #73 added linking issues in commit messages to chosen issue tracker url
61 62 based on user defined regular expression
62 63 - added linking of changesets in commit messages
63 64 - new compact changelog with expandable commit messages
64 65 - firstname and lastname are optional in user creation
65 66 - #348 added post-create repository hook
66 67 - #212 global encoding settings is now configurable from .ini files
67 68 - #227 added repository groups permissions
68 69 - markdown gets codehilite extensions
69 70 - new API methods, delete_repositories, grante/revoke permissions for groups
70 71 and repos
71 72
72 73
73 74 fixes
74 75 +++++
75 76
76 77 - rewrote dbsession management for atomic operations, and better error handling
77 78 - fixed sorting of repo tables
78 79 - #326 escape of special html entities in diffs
79 80 - normalized user_name => username in api attributes
80 81 - fixes #298 ldap created users with mixed case emails created conflicts
81 82 on saving a form
82 83 - fixes issue when owner of a repo couldn't revoke permissions for users
83 84 and groups
84 85 - fixes #271 rare JSON serialization problem with statistics
85 86 - fixes #337 missing validation check for conflicting names of a group with a
86 87 repositories group
87 88 - #340 fixed session problem for mysql and celery tasks
88 89 - fixed #331 RhodeCode mangles repository names if the a repository group
89 90 contains the "full path" to the repositories
90 91 - #355 RhodeCode doesn't store encrypted LDAP passwords
91 92
92 93 1.2.5 (**2012-01-28**)
93 94 ----------------------
94 95
95 96 news
96 97 ++++
97 98
98 99 fixes
99 100 +++++
100 101
101 102 - #340 Celery complains about MySQL server gone away, added session cleanup
102 103 for celery tasks
103 104 - #341 "scanning for repositories in None" log message during Rescan was missing
104 105 a parameter
105 106 - fixed creating archives with subrepos. Some hooks were triggered during that
106 107 operation leading to crash.
107 108 - fixed missing email in account page.
108 109 - Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes
109 110 forking on windows impossible
110 111
111 112 1.2.4 (**2012-01-19**)
112 113 ----------------------
113 114
114 115 news
115 116 ++++
116 117
117 118 - RhodeCode is bundled with mercurial series 2.0.X by default, with
118 119 full support to largefiles extension. Enabled by default in new installations
119 120 - #329 Ability to Add/Remove Groups to/from a Repository via AP
120 121 - added requires.txt file with requirements
121 122
122 123 fixes
123 124 +++++
124 125
125 126 - fixes db session issues with celery when emailing admins
126 127 - #331 RhodeCode mangles repository names if the a repository group
127 128 contains the "full path" to the repositories
128 129 - #298 Conflicting e-mail addresses for LDAP and RhodeCode users
129 130 - DB session cleanup after hg protocol operations, fixes issues with
130 131 `mysql has gone away` errors
131 132 - #333 doc fixes for get_repo api function
132 133 - #271 rare JSON serialization problem with statistics enabled
133 134 - #337 Fixes issues with validation of repository name conflicting with
134 135 a group name. A proper message is now displayed.
135 136 - #292 made ldap_dn in user edit readonly, to get rid of confusion that field
136 137 doesn't work
137 138 - #316 fixes issues with web description in hgrc files
138 139
139 140 1.2.3 (**2011-11-02**)
140 141 ----------------------
141 142
142 143 news
143 144 ++++
144 145
145 146 - added option to manage repos group for non admin users
146 147 - added following API methods for get_users, create_user, get_users_groups,
147 148 get_users_group, create_users_group, add_user_to_users_groups, get_repos,
148 149 get_repo, create_repo, add_user_to_repo
149 150 - implements #237 added password confirmation for my account
150 151 and admin edit user.
151 152 - implements #291 email notification for global events are now sent to all
152 153 administrator users, and global config email.
153 154
154 155 fixes
155 156 +++++
156 157
157 158 - added option for passing auth method for smtp mailer
158 159 - #276 issue with adding a single user with id>10 to usergroups
159 160 - #277 fixes windows LDAP settings in which missing values breaks the ldap auth
160 161 - #288 fixes managing of repos in a group for non admin user
161 162
162 163 1.2.2 (**2011-10-17**)
163 164 ----------------------
164 165
165 166 news
166 167 ++++
167 168
168 169 - #226 repo groups are available by path instead of numerical id
169 170
170 171 fixes
171 172 +++++
172 173
173 174 - #259 Groups with the same name but with different parent group
174 175 - #260 Put repo in group, then move group to another group -> repo becomes unavailable
175 176 - #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems)
176 177 - #265 ldap save fails sometimes on converting attributes to booleans,
177 178 added getter and setter into model that will prevent from this on db model level
178 179 - fixed problems with timestamps issues #251 and #213
179 180 - fixes #266 RhodeCode allows to create repo with the same name and in
180 181 the same parent as group
181 182 - fixes #245 Rescan of the repositories on Windows
182 183 - fixes #248 cannot edit repos inside a group on windows
183 184 - fixes #219 forking problems on windows
184 185
185 186 1.2.1 (**2011-10-08**)
186 187 ----------------------
187 188
188 189 news
189 190 ++++
190 191
191 192
192 193 fixes
193 194 +++++
194 195
195 196 - fixed problems with basic auth and push problems
196 197 - gui fixes
197 198 - fixed logger
198 199
199 200 1.2.0 (**2011-10-07**)
200 201 ----------------------
201 202
202 203 news
203 204 ++++
204 205
205 206 - implemented #47 repository groups
206 207 - implemented #89 Can setup google analytics code from settings menu
207 208 - implemented #91 added nicer looking archive urls with more download options
208 209 like tags, branches
209 210 - implemented #44 into file browsing, and added follow branch option
210 211 - implemented #84 downloads can be enabled/disabled for each repository
211 212 - anonymous repository can be cloned without having to pass default:default
212 213 into clone url
213 214 - fixed #90 whoosh indexer can index chooses repositories passed in command
214 215 line
215 216 - extended journal with day aggregates and paging
216 217 - implemented #107 source code lines highlight ranges
217 218 - implemented #93 customizable changelog on combined revision ranges -
218 219 equivalent of githubs compare view
219 220 - implemented #108 extended and more powerful LDAP configuration
220 221 - implemented #56 users groups
221 222 - major code rewrites optimized codes for speed and memory usage
222 223 - raw and diff downloads are now in git format
223 224 - setup command checks for write access to given path
224 225 - fixed many issues with international characters and unicode. It uses utf8
225 226 decode with replace to provide less errors even with non utf8 encoded strings
226 227 - #125 added API KEY access to feeds
227 228 - #109 Repository can be created from external Mercurial link (aka. remote
228 229 repository, and manually updated (via pull) from admin panel
229 230 - beta git support - push/pull server + basic view for git repos
230 231 - added followers page and forks page
231 232 - server side file creation (with binary file upload interface)
232 233 and edition with commits powered by codemirror
233 234 - #111 file browser file finder, quick lookup files on whole file tree
234 235 - added quick login sliding menu into main page
235 236 - changelog uses lazy loading of affected files details, in some scenarios
236 237 this can improve speed of changelog page dramatically especially for
237 238 larger repositories.
238 239 - implements #214 added support for downloading subrepos in download menu.
239 240 - Added basic API for direct operations on rhodecode via JSON
240 241 - Implemented advanced hook management
241 242
242 243 fixes
243 244 +++++
244 245
245 246 - fixed file browser bug, when switching into given form revision the url was
246 247 not changing
247 248 - fixed propagation to error controller on simplehg and simplegit middlewares
248 249 - fixed error when trying to make a download on empty repository
249 250 - fixed problem with '[' chars in commit messages in journal
250 251 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
251 252 - journal fork fixes
252 253 - removed issue with space inside renamed repository after deletion
253 254 - fixed strange issue on formencode imports
254 255 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
255 256 - #150 fixes for errors on repositories mapped in db but corrupted in
256 257 filesystem
257 258 - fixed problem with ascendant characters in realm #181
258 259 - fixed problem with sqlite file based database connection pool
259 260 - whoosh indexer and code stats share the same dynamic extensions map
260 261 - fixes #188 - relationship delete of repo_to_perm entry on user removal
261 262 - fixes issue #189 Trending source files shows "show more" when no more exist
262 263 - fixes issue #197 Relative paths for pidlocks
263 264 - fixes issue #198 password will require only 3 chars now for login form
264 265 - fixes issue #199 wrong redirection for non admin users after creating a repository
265 266 - fixes issues #202, bad db constraint made impossible to attach same group
266 267 more than one time. Affects only mysql/postgres
267 268 - fixes #218 os.kill patch for windows was missing sig param
268 269 - improved rendering of dag (they are not trimmed anymore when number of
269 270 heads exceeds 5)
270 271
271 272 1.1.8 (**2011-04-12**)
272 273 ----------------------
273 274
274 275 news
275 276 ++++
276 277
277 278 - improved windows support
278 279
279 280 fixes
280 281 +++++
281 282
282 283 - fixed #140 freeze of python dateutil library, since new version is python2.x
283 284 incompatible
284 285 - setup-app will check for write permission in given path
285 286 - cleaned up license info issue #149
286 287 - fixes for issues #137,#116 and problems with unicode and accented characters.
287 288 - fixes crashes on gravatar, when passed in email as unicode
288 289 - fixed tooltip flickering problems
289 290 - fixed came_from redirection on windows
290 291 - fixed logging modules, and sql formatters
291 292 - windows fixes for os.kill issue #133
292 293 - fixes path splitting for windows issues #148
293 294 - fixed issue #143 wrong import on migration to 1.1.X
294 295 - fixed problems with displaying binary files, thanks to Thomas Waldmann
295 296 - removed name from archive files since it's breaking ui for long repo names
296 297 - fixed issue with archive headers sent to browser, thanks to Thomas Waldmann
297 298 - fixed compatibility for 1024px displays, and larger dpi settings, thanks to
298 299 Thomas Waldmann
299 300 - fixed issue #166 summary pager was skipping 10 revisions on second page
300 301
301 302
302 303 1.1.7 (**2011-03-23**)
303 304 ----------------------
304 305
305 306 news
306 307 ++++
307 308
308 309 fixes
309 310 +++++
310 311
311 312 - fixed (again) #136 installation support for FreeBSD
312 313
313 314
314 315 1.1.6 (**2011-03-21**)
315 316 ----------------------
316 317
317 318 news
318 319 ++++
319 320
320 321 fixes
321 322 +++++
322 323
323 324 - fixed #136 installation support for FreeBSD
324 325 - RhodeCode will check for python version during installation
325 326
326 327 1.1.5 (**2011-03-17**)
327 328 ----------------------
328 329
329 330 news
330 331 ++++
331 332
332 333 - basic windows support, by exchanging pybcrypt into sha256 for windows only
333 334 highly inspired by idea of mantis406
334 335
335 336 fixes
336 337 +++++
337 338
338 339 - fixed sorting by author in main page
339 340 - fixed crashes with diffs on binary files
340 341 - fixed #131 problem with boolean values for LDAP
341 342 - fixed #122 mysql problems thanks to striker69
342 343 - fixed problem with errors on calling raw/raw_files/annotate functions
343 344 with unknown revisions
344 345 - fixed returned rawfiles attachment names with international character
345 346 - cleaned out docs, big thanks to Jason Harris
346 347
347 348 1.1.4 (**2011-02-19**)
348 349 ----------------------
349 350
350 351 news
351 352 ++++
352 353
353 354 fixes
354 355 +++++
355 356
356 357 - fixed formencode import problem on settings page, that caused server crash
357 358 when that page was accessed as first after server start
358 359 - journal fixes
359 360 - fixed option to access repository just by entering http://server/<repo_name>
360 361
361 362 1.1.3 (**2011-02-16**)
362 363 ----------------------
363 364
364 365 news
365 366 ++++
366 367
367 368 - implemented #102 allowing the '.' character in username
368 369 - added option to access repository just by entering http://server/<repo_name>
369 370 - celery task ignores result for better performance
370 371
371 372 fixes
372 373 +++++
373 374
374 375 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
375 376 apollo13 and Johan Walles
376 377 - small fixes in journal
377 378 - fixed problems with getting setting for celery from .ini files
378 379 - registration, password reset and login boxes share the same title as main
379 380 application now
380 381 - fixed #113: to high permissions to fork repository
381 382 - fixed problem with '[' chars in commit messages in journal
382 383 - removed issue with space inside renamed repository after deletion
383 384 - db transaction fixes when filesystem repository creation failed
384 385 - fixed #106 relation issues on databases different than sqlite
385 386 - fixed static files paths links to use of url() method
386 387
387 388 1.1.2 (**2011-01-12**)
388 389 ----------------------
389 390
390 391 news
391 392 ++++
392 393
393 394
394 395 fixes
395 396 +++++
396 397
397 398 - fixes #98 protection against float division of percentage stats
398 399 - fixed graph bug
399 400 - forced webhelpers version since it was making troubles during installation
400 401
401 402 1.1.1 (**2011-01-06**)
402 403 ----------------------
403 404
404 405 news
405 406 ++++
406 407
407 408 - added force https option into ini files for easier https usage (no need to
408 409 set server headers with this options)
409 410 - small css updates
410 411
411 412 fixes
412 413 +++++
413 414
414 415 - fixed #96 redirect loop on files view on repositories without changesets
415 416 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
416 417 and server crashed with errors
417 418 - fixed large tooltips problems on main page
418 419 - fixed #92 whoosh indexer is more error proof
419 420
420 421 1.1.0 (**2010-12-18**)
421 422 ----------------------
422 423
423 424 news
424 425 ++++
425 426
426 427 - rewrite of internals for vcs >=0.1.10
427 428 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
428 429 with older clients
429 430 - anonymous access, authentication via ldap
430 431 - performance upgrade for cached repos list - each repository has its own
431 432 cache that's invalidated when needed.
432 433 - performance upgrades on repositories with large amount of commits (20K+)
433 434 - main page quick filter for filtering repositories
434 435 - user dashboards with ability to follow chosen repositories actions
435 436 - sends email to admin on new user registration
436 437 - added cache/statistics reset options into repository settings
437 438 - more detailed action logger (based on hooks) with pushed changesets lists
438 439 and options to disable those hooks from admin panel
439 440 - introduced new enhanced changelog for merges that shows more accurate results
440 441 - new improved and faster code stats (based on pygments lexers mapping tables,
441 442 showing up to 10 trending sources for each repository. Additionally stats
442 443 can be disabled in repository settings.
443 444 - gui optimizations, fixed application width to 1024px
444 445 - added cut off (for large files/changesets) limit into config files
445 446 - whoosh, celeryd, upgrade moved to paster command
446 447 - other than sqlite database backends can be used
447 448
448 449 fixes
449 450 +++++
450 451
451 452 - fixes #61 forked repo was showing only after cache expired
452 453 - fixes #76 no confirmation on user deletes
453 454 - fixes #66 Name field misspelled
454 455 - fixes #72 block user removal when he owns repositories
455 456 - fixes #69 added password confirmation fields
456 457 - fixes #87 RhodeCode crashes occasionally on updating repository owner
457 458 - fixes #82 broken annotations on files with more than 1 blank line at the end
458 459 - a lot of fixes and tweaks for file browser
459 460 - fixed detached session issues
460 461 - fixed when user had no repos he would see all repos listed in my account
461 462 - fixed ui() instance bug when global hgrc settings was loaded for server
462 463 instance and all hgrc options were merged with our db ui() object
463 464 - numerous small bugfixes
464 465
465 466 (special thanks for TkSoh for detailed feedback)
466 467
467 468
468 469 1.0.2 (**2010-11-12**)
469 470 ----------------------
470 471
471 472 news
472 473 ++++
473 474
474 475 - tested under python2.7
475 476 - bumped sqlalchemy and celery versions
476 477
477 478 fixes
478 479 +++++
479 480
480 481 - fixed #59 missing graph.js
481 482 - fixed repo_size crash when repository had broken symlinks
482 483 - fixed python2.5 crashes.
483 484
484 485
485 486 1.0.1 (**2010-11-10**)
486 487 ----------------------
487 488
488 489 news
489 490 ++++
490 491
491 492 - small css updated
492 493
493 494 fixes
494 495 +++++
495 496
496 497 - fixed #53 python2.5 incompatible enumerate calls
497 498 - fixed #52 disable mercurial extension for web
498 499 - fixed #51 deleting repositories don't delete it's dependent objects
499 500
500 501
501 502 1.0.0 (**2010-11-02**)
502 503 ----------------------
503 504
504 505 - security bugfix simplehg wasn't checking for permissions on commands
505 506 other than pull or push.
506 507 - fixed doubled messages after push or pull in admin journal
507 508 - templating and css corrections, fixed repo switcher on chrome, updated titles
508 509 - admin menu accessible from options menu on repository view
509 510 - permissions cached queries
510 511
511 512 1.0.0rc4 (**2010-10-12**)
512 513 --------------------------
513 514
514 515 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
515 516 - removed cache_manager settings from sqlalchemy meta
516 517 - added sqlalchemy cache settings to ini files
517 518 - validated password length and added second try of failure on paster setup-app
518 519 - fixed setup database destroy prompt even when there was no db
519 520
520 521
521 522 1.0.0rc3 (**2010-10-11**)
522 523 -------------------------
523 524
524 525 - fixed i18n during installation.
525 526
526 527 1.0.0rc2 (**2010-10-11**)
527 528 -------------------------
528 529
529 530 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
530 531 occure. After vcs is fixed it'll be put back again.
531 532 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,758 +1,773 b''
1 1 """ this is forms validation classes
2 2 http://formencode.org/module-formencode.validators.html
3 3 for list off all availible validators
4 4
5 5 we can create our own validators
6 6
7 7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 8 pre_validators [] These validators will be applied before the schema
9 9 chained_validators [] These validators will be applied after the schema
10 10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14 14
15 15
16 16 <name> = formencode.validators.<name of validator>
17 17 <name> must equal form name
18 18 list=[1,2,3,4,5]
19 19 for SELECT use formencode.All(OneOf(list), Int())
20 20
21 21 """
22 22 import os
23 23 import re
24 24 import logging
25 25 import traceback
26 26
27 27 import formencode
28 28 from formencode import All
29 29 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
30 30 Email, Bool, StringBoolean, Set
31 31
32 32 from pylons.i18n.translation import _
33 33 from webhelpers.pylonslib.secure_form import authentication_token
34 34
35 35 from rhodecode.config.routing import ADMIN_PREFIX
36 36 from rhodecode.lib.utils import repo_name_slug
37 37 from rhodecode.lib.auth import authenticate, get_crypt_password
38 38 from rhodecode.lib.exceptions import LdapImportError
39 39 from rhodecode.model.db import User, UsersGroup, RepoGroup, Repository
40 40 from rhodecode import BACKENDS
41 41
42 42 log = logging.getLogger(__name__)
43 43
44 44
45 45 #this is needed to translate the messages using _() in validators
46 46 class State_obj(object):
47 47 _ = staticmethod(_)
48 48
49 49
50 50 #==============================================================================
51 51 # VALIDATORS
52 52 #==============================================================================
53 53 class ValidAuthToken(formencode.validators.FancyValidator):
54 54 messages = {'invalid_token': _('Token mismatch')}
55 55
56 56 def validate_python(self, value, state):
57 57
58 58 if value != authentication_token():
59 59 raise formencode.Invalid(
60 60 self.message('invalid_token',
61 61 state, search_number=value),
62 62 value,
63 63 state
64 64 )
65 65
66 66
67 67 def ValidUsername(edit, old_data):
68 68 class _ValidUsername(formencode.validators.FancyValidator):
69 69
70 70 def validate_python(self, value, state):
71 71 if value in ['default', 'new_user']:
72 72 raise formencode.Invalid(_('Invalid username'), value, state)
73 73 #check if user is unique
74 74 old_un = None
75 75 if edit:
76 76 old_un = User.get(old_data.get('user_id')).username
77 77
78 78 if old_un != value or not edit:
79 79 if User.get_by_username(value, case_insensitive=True):
80 80 raise formencode.Invalid(_('This username already '
81 81 'exists') , value, state)
82 82
83 83 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
84 84 raise formencode.Invalid(
85 85 _('Username may only contain alphanumeric characters '
86 86 'underscores, periods or dashes and must begin with '
87 87 'alphanumeric character'),
88 88 value,
89 89 state
90 90 )
91 91
92 92 return _ValidUsername
93 93
94 94
95 95 def ValidUsersGroup(edit, old_data):
96 96
97 97 class _ValidUsersGroup(formencode.validators.FancyValidator):
98 98
99 99 def validate_python(self, value, state):
100 100 if value in ['default']:
101 101 raise formencode.Invalid(_('Invalid group name'), value, state)
102 102 #check if group is unique
103 103 old_ugname = None
104 104 if edit:
105 105 old_ugname = UsersGroup.get(
106 106 old_data.get('users_group_id')).users_group_name
107 107
108 108 if old_ugname != value or not edit:
109 109 if UsersGroup.get_by_group_name(value, cache=False,
110 110 case_insensitive=True):
111 111 raise formencode.Invalid(_('This users group '
112 112 'already exists'), value,
113 113 state)
114 114
115 115 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
116 116 raise formencode.Invalid(
117 117 _('RepoGroup name may only contain alphanumeric characters '
118 118 'underscores, periods or dashes and must begin with '
119 119 'alphanumeric character'),
120 120 value,
121 121 state
122 122 )
123 123
124 124 return _ValidUsersGroup
125 125
126 126
127 127 def ValidReposGroup(edit, old_data):
128 128 class _ValidReposGroup(formencode.validators.FancyValidator):
129 129
130 130 def validate_python(self, value, state):
131 131 # TODO WRITE VALIDATIONS
132 132 group_name = value.get('group_name')
133 133 group_parent_id = value.get('group_parent_id')
134 134
135 135 # slugify repo group just in case :)
136 136 slug = repo_name_slug(group_name)
137 137
138 138 # check for parent of self
139 139 parent_of_self = lambda: (
140 140 old_data['group_id'] == int(group_parent_id)
141 141 if group_parent_id else False
142 142 )
143 143 if edit and parent_of_self():
144 144 e_dict = {
145 145 'group_parent_id': _('Cannot assign this group as parent')
146 146 }
147 147 raise formencode.Invalid('', value, state,
148 148 error_dict=e_dict)
149 149
150 150 old_gname = None
151 151 if edit:
152 152 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
153 153
154 154 if old_gname != group_name or not edit:
155 155
156 156 # check group
157 157 gr = RepoGroup.query()\
158 158 .filter(RepoGroup.group_name == slug)\
159 159 .filter(RepoGroup.group_parent_id == group_parent_id)\
160 160 .scalar()
161 161
162 162 if gr:
163 163 e_dict = {
164 164 'group_name': _('This group already exists')
165 165 }
166 166 raise formencode.Invalid('', value, state,
167 167 error_dict=e_dict)
168 168
169 169 # check for same repo
170 170 repo = Repository.query()\
171 171 .filter(Repository.repo_name == slug)\
172 172 .scalar()
173 173
174 174 if repo:
175 175 e_dict = {
176 176 'group_name': _('Repository with this name already exists')
177 177 }
178 178 raise formencode.Invalid('', value, state,
179 179 error_dict=e_dict)
180 180
181 181 return _ValidReposGroup
182 182
183 183
184 184 class ValidPassword(formencode.validators.FancyValidator):
185 185
186 186 def to_python(self, value, state):
187 187
188 188 if not value:
189 189 return
190 190
191 191 if value.get('password'):
192 192 try:
193 193 value['password'] = get_crypt_password(value['password'])
194 194 except UnicodeEncodeError:
195 195 e_dict = {'password': _('Invalid characters in password')}
196 196 raise formencode.Invalid('', value, state, error_dict=e_dict)
197 197
198 198 if value.get('password_confirmation'):
199 199 try:
200 200 value['password_confirmation'] = \
201 201 get_crypt_password(value['password_confirmation'])
202 202 except UnicodeEncodeError:
203 203 e_dict = {
204 204 'password_confirmation': _('Invalid characters in password')
205 205 }
206 206 raise formencode.Invalid('', value, state, error_dict=e_dict)
207 207
208 208 if value.get('new_password'):
209 209 try:
210 210 value['new_password'] = \
211 211 get_crypt_password(value['new_password'])
212 212 except UnicodeEncodeError:
213 213 e_dict = {'new_password': _('Invalid characters in password')}
214 214 raise formencode.Invalid('', value, state, error_dict=e_dict)
215 215
216 216 return value
217 217
218 218
219 219 class ValidPasswordsMatch(formencode.validators.FancyValidator):
220 220
221 221 def validate_python(self, value, state):
222 222
223 223 pass_val = value.get('password') or value.get('new_password')
224 224 if pass_val != value['password_confirmation']:
225 225 e_dict = {'password_confirmation':
226 226 _('Passwords do not match')}
227 227 raise formencode.Invalid('', value, state, error_dict=e_dict)
228 228
229 229
230 230 class ValidAuth(formencode.validators.FancyValidator):
231 231 messages = {
232 232 'invalid_password':_('invalid password'),
233 233 'invalid_login':_('invalid user name'),
234 234 'disabled_account':_('Your account is disabled')
235 235 }
236 236
237 237 # error mapping
238 238 e_dict = {'username': messages['invalid_login'],
239 239 'password': messages['invalid_password']}
240 240 e_dict_disable = {'username': messages['disabled_account']}
241 241
242 242 def validate_python(self, value, state):
243 243 password = value['password']
244 244 username = value['username']
245 245 user = User.get_by_username(username)
246 246
247 247 if authenticate(username, password):
248 248 return value
249 249 else:
250 250 if user and user.active is False:
251 251 log.warning('user %s is disabled' % username)
252 252 raise formencode.Invalid(
253 253 self.message('disabled_account',
254 254 state=State_obj),
255 255 value, state,
256 256 error_dict=self.e_dict_disable
257 257 )
258 258 else:
259 259 log.warning('user %s failed to authenticate' % username)
260 260 raise formencode.Invalid(
261 261 self.message('invalid_password',
262 262 state=State_obj), value, state,
263 263 error_dict=self.e_dict
264 264 )
265 265
266 266
267 267 class ValidRepoUser(formencode.validators.FancyValidator):
268 268
269 269 def to_python(self, value, state):
270 270 try:
271 271 User.query().filter(User.active == True)\
272 272 .filter(User.username == value).one()
273 273 except Exception:
274 274 raise formencode.Invalid(_('This username is not valid'),
275 275 value, state)
276 276 return value
277 277
278 278
279 279 def ValidRepoName(edit, old_data):
280 280 class _ValidRepoName(formencode.validators.FancyValidator):
281 281 def to_python(self, value, state):
282 282
283 283 repo_name = value.get('repo_name')
284 284
285 285 slug = repo_name_slug(repo_name)
286 286 if slug in [ADMIN_PREFIX, '']:
287 287 e_dict = {'repo_name': _('This repository name is disallowed')}
288 288 raise formencode.Invalid('', value, state, error_dict=e_dict)
289 289
290 290 if value.get('repo_group'):
291 291 gr = RepoGroup.get(value.get('repo_group'))
292 292 group_path = gr.full_path
293 293 # value needs to be aware of group name in order to check
294 294 # db key This is an actual just the name to store in the
295 295 # database
296 296 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
297 297
298 298 else:
299 299 group_path = ''
300 300 repo_name_full = repo_name
301 301
302 302 value['repo_name_full'] = repo_name_full
303 303 rename = old_data.get('repo_name') != repo_name_full
304 304 create = not edit
305 305 if rename or create:
306 306
307 307 if group_path != '':
308 308 if Repository.get_by_repo_name(repo_name_full):
309 309 e_dict = {
310 310 'repo_name': _('This repository already exists in '
311 311 'a group "%s"') % gr.group_name
312 312 }
313 313 raise formencode.Invalid('', value, state,
314 314 error_dict=e_dict)
315 315 elif RepoGroup.get_by_group_name(repo_name_full):
316 316 e_dict = {
317 317 'repo_name': _('There is a group with this name '
318 318 'already "%s"') % repo_name_full
319 319 }
320 320 raise formencode.Invalid('', value, state,
321 321 error_dict=e_dict)
322 322
323 323 elif Repository.get_by_repo_name(repo_name_full):
324 324 e_dict = {'repo_name': _('This repository '
325 325 'already exists')}
326 326 raise formencode.Invalid('', value, state,
327 327 error_dict=e_dict)
328 328
329 329 return value
330 330
331 331 return _ValidRepoName
332 332
333 333
334 334 def ValidForkName(*args, **kwargs):
335 335 return ValidRepoName(*args, **kwargs)
336 336
337 337
338 338 def SlugifyName():
339 339 class _SlugifyName(formencode.validators.FancyValidator):
340 340
341 341 def to_python(self, value, state):
342 342 return repo_name_slug(value)
343 343
344 344 return _SlugifyName
345 345
346 346
347 347 def ValidCloneUri():
348 from mercurial.httprepo import httprepository, httpsrepository
349 348 from rhodecode.lib.utils import make_ui
350 349
350 def url_handler(repo_type, url, proto, ui=None):
351 if repo_type == 'hg':
352 from mercurial.httprepo import httprepository, httpsrepository
353 if proto == 'https':
354 httpsrepository(make_ui('db'), url).capabilities
355 elif proto == 'http':
356 httprepository(make_ui('db'), url).capabilities
357 elif repo_type == 'git':
358 #TODO: write a git url validator
359 pass
360
351 361 class _ValidCloneUri(formencode.validators.FancyValidator):
352 362
353 363 def to_python(self, value, state):
354 if not value:
364
365 repo_type = value.get('repo_type')
366 url = value.get('clone_uri')
367 e_dict = {'clone_uri': _('invalid clone url')}
368
369 if not url:
355 370 pass
356 elif value.startswith('https'):
371 elif url.startswith('https'):
357 372 try:
358 httpsrepository(make_ui('db'), value).capabilities
373 url_handler(repo_type, url, 'https', make_ui('db'))
359 374 except Exception:
360 375 log.error(traceback.format_exc())
361 raise formencode.Invalid(_('invalid clone url'), value,
362 state)
363 elif value.startswith('http'):
376 raise formencode.Invalid('', value, state, error_dict=e_dict)
377 elif url.startswith('http'):
364 378 try:
365 httprepository(make_ui('db'), value).capabilities
379 url_handler(repo_type, url, 'http', make_ui('db'))
366 380 except Exception:
367 381 log.error(traceback.format_exc())
368 raise formencode.Invalid(_('invalid clone url'), value,
369 state)
382 raise formencode.Invalid('', value, state, error_dict=e_dict)
370 383 else:
371 raise formencode.Invalid(_('Invalid clone url, provide a '
372 'valid clone http\s url'), value,
373 state)
384 e_dict = {'clone_uri': _('Invalid clone url, provide a '
385 'valid clone http\s url')}
386 raise formencode.Invalid('', value, state, error_dict=e_dict)
387
374 388 return value
375 389
376 390 return _ValidCloneUri
377 391
378 392
379 393 def ValidForkType(old_data):
380 394 class _ValidForkType(formencode.validators.FancyValidator):
381 395
382 396 def to_python(self, value, state):
383 397 if old_data['repo_type'] != value:
384 398 raise formencode.Invalid(_('Fork have to be the same '
385 399 'type as original'), value, state)
386 400
387 401 return value
388 402 return _ValidForkType
389 403
390 404
391 405 def ValidPerms(type_='repo'):
392 406 if type_ == 'group':
393 407 EMPTY_PERM = 'group.none'
394 408 elif type_ == 'repo':
395 409 EMPTY_PERM = 'repository.none'
396 410
397 411 class _ValidPerms(formencode.validators.FancyValidator):
398 412 messages = {
399 413 'perm_new_member_name':
400 414 _('This username or users group name is not valid')
401 415 }
402 416
403 417 def to_python(self, value, state):
404 418 perms_update = []
405 419 perms_new = []
406 420 # build a list of permission to update and new permission to create
407 421 for k, v in value.items():
408 422 # means new added member to permissions
409 423 if k.startswith('perm_new_member'):
410 424 new_perm = value.get('perm_new_member', False)
411 425 new_member = value.get('perm_new_member_name', False)
412 426 new_type = value.get('perm_new_member_type')
413 427
414 428 if new_member and new_perm:
415 429 if (new_member, new_perm, new_type) not in perms_new:
416 430 perms_new.append((new_member, new_perm, new_type))
417 431 elif k.startswith('u_perm_') or k.startswith('g_perm_'):
418 432 member = k[7:]
419 433 t = {'u': 'user',
420 434 'g': 'users_group'
421 435 }[k[0]]
422 436 if member == 'default':
423 437 if value.get('private'):
424 438 # set none for default when updating to private repo
425 439 v = EMPTY_PERM
426 440 perms_update.append((member, v, t))
427 441
428 442 value['perms_updates'] = perms_update
429 443 value['perms_new'] = perms_new
430 444
431 445 # update permissions
432 446 for k, v, t in perms_new:
433 447 try:
434 448 if t is 'user':
435 449 self.user_db = User.query()\
436 450 .filter(User.active == True)\
437 451 .filter(User.username == k).one()
438 452 if t is 'users_group':
439 453 self.user_db = UsersGroup.query()\
440 454 .filter(UsersGroup.users_group_active == True)\
441 455 .filter(UsersGroup.users_group_name == k).one()
442 456
443 457 except Exception:
444 458 msg = self.message('perm_new_member_name',
445 459 state=State_obj)
446 460 raise formencode.Invalid(
447 461 msg, value, state, error_dict={'perm_new_member_name': msg}
448 462 )
449 463 return value
450 464 return _ValidPerms
451 465
452 466
453 467 class ValidSettings(formencode.validators.FancyValidator):
454 468
455 469 def to_python(self, value, state):
456 470 # settings form can't edit user
457 471 if 'user' in value:
458 472 del['value']['user']
459 473 return value
460 474
461 475
462 476 class ValidPath(formencode.validators.FancyValidator):
463 477 def to_python(self, value, state):
464 478
465 479 if not os.path.isdir(value):
466 480 msg = _('This is not a valid path')
467 481 raise formencode.Invalid(msg, value, state,
468 482 error_dict={'paths_root_path': msg})
469 483 return value
470 484
471 485
472 486 def UniqSystemEmail(old_data):
473 487 class _UniqSystemEmail(formencode.validators.FancyValidator):
474 488 def to_python(self, value, state):
475 489 value = value.lower()
476 490 if old_data.get('email', '').lower() != value:
477 491 user = User.get_by_email(value, case_insensitive=True)
478 492 if user:
479 493 raise formencode.Invalid(
480 494 _("This e-mail address is already taken"), value, state
481 495 )
482 496 return value
483 497
484 498 return _UniqSystemEmail
485 499
486 500
487 501 class ValidSystemEmail(formencode.validators.FancyValidator):
488 502 def to_python(self, value, state):
489 503 value = value.lower()
490 504 user = User.get_by_email(value, case_insensitive=True)
491 505 if user is None:
492 506 raise formencode.Invalid(
493 507 _("This e-mail address doesn't exist."), value, state
494 508 )
495 509
496 510 return value
497 511
498 512
499 513 class LdapLibValidator(formencode.validators.FancyValidator):
500 514
501 515 def to_python(self, value, state):
502 516
503 517 try:
504 518 import ldap
505 519 except ImportError:
506 520 raise LdapImportError
507 521 return value
508 522
509 523
510 524 class AttrLoginValidator(formencode.validators.FancyValidator):
511 525
512 526 def to_python(self, value, state):
513 527
514 528 if not value or not isinstance(value, (str, unicode)):
515 529 raise formencode.Invalid(
516 530 _("The LDAP Login attribute of the CN must be specified - "
517 531 "this is the name of the attribute that is equivalent "
518 532 "to 'username'"), value, state
519 533 )
520 534
521 535 return value
522 536
523 537
524 538 #==============================================================================
525 539 # FORMS
526 540 #==============================================================================
527 541 class LoginForm(formencode.Schema):
528 542 allow_extra_fields = True
529 543 filter_extra_fields = True
530 544 username = UnicodeString(
531 545 strip=True,
532 546 min=1,
533 547 not_empty=True,
534 548 messages={
535 549 'empty': _('Please enter a login'),
536 550 'tooShort': _('Enter a value %(min)i characters long or more')}
537 551 )
538 552
539 553 password = UnicodeString(
540 554 strip=True,
541 555 min=3,
542 556 not_empty=True,
543 557 messages={
544 558 'empty': _('Please enter a password'),
545 559 'tooShort': _('Enter %(min)i characters or more')}
546 560 )
547 561
548 562 remember = StringBoolean(if_missing=False)
549 563
550 564 chained_validators = [ValidAuth]
551 565
552 566
553 567 def UserForm(edit=False, old_data={}):
554 568 class _UserForm(formencode.Schema):
555 569 allow_extra_fields = True
556 570 filter_extra_fields = True
557 571 username = All(UnicodeString(strip=True, min=1, not_empty=True),
558 572 ValidUsername(edit, old_data))
559 573 if edit:
560 574 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
561 575 password_confirmation = All(UnicodeString(strip=True, min=6,
562 576 not_empty=False))
563 577 admin = StringBoolean(if_missing=False)
564 578 else:
565 579 password = All(UnicodeString(strip=True, min=6, not_empty=True))
566 580 password_confirmation = All(UnicodeString(strip=True, min=6,
567 581 not_empty=False))
568 582
569 583 active = StringBoolean(if_missing=False)
570 584 name = UnicodeString(strip=True, min=1, not_empty=False)
571 585 lastname = UnicodeString(strip=True, min=1, not_empty=False)
572 586 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
573 587
574 588 chained_validators = [ValidPasswordsMatch, ValidPassword]
575 589
576 590 return _UserForm
577 591
578 592
579 593 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
580 594 class _UsersGroupForm(formencode.Schema):
581 595 allow_extra_fields = True
582 596 filter_extra_fields = True
583 597
584 598 users_group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
585 599 ValidUsersGroup(edit, old_data))
586 600
587 601 users_group_active = StringBoolean(if_missing=False)
588 602
589 603 if edit:
590 604 users_group_members = OneOf(available_members, hideList=False,
591 605 testValueList=True,
592 606 if_missing=None, not_empty=False)
593 607
594 608 return _UsersGroupForm
595 609
596 610
597 611 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
598 612 class _ReposGroupForm(formencode.Schema):
599 613 allow_extra_fields = True
600 614 filter_extra_fields = False
601 615
602 616 group_name = All(UnicodeString(strip=True, min=1, not_empty=True),
603 617 SlugifyName())
604 618 group_description = UnicodeString(strip=True, min=1,
605 619 not_empty=True)
606 620 group_parent_id = OneOf(available_groups, hideList=False,
607 621 testValueList=True,
608 622 if_missing=None, not_empty=False)
609 623
610 624 chained_validators = [ValidReposGroup(edit, old_data), ValidPerms('group')]
611 625
612 626 return _ReposGroupForm
613 627
614 628
615 629 def RegisterForm(edit=False, old_data={}):
616 630 class _RegisterForm(formencode.Schema):
617 631 allow_extra_fields = True
618 632 filter_extra_fields = True
619 633 username = All(ValidUsername(edit, old_data),
620 634 UnicodeString(strip=True, min=1, not_empty=True))
621 635 password = All(UnicodeString(strip=True, min=6, not_empty=True))
622 636 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
623 637 active = StringBoolean(if_missing=False)
624 638 name = UnicodeString(strip=True, min=1, not_empty=False)
625 639 lastname = UnicodeString(strip=True, min=1, not_empty=False)
626 640 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
627 641
628 642 chained_validators = [ValidPasswordsMatch, ValidPassword]
629 643
630 644 return _RegisterForm
631 645
632 646
633 647 def PasswordResetForm():
634 648 class _PasswordResetForm(formencode.Schema):
635 649 allow_extra_fields = True
636 650 filter_extra_fields = True
637 651 email = All(ValidSystemEmail(), Email(not_empty=True))
638 652 return _PasswordResetForm
639 653
640 654
641 655 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
642 656 repo_groups=[]):
643 657 class _RepoForm(formencode.Schema):
644 658 allow_extra_fields = True
645 659 filter_extra_fields = False
646 660 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
647 661 SlugifyName())
648 clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False),
649 ValidCloneUri()())
662 clone_uri = All(UnicodeString(strip=True, min=1, not_empty=False))
650 663 repo_group = OneOf(repo_groups, hideList=True)
651 664 repo_type = OneOf(supported_backends)
652 665 description = UnicodeString(strip=True, min=1, not_empty=True)
653 666 private = StringBoolean(if_missing=False)
654 667 enable_statistics = StringBoolean(if_missing=False)
655 668 enable_downloads = StringBoolean(if_missing=False)
656 669
657 670 if edit:
658 671 #this is repo owner
659 672 user = All(UnicodeString(not_empty=True), ValidRepoUser)
660 673
661 chained_validators = [ValidRepoName(edit, old_data), ValidPerms()]
674 chained_validators = [ValidCloneUri()(),
675 ValidRepoName(edit, old_data),
676 ValidPerms()]
662 677 return _RepoForm
663 678
664 679
665 680 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
666 681 repo_groups=[]):
667 682 class _RepoForkForm(formencode.Schema):
668 683 allow_extra_fields = True
669 684 filter_extra_fields = False
670 685 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
671 686 SlugifyName())
672 687 repo_group = OneOf(repo_groups, hideList=True)
673 688 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
674 689 description = UnicodeString(strip=True, min=1, not_empty=True)
675 690 private = StringBoolean(if_missing=False)
676 691 copy_permissions = StringBoolean(if_missing=False)
677 692 update_after_clone = StringBoolean(if_missing=False)
678 693 fork_parent_id = UnicodeString()
679 694 chained_validators = [ValidForkName(edit, old_data)]
680 695
681 696 return _RepoForkForm
682 697
683 698
684 699 def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
685 700 repo_groups=[]):
686 701 class _RepoForm(formencode.Schema):
687 702 allow_extra_fields = True
688 703 filter_extra_fields = False
689 704 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
690 705 SlugifyName())
691 706 description = UnicodeString(strip=True, min=1, not_empty=True)
692 707 repo_group = OneOf(repo_groups, hideList=True)
693 708 private = StringBoolean(if_missing=False)
694 709
695 710 chained_validators = [ValidRepoName(edit, old_data), ValidPerms(),
696 711 ValidSettings]
697 712 return _RepoForm
698 713
699 714
700 715 def ApplicationSettingsForm():
701 716 class _ApplicationSettingsForm(formencode.Schema):
702 717 allow_extra_fields = True
703 718 filter_extra_fields = False
704 719 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
705 720 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
706 721 rhodecode_ga_code = UnicodeString(strip=True, min=1, not_empty=False)
707 722
708 723 return _ApplicationSettingsForm
709 724
710 725
711 726 def ApplicationUiSettingsForm():
712 727 class _ApplicationUiSettingsForm(formencode.Schema):
713 728 allow_extra_fields = True
714 729 filter_extra_fields = False
715 730 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
716 731 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
717 732 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
718 733 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
719 734 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
720 735 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
721 736
722 737 return _ApplicationUiSettingsForm
723 738
724 739
725 740 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
726 741 class _DefaultPermissionsForm(formencode.Schema):
727 742 allow_extra_fields = True
728 743 filter_extra_fields = True
729 744 overwrite_default = StringBoolean(if_missing=False)
730 745 anonymous = OneOf(['True', 'False'], if_missing=False)
731 746 default_perm = OneOf(perms_choices)
732 747 default_register = OneOf(register_choices)
733 748 default_create = OneOf(create_choices)
734 749
735 750 return _DefaultPermissionsForm
736 751
737 752
738 753 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices, tls_kind_choices):
739 754 class _LdapSettingsForm(formencode.Schema):
740 755 allow_extra_fields = True
741 756 filter_extra_fields = True
742 757 pre_validators = [LdapLibValidator]
743 758 ldap_active = StringBoolean(if_missing=False)
744 759 ldap_host = UnicodeString(strip=True,)
745 760 ldap_port = Number(strip=True,)
746 761 ldap_tls_kind = OneOf(tls_kind_choices)
747 762 ldap_tls_reqcert = OneOf(tls_reqcert_choices)
748 763 ldap_dn_user = UnicodeString(strip=True,)
749 764 ldap_dn_pass = UnicodeString(strip=True,)
750 765 ldap_base_dn = UnicodeString(strip=True,)
751 766 ldap_filter = UnicodeString(strip=True,)
752 767 ldap_search_scope = OneOf(search_scope_choices)
753 768 ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,))
754 769 ldap_attr_firstname = UnicodeString(strip=True,)
755 770 ldap_attr_lastname = UnicodeString(strip=True,)
756 771 ldap_attr_email = UnicodeString(strip=True,)
757 772
758 773 return _LdapSettingsForm
General Comments 0
You need to be logged in to leave comments. Login now