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