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