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