##// END OF EJS Templates
fix required repo_type param on repo edit form
marcink -
r3862:2b2f5e6c default
parent child Browse files
Show More
@@ -1,606 +1,610 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Repositories controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29 from formencode import htmlfill
30 30
31 31 from webob.exc import HTTPInternalServerError, HTTPForbidden
32 32 from pylons import request, session, tmpl_context as c, url
33 33 from pylons.controllers.util import redirect
34 34 from pylons.i18n.translation import _
35 35 from sqlalchemy.exc import IntegrityError
36 36
37 37 import rhodecode
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
40 40 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator, NotAnonymous,\
41 41 HasPermissionAny, HasReposGroupPermissionAny, HasRepoPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseRepoController, render
43 43 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
44 44 from rhodecode.lib.helpers import get_token
45 45 from rhodecode.model.meta import Session
46 46 from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup,\
47 47 RhodeCodeSetting, RepositoryField
48 48 from rhodecode.model.forms import RepoForm, RepoFieldForm, RepoPermsForm
49 49 from rhodecode.model.scm import ScmModel, GroupList
50 50 from rhodecode.model.repo import RepoModel
51 51 from rhodecode.lib.compat import json
52 52 from sqlalchemy.sql.expression import func
53 53 from rhodecode.lib.exceptions import AttachedForksError
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57
58 58 class ReposController(BaseRepoController):
59 59 """
60 60 REST Controller styled on the Atom Publishing Protocol"""
61 61 # To properly map this controller, ensure your config/routing.py
62 62 # file has a resource setup:
63 63 # map.resource('repo', 'repos')
64 64
65 65 @LoginRequired()
66 66 def __before__(self):
67 67 c.admin_user = session.get('admin_user')
68 68 c.admin_username = session.get('admin_username')
69 69 super(ReposController, self).__before__()
70 70
71 71 def __load_defaults(self):
72 72 acl_groups = GroupList(RepoGroup.query().all(),
73 73 perm_set=['group.write', 'group.admin'])
74 74 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
75 75 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
76 76
77 77 repo_model = RepoModel()
78 78 c.users_array = repo_model.get_users_js()
79 79 c.users_groups_array = repo_model.get_users_groups_js()
80 80 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
81 81 c.landing_revs_choices = choices
82 82
83 83 def __load_data(self, repo_name=None):
84 84 """
85 85 Load defaults settings for edit, and update
86 86
87 87 :param repo_name:
88 88 """
89 89 self.__load_defaults()
90 90
91 91 c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
92 92 repo = db_repo.scm_instance
93 93
94 94 if c.repo_info is None:
95 95 h.not_mapped_error(repo_name)
96 96 return redirect(url('repos'))
97 97
98 98 ##override defaults for exact repo info here git/hg etc
99 99 choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info)
100 100 c.landing_revs_choices = choices
101 101
102 102 c.default_user_id = User.get_by_username('default').user_id
103 103 c.in_public_journal = UserFollowing.query()\
104 104 .filter(UserFollowing.user_id == c.default_user_id)\
105 105 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
106 106
107 107 if c.repo_info.stats:
108 108 # this is on what revision we ended up so we add +1 for count
109 109 last_rev = c.repo_info.stats.stat_on_revision + 1
110 110 else:
111 111 last_rev = 0
112 112 c.stats_revision = last_rev
113 113
114 114 c.repo_last_rev = repo.count() if repo.revisions else 0
115 115
116 116 if last_rev == 0 or c.repo_last_rev == 0:
117 117 c.stats_percentage = 0
118 118 else:
119 119 c.stats_percentage = '%.2f' % ((float((last_rev)) /
120 120 c.repo_last_rev) * 100)
121 121
122 122 c.repo_fields = RepositoryField.query()\
123 123 .filter(RepositoryField.repository == db_repo).all()
124 124
125 125 defaults = RepoModel()._get_defaults(repo_name)
126 126
127 127 c.repos_list = [('', _('--REMOVE FORK--'))]
128 128 c.repos_list += [(x.repo_id, x.repo_name) for x in
129 129 Repository.query().order_by(Repository.repo_name).all()
130 130 if x.repo_id != c.repo_info.repo_id]
131 131
132 132 defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else ''
133 133 return defaults
134 134
135 135 @HasPermissionAllDecorator('hg.admin')
136 136 def index(self, format='html'):
137 137 """GET /repos: All items in the collection"""
138 138 # url('repos')
139 139
140 140 c.repos_list = Repository.query()\
141 141 .order_by(func.lower(Repository.repo_name))\
142 142 .all()
143 143
144 144 repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list,
145 145 admin=True,
146 146 super_user_actions=True)
147 147 #json used to render the grid
148 148 c.data = json.dumps(repos_data)
149 149
150 150 return render('admin/repos/repos.html')
151 151
152 152 @NotAnonymous()
153 153 def create(self):
154 154 """
155 155 POST /repos: Create a new item"""
156 156 # url('repos')
157 157
158 158 self.__load_defaults()
159 159 form_result = {}
160 160 try:
161 161 form_result = RepoForm(repo_groups=c.repo_groups_choices,
162 162 landing_revs=c.landing_revs_choices)()\
163 163 .to_python(dict(request.POST))
164 164
165 165 new_repo = RepoModel().create(form_result,
166 166 self.rhodecode_user.user_id)
167 167 if form_result['clone_uri']:
168 168 h.flash(_('Created repository %s from %s') \
169 169 % (form_result['repo_name'], form_result['clone_uri']),
170 170 category='success')
171 171 else:
172 172 repo_url = h.link_to(form_result['repo_name'],
173 173 h.url('summary_home', repo_name=form_result['repo_name_full']))
174 174 h.flash(h.literal(_('Created repository %s') % repo_url),
175 175 category='success')
176 176
177 177 if request.POST.get('user_created'):
178 178 # created by regular non admin user
179 179 action_logger(self.rhodecode_user, 'user_created_repo',
180 180 form_result['repo_name_full'], self.ip_addr,
181 181 self.sa)
182 182 else:
183 183 action_logger(self.rhodecode_user, 'admin_created_repo',
184 184 form_result['repo_name_full'], self.ip_addr,
185 185 self.sa)
186 186 Session().commit()
187 187 except formencode.Invalid, errors:
188 188 return htmlfill.render(
189 189 render('admin/repos/repo_add.html'),
190 190 defaults=errors.value,
191 191 errors=errors.error_dict or {},
192 192 prefix_error=False,
193 193 encoding="UTF-8")
194 194
195 195 except Exception:
196 196 log.error(traceback.format_exc())
197 197 msg = _('Error creating repository %s') \
198 198 % form_result.get('repo_name')
199 199 h.flash(msg, category='error')
200 200 if c.rhodecode_user.is_admin:
201 201 return redirect(url('repos'))
202 202 return redirect(url('home'))
203 203 #redirect to our new repo !
204 204 return redirect(url('summary_home', repo_name=new_repo.repo_name))
205 205
206 206 @NotAnonymous()
207 207 def create_repository(self):
208 208 """GET /_admin/create_repository: Form to create a new item"""
209 209 new_repo = request.GET.get('repo', '')
210 210 parent_group = request.GET.get('parent_group')
211 211 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
212 212 #you're not super admin nor have global create permissions,
213 213 #but maybe you have at least write permission to a parent group ?
214 214 _gr = RepoGroup.get(parent_group)
215 215 gr_name = _gr.group_name if _gr else None
216 216 if not HasReposGroupPermissionAny('group.admin', 'group.write')(group_name=gr_name):
217 217 raise HTTPForbidden
218 218
219 219 acl_groups = GroupList(RepoGroup.query().all(),
220 220 perm_set=['group.write', 'group.admin'])
221 221 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
222 222 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
223 223 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
224 224
225 225 c.new_repo = repo_name_slug(new_repo)
226 226
227 227 ## apply the defaults from defaults page
228 228 defaults = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
229 229 if parent_group:
230 230 defaults.update({'repo_group': parent_group})
231 231
232 232 return htmlfill.render(
233 233 render('admin/repos/repo_add.html'),
234 234 defaults=defaults,
235 235 errors={},
236 236 prefix_error=False,
237 237 encoding="UTF-8"
238 238 )
239 239
240 240 @HasRepoPermissionAllDecorator('repository.admin')
241 241 def update(self, repo_name):
242 242 """
243 243 PUT /repos/repo_name: Update an existing item"""
244 244 # Forms posted to this method should contain a hidden field:
245 245 # <input type="hidden" name="_method" value="PUT" />
246 246 # Or using helpers:
247 247 # h.form(url('repo', repo_name=ID),
248 248 # method='put')
249 249 # url('repo', repo_name=ID)
250 250 self.__load_defaults()
251 251 repo_model = RepoModel()
252 252 changed_name = repo_name
253 253 #override the choices with extracted revisions !
254 254 choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name)
255 255 c.landing_revs_choices = choices
256 256 repo = Repository.get_by_repo_name(repo_name)
257 _form = RepoForm(edit=True, old_data={'repo_name': repo_name,
258 'repo_group': repo.group.get_dict() \
259 if repo.group else {}},
257 old_data = {
258 'repo_name': repo_name,
259 'repo_group': repo.group.get_dict() if repo.group else {},
260 'repo_type': repo.repo_type,
261 }
262 _form = RepoForm(edit=True, old_data=old_data,
260 263 repo_groups=c.repo_groups_choices,
261 264 landing_revs=c.landing_revs_choices)()
265
262 266 try:
263 267 form_result = _form.to_python(dict(request.POST))
264 268 repo = repo_model.update(repo_name, **form_result)
265 269 invalidate_cache('get_repo_cached_%s' % repo_name)
266 270 h.flash(_('Repository %s updated successfully') % repo_name,
267 271 category='success')
268 272 changed_name = repo.repo_name
269 273 action_logger(self.rhodecode_user, 'admin_updated_repo',
270 274 changed_name, self.ip_addr, self.sa)
271 275 Session().commit()
272 276 except formencode.Invalid, errors:
273 277 defaults = self.__load_data(repo_name)
274 278 defaults.update(errors.value)
275 279 return htmlfill.render(
276 280 render('admin/repos/repo_edit.html'),
277 281 defaults=defaults,
278 282 errors=errors.error_dict or {},
279 283 prefix_error=False,
280 284 encoding="UTF-8")
281 285
282 286 except Exception:
283 287 log.error(traceback.format_exc())
284 288 h.flash(_('Error occurred during update of repository %s') \
285 289 % repo_name, category='error')
286 290 return redirect(url('edit_repo', repo_name=changed_name))
287 291
288 292 @HasRepoPermissionAllDecorator('repository.admin')
289 293 def delete(self, repo_name):
290 294 """
291 295 DELETE /repos/repo_name: Delete an existing item"""
292 296 # Forms posted to this method should contain a hidden field:
293 297 # <input type="hidden" name="_method" value="DELETE" />
294 298 # Or using helpers:
295 299 # h.form(url('repo', repo_name=ID),
296 300 # method='delete')
297 301 # url('repo', repo_name=ID)
298 302
299 303 repo_model = RepoModel()
300 304 repo = repo_model.get_by_repo_name(repo_name)
301 305 if not repo:
302 306 h.not_mapped_error(repo_name)
303 307 return redirect(url('repos'))
304 308 try:
305 309 _forks = repo.forks.count()
306 310 handle_forks = None
307 311 if _forks and request.POST.get('forks'):
308 312 do = request.POST['forks']
309 313 if do == 'detach_forks':
310 314 handle_forks = 'detach'
311 315 h.flash(_('Detached %s forks') % _forks, category='success')
312 316 elif do == 'delete_forks':
313 317 handle_forks = 'delete'
314 318 h.flash(_('Deleted %s forks') % _forks, category='success')
315 319 repo_model.delete(repo, forks=handle_forks)
316 320 action_logger(self.rhodecode_user, 'admin_deleted_repo',
317 321 repo_name, self.ip_addr, self.sa)
318 322 invalidate_cache('get_repo_cached_%s' % repo_name)
319 323 h.flash(_('Deleted repository %s') % repo_name, category='success')
320 324 Session().commit()
321 325 except AttachedForksError:
322 326 h.flash(_('Cannot delete %s it still contains attached forks')
323 327 % repo_name, category='warning')
324 328
325 329 except Exception:
326 330 log.error(traceback.format_exc())
327 331 h.flash(_('An error occurred during deletion of %s') % repo_name,
328 332 category='error')
329 333
330 334 return redirect(url('repos'))
331 335
332 336 @HasRepoPermissionAllDecorator('repository.admin')
333 337 def set_repo_perm_member(self, repo_name):
334 338 form = RepoPermsForm()().to_python(request.POST)
335 339
336 340 perms_new = form['perms_new']
337 341 perms_updates = form['perms_updates']
338 342 cur_repo = repo_name
339 343
340 344 # update permissions
341 345 for member, perm, member_type in perms_updates:
342 346 if member_type == 'user':
343 347 # this updates existing one
344 348 RepoModel().grant_user_permission(
345 349 repo=cur_repo, user=member, perm=perm
346 350 )
347 351 else:
348 352 RepoModel().grant_users_group_permission(
349 353 repo=cur_repo, group_name=member, perm=perm
350 354 )
351 355 # set new permissions
352 356 for member, perm, member_type in perms_new:
353 357 if member_type == 'user':
354 358 RepoModel().grant_user_permission(
355 359 repo=cur_repo, user=member, perm=perm
356 360 )
357 361 else:
358 362 RepoModel().grant_users_group_permission(
359 363 repo=cur_repo, group_name=member, perm=perm
360 364 )
361 365 #TODO: implement this
362 366 #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
363 367 # repo_name, self.ip_addr, self.sa)
364 368 Session().commit()
365 369 h.flash(_('Repository permissions updated'), category='success')
366 370 return redirect(url('edit_repo', repo_name=repo_name))
367 371
368 372 @HasRepoPermissionAllDecorator('repository.admin')
369 373 def delete_perm_user(self, repo_name):
370 374 """
371 375 DELETE an existing repository permission user
372 376
373 377 :param repo_name:
374 378 """
375 379 try:
376 380 RepoModel().revoke_user_permission(repo=repo_name,
377 381 user=request.POST['user_id'])
378 382 #TODO: implement this
379 383 #action_logger(self.rhodecode_user, 'admin_revoked_repo_permissions',
380 384 # repo_name, self.ip_addr, self.sa)
381 385 Session().commit()
382 386 except Exception:
383 387 log.error(traceback.format_exc())
384 388 h.flash(_('An error occurred during deletion of repository user'),
385 389 category='error')
386 390 raise HTTPInternalServerError()
387 391
388 392 @HasRepoPermissionAllDecorator('repository.admin')
389 393 def delete_perm_users_group(self, repo_name):
390 394 """
391 395 DELETE an existing repository permission user group
392 396
393 397 :param repo_name:
394 398 """
395 399
396 400 try:
397 401 RepoModel().revoke_users_group_permission(
398 402 repo=repo_name, group_name=request.POST['users_group_id']
399 403 )
400 404 Session().commit()
401 405 except Exception:
402 406 log.error(traceback.format_exc())
403 407 h.flash(_('An error occurred during deletion of repository'
404 408 ' user groups'),
405 409 category='error')
406 410 raise HTTPInternalServerError()
407 411
408 412 @HasRepoPermissionAllDecorator('repository.admin')
409 413 def repo_stats(self, repo_name):
410 414 """
411 415 DELETE an existing repository statistics
412 416
413 417 :param repo_name:
414 418 """
415 419
416 420 try:
417 421 RepoModel().delete_stats(repo_name)
418 422 Session().commit()
419 423 except Exception, e:
420 424 log.error(traceback.format_exc())
421 425 h.flash(_('An error occurred during deletion of repository stats'),
422 426 category='error')
423 427 return redirect(url('edit_repo', repo_name=repo_name))
424 428
425 429 @HasRepoPermissionAllDecorator('repository.admin')
426 430 def repo_cache(self, repo_name):
427 431 """
428 432 INVALIDATE existing repository cache
429 433
430 434 :param repo_name:
431 435 """
432 436
433 437 try:
434 438 ScmModel().mark_for_invalidation(repo_name)
435 439 Session().commit()
436 440 except Exception, e:
437 441 log.error(traceback.format_exc())
438 442 h.flash(_('An error occurred during cache invalidation'),
439 443 category='error')
440 444 return redirect(url('edit_repo', repo_name=repo_name))
441 445
442 446 @HasRepoPermissionAllDecorator('repository.admin')
443 447 def repo_locking(self, repo_name):
444 448 """
445 449 Unlock repository when it is locked !
446 450
447 451 :param repo_name:
448 452 """
449 453
450 454 try:
451 455 repo = Repository.get_by_repo_name(repo_name)
452 456 if request.POST.get('set_lock'):
453 457 Repository.lock(repo, c.rhodecode_user.user_id)
454 458 elif request.POST.get('set_unlock'):
455 459 Repository.unlock(repo)
456 460 except Exception, e:
457 461 log.error(traceback.format_exc())
458 462 h.flash(_('An error occurred during unlocking'),
459 463 category='error')
460 464 return redirect(url('edit_repo', repo_name=repo_name))
461 465
462 466 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
463 467 def toggle_locking(self, repo_name):
464 468 """
465 469 Toggle locking of repository by simple GET call to url
466 470
467 471 :param repo_name:
468 472 """
469 473
470 474 try:
471 475 repo = Repository.get_by_repo_name(repo_name)
472 476
473 477 if repo.enable_locking:
474 478 if repo.locked[0]:
475 479 Repository.unlock(repo)
476 480 action = _('Unlocked')
477 481 else:
478 482 Repository.lock(repo, c.rhodecode_user.user_id)
479 483 action = _('Locked')
480 484
481 485 h.flash(_('Repository has been %s') % action,
482 486 category='success')
483 487 except Exception, e:
484 488 log.error(traceback.format_exc())
485 489 h.flash(_('An error occurred during unlocking'),
486 490 category='error')
487 491 return redirect(url('summary_home', repo_name=repo_name))
488 492
489 493 @HasRepoPermissionAllDecorator('repository.admin')
490 494 def repo_public_journal(self, repo_name):
491 495 """
492 496 Set's this repository to be visible in public journal,
493 497 in other words assing default user to follow this repo
494 498
495 499 :param repo_name:
496 500 """
497 501
498 502 cur_token = request.POST.get('auth_token')
499 503 token = get_token()
500 504 if cur_token == token:
501 505 try:
502 506 repo_id = Repository.get_by_repo_name(repo_name).repo_id
503 507 user_id = User.get_by_username('default').user_id
504 508 self.scm_model.toggle_following_repo(repo_id, user_id)
505 509 h.flash(_('Updated repository visibility in public journal'),
506 510 category='success')
507 511 Session().commit()
508 512 except Exception:
509 513 h.flash(_('An error occurred during setting this'
510 514 ' repository in public journal'),
511 515 category='error')
512 516
513 517 else:
514 518 h.flash(_('Token mismatch'), category='error')
515 519 return redirect(url('edit_repo', repo_name=repo_name))
516 520
517 521 @HasRepoPermissionAllDecorator('repository.admin')
518 522 def repo_pull(self, repo_name):
519 523 """
520 524 Runs task to update given repository with remote changes,
521 525 ie. make pull on remote location
522 526
523 527 :param repo_name:
524 528 """
525 529 try:
526 530 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
527 531 h.flash(_('Pulled from remote location'), category='success')
528 532 except Exception, e:
529 533 h.flash(_('An error occurred during pull from remote location'),
530 534 category='error')
531 535
532 536 return redirect(url('edit_repo', repo_name=repo_name))
533 537
534 538 @HasRepoPermissionAllDecorator('repository.admin')
535 539 def repo_as_fork(self, repo_name):
536 540 """
537 541 Mark given repository as a fork of another
538 542
539 543 :param repo_name:
540 544 """
541 545 try:
542 546 fork_id = request.POST.get('id_fork_of')
543 547 repo = ScmModel().mark_as_fork(repo_name, fork_id,
544 548 self.rhodecode_user.username)
545 549 fork = repo.fork.repo_name if repo.fork else _('Nothing')
546 550 Session().commit()
547 551 h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
548 552 category='success')
549 553 except Exception, e:
550 554 log.error(traceback.format_exc())
551 555 h.flash(_('An error occurred during this operation'),
552 556 category='error')
553 557
554 558 return redirect(url('edit_repo', repo_name=repo_name))
555 559
556 560 @HasPermissionAllDecorator('hg.admin')
557 561 def show(self, repo_name, format='html'):
558 562 """GET /repos/repo_name: Show a specific item"""
559 563 # url('repo', repo_name=ID)
560 564
561 565 @HasRepoPermissionAllDecorator('repository.admin')
562 566 def edit(self, repo_name, format='html'):
563 567 """GET /repos/repo_name/edit: Form to edit an existing item"""
564 568 # url('edit_repo', repo_name=ID)
565 569 defaults = self.__load_data(repo_name)
566 570
567 571 return htmlfill.render(
568 572 render('admin/repos/repo_edit.html'),
569 573 defaults=defaults,
570 574 encoding="UTF-8",
571 575 force_defaults=False
572 576 )
573 577
574 578 @HasPermissionAllDecorator('hg.admin')
575 579 def create_repo_field(self, repo_name):
576 580 try:
577 581 form_result = RepoFieldForm()().to_python(dict(request.POST))
578 582 new_field = RepositoryField()
579 583 new_field.repository = Repository.get_by_repo_name(repo_name)
580 584 new_field.field_key = form_result['new_field_key']
581 585 new_field.field_type = form_result['new_field_type'] # python type
582 586 new_field.field_value = form_result['new_field_value'] # set initial blank value
583 587 new_field.field_desc = form_result['new_field_desc']
584 588 new_field.field_label = form_result['new_field_label']
585 589 Session().add(new_field)
586 590 Session().commit()
587 591
588 592 except Exception, e:
589 593 log.error(traceback.format_exc())
590 594 msg = _('An error occurred during creation of field')
591 595 if isinstance(e, formencode.Invalid):
592 596 msg += ". " + e.msg
593 597 h.flash(msg, category='error')
594 598 return redirect(url('edit_repo', repo_name=repo_name))
595 599
596 600 @HasPermissionAllDecorator('hg.admin')
597 601 def delete_repo_field(self, repo_name, field_id):
598 602 field = RepositoryField.get_or_404(field_id)
599 603 try:
600 604 Session().delete(field)
601 605 Session().commit()
602 606 except Exception, e:
603 607 log.error(traceback.format_exc())
604 608 msg = _('An error occurred during removal of field')
605 609 h.flash(msg, category='error')
606 610 return redirect(url('edit_repo', repo_name=repo_name))
@@ -1,384 +1,385 b''
1 1 """ this is forms validation classes
2 2 http://formencode.org/module-formencode.validators.html
3 3 for list off all availible validators
4 4
5 5 we can create our own validators
6 6
7 7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 8 pre_validators [] These validators will be applied before the schema
9 9 chained_validators [] These validators will be applied after the schema
10 10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14 14
15 15
16 16 <name> = formencode.validators.<name of validator>
17 17 <name> must equal form name
18 18 list=[1,2,3,4,5]
19 19 for SELECT use formencode.All(OneOf(list), Int())
20 20
21 21 """
22 22 import logging
23 23
24 24 import formencode
25 25 from formencode import All
26 26
27 27 from pylons.i18n.translation import _
28 28
29 29 from rhodecode.model import validators as v
30 30 from rhodecode import BACKENDS
31 31
32 32 log = logging.getLogger(__name__)
33 33
34 34
35 35 class LoginForm(formencode.Schema):
36 36 allow_extra_fields = True
37 37 filter_extra_fields = True
38 38 username = v.UnicodeString(
39 39 strip=True,
40 40 min=1,
41 41 not_empty=True,
42 42 messages={
43 43 'empty': _(u'Please enter a login'),
44 44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
45 45 )
46 46
47 47 password = v.UnicodeString(
48 48 strip=False,
49 49 min=3,
50 50 not_empty=True,
51 51 messages={
52 52 'empty': _(u'Please enter a password'),
53 53 'tooShort': _(u'Enter %(min)i characters or more')}
54 54 )
55 55
56 56 remember = v.StringBoolean(if_missing=False)
57 57
58 58 chained_validators = [v.ValidAuth()]
59 59
60 60
61 61 def UserForm(edit=False, old_data={}):
62 62 class _UserForm(formencode.Schema):
63 63 allow_extra_fields = True
64 64 filter_extra_fields = True
65 65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
66 66 v.ValidUsername(edit, old_data))
67 67 if edit:
68 68 new_password = All(
69 69 v.ValidPassword(),
70 70 v.UnicodeString(strip=False, min=6, not_empty=False)
71 71 )
72 72 password_confirmation = All(
73 73 v.ValidPassword(),
74 74 v.UnicodeString(strip=False, min=6, not_empty=False),
75 75 )
76 76 admin = v.StringBoolean(if_missing=False)
77 77 else:
78 78 password = All(
79 79 v.ValidPassword(),
80 80 v.UnicodeString(strip=False, min=6, not_empty=True)
81 81 )
82 82 password_confirmation = All(
83 83 v.ValidPassword(),
84 84 v.UnicodeString(strip=False, min=6, not_empty=False)
85 85 )
86 86
87 87 active = v.StringBoolean(if_missing=False)
88 88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
90 90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
91 91
92 92 chained_validators = [v.ValidPasswordsMatch()]
93 93
94 94 return _UserForm
95 95
96 96
97 97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
98 98 class _UserGroupForm(formencode.Schema):
99 99 allow_extra_fields = True
100 100 filter_extra_fields = True
101 101
102 102 users_group_name = All(
103 103 v.UnicodeString(strip=True, min=1, not_empty=True),
104 104 v.ValidUserGroup(edit, old_data)
105 105 )
106 106
107 107 users_group_active = v.StringBoolean(if_missing=False)
108 108
109 109 if edit:
110 110 users_group_members = v.OneOf(
111 111 available_members, hideList=False, testValueList=True,
112 112 if_missing=None, not_empty=False
113 113 )
114 114
115 115 return _UserGroupForm
116 116
117 117
118 118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
119 119 can_create_in_root=False):
120 120 class _ReposGroupForm(formencode.Schema):
121 121 allow_extra_fields = True
122 122 filter_extra_fields = False
123 123
124 124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
125 125 v.SlugifyName())
126 126 group_description = v.UnicodeString(strip=True, min=1,
127 127 not_empty=False)
128 128 if edit:
129 129 #FIXME: do a special check that we cannot move a group to one of
130 130 #it's children
131 131 pass
132 132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
133 133 v.OneOf(available_groups, hideList=False,
134 134 testValueList=True,
135 135 if_missing=None, not_empty=True))
136 136 enable_locking = v.StringBoolean(if_missing=False)
137 137 recursive = v.StringBoolean(if_missing=False)
138 138 chained_validators = [v.ValidReposGroup(edit, old_data),
139 139 v.ValidPerms('group')]
140 140
141 141 return _ReposGroupForm
142 142
143 143
144 144 def RegisterForm(edit=False, old_data={}):
145 145 class _RegisterForm(formencode.Schema):
146 146 allow_extra_fields = True
147 147 filter_extra_fields = True
148 148 username = All(
149 149 v.ValidUsername(edit, old_data),
150 150 v.UnicodeString(strip=True, min=1, not_empty=True)
151 151 )
152 152 password = All(
153 153 v.ValidPassword(),
154 154 v.UnicodeString(strip=False, min=6, not_empty=True)
155 155 )
156 156 password_confirmation = All(
157 157 v.ValidPassword(),
158 158 v.UnicodeString(strip=False, min=6, not_empty=True)
159 159 )
160 160 active = v.StringBoolean(if_missing=False)
161 161 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
162 162 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
163 163 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
164 164
165 165 chained_validators = [v.ValidPasswordsMatch()]
166 166
167 167 return _RegisterForm
168 168
169 169
170 170 def PasswordResetForm():
171 171 class _PasswordResetForm(formencode.Schema):
172 172 allow_extra_fields = True
173 173 filter_extra_fields = True
174 174 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
175 175 return _PasswordResetForm
176 176
177 177
178 178 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
179 179 repo_groups=[], landing_revs=[]):
180 180 class _RepoForm(formencode.Schema):
181 181 allow_extra_fields = True
182 182 filter_extra_fields = False
183 183 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
184 184 v.SlugifyName())
185 185 repo_group = All(v.CanWriteGroup(old_data),
186 186 v.OneOf(repo_groups, hideList=True))
187 repo_type = v.OneOf(supported_backends)
187 repo_type = v.OneOf(supported_backends, required=False,
188 if_missing=old_data.get('repo_type'))
188 189 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
189 190 repo_private = v.StringBoolean(if_missing=False)
190 191 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
191 192 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
192 193
193 194 repo_enable_statistics = v.StringBoolean(if_missing=False)
194 195 repo_enable_downloads = v.StringBoolean(if_missing=False)
195 196 repo_enable_locking = v.StringBoolean(if_missing=False)
196 197
197 198 if edit:
198 199 #this is repo owner
199 200 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
200 201
201 202 chained_validators = [v.ValidCloneUri(),
202 203 v.ValidRepoName(edit, old_data)]
203 204 return _RepoForm
204 205
205 206
206 207 def RepoPermsForm():
207 208 class _RepoPermsForm(formencode.Schema):
208 209 allow_extra_fields = True
209 210 filter_extra_fields = False
210 211 chained_validators = [v.ValidPerms()]
211 212 return _RepoPermsForm
212 213
213 214
214 215 def RepoFieldForm():
215 216 class _RepoFieldForm(formencode.Schema):
216 217 filter_extra_fields = True
217 218 allow_extra_fields = True
218 219
219 220 new_field_key = All(v.FieldKey(),
220 221 v.UnicodeString(strip=True, min=3, not_empty=True))
221 222 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
222 223 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
223 224 if_missing='str')
224 225 new_field_label = v.UnicodeString(not_empty=False)
225 226 new_field_desc = v.UnicodeString(not_empty=False)
226 227
227 228 return _RepoFieldForm
228 229
229 230
230 231 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
231 232 repo_groups=[], landing_revs=[]):
232 233 class _RepoForkForm(formencode.Schema):
233 234 allow_extra_fields = True
234 235 filter_extra_fields = False
235 236 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
236 237 v.SlugifyName())
237 238 repo_group = All(v.CanWriteGroup(),
238 239 v.OneOf(repo_groups, hideList=True))
239 240 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
240 241 description = v.UnicodeString(strip=True, min=1, not_empty=True)
241 242 private = v.StringBoolean(if_missing=False)
242 243 copy_permissions = v.StringBoolean(if_missing=False)
243 244 update_after_clone = v.StringBoolean(if_missing=False)
244 245 fork_parent_id = v.UnicodeString()
245 246 chained_validators = [v.ValidForkName(edit, old_data)]
246 247 landing_rev = v.OneOf(landing_revs, hideList=True)
247 248
248 249 return _RepoForkForm
249 250
250 251
251 252 def ApplicationSettingsForm():
252 253 class _ApplicationSettingsForm(formencode.Schema):
253 254 allow_extra_fields = True
254 255 filter_extra_fields = False
255 256 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
256 257 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
257 258 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
258 259
259 260 return _ApplicationSettingsForm
260 261
261 262
262 263 def ApplicationVisualisationForm():
263 264 class _ApplicationVisualisationForm(formencode.Schema):
264 265 allow_extra_fields = True
265 266 filter_extra_fields = False
266 267 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
267 268 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
268 269 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
269 270
270 271 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
271 272 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
272 273 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
273 274
274 275 return _ApplicationVisualisationForm
275 276
276 277
277 278 def ApplicationUiSettingsForm():
278 279 class _ApplicationUiSettingsForm(formencode.Schema):
279 280 allow_extra_fields = True
280 281 filter_extra_fields = False
281 282 web_push_ssl = v.StringBoolean(if_missing=False)
282 283 paths_root_path = All(
283 284 v.ValidPath(),
284 285 v.UnicodeString(strip=True, min=1, not_empty=True)
285 286 )
286 287 hooks_changegroup_update = v.StringBoolean(if_missing=False)
287 288 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
288 289 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
289 290 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
290 291
291 292 extensions_largefiles = v.StringBoolean(if_missing=False)
292 293 extensions_hgsubversion = v.StringBoolean(if_missing=False)
293 294 extensions_hggit = v.StringBoolean(if_missing=False)
294 295
295 296 return _ApplicationUiSettingsForm
296 297
297 298
298 299 def DefaultPermissionsForm(repo_perms_choices, group_perms_choices,
299 300 register_choices, create_choices, fork_choices):
300 301 class _DefaultPermissionsForm(formencode.Schema):
301 302 allow_extra_fields = True
302 303 filter_extra_fields = True
303 304 overwrite_default_repo = v.StringBoolean(if_missing=False)
304 305 overwrite_default_group = v.StringBoolean(if_missing=False)
305 306 anonymous = v.StringBoolean(if_missing=False)
306 307 default_repo_perm = v.OneOf(repo_perms_choices)
307 308 default_group_perm = v.OneOf(group_perms_choices)
308 309 default_register = v.OneOf(register_choices)
309 310 default_create = v.OneOf(create_choices)
310 311 default_fork = v.OneOf(fork_choices)
311 312
312 313 return _DefaultPermissionsForm
313 314
314 315
315 316 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
316 317 class _DefaultsForm(formencode.Schema):
317 318 allow_extra_fields = True
318 319 filter_extra_fields = True
319 320 default_repo_type = v.OneOf(supported_backends)
320 321 default_repo_private = v.StringBoolean(if_missing=False)
321 322 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
322 323 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
323 324 default_repo_enable_locking = v.StringBoolean(if_missing=False)
324 325
325 326 return _DefaultsForm
326 327
327 328
328 329 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
329 330 tls_kind_choices):
330 331 class _LdapSettingsForm(formencode.Schema):
331 332 allow_extra_fields = True
332 333 filter_extra_fields = True
333 334 #pre_validators = [LdapLibValidator]
334 335 ldap_active = v.StringBoolean(if_missing=False)
335 336 ldap_host = v.UnicodeString(strip=True,)
336 337 ldap_port = v.Number(strip=True,)
337 338 ldap_tls_kind = v.OneOf(tls_kind_choices)
338 339 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
339 340 ldap_dn_user = v.UnicodeString(strip=True,)
340 341 ldap_dn_pass = v.UnicodeString(strip=True,)
341 342 ldap_base_dn = v.UnicodeString(strip=True,)
342 343 ldap_filter = v.UnicodeString(strip=True,)
343 344 ldap_search_scope = v.OneOf(search_scope_choices)
344 345 ldap_attr_login = v.AttrLoginValidator()(not_empty=True)
345 346 ldap_attr_firstname = v.UnicodeString(strip=True,)
346 347 ldap_attr_lastname = v.UnicodeString(strip=True,)
347 348 ldap_attr_email = v.UnicodeString(strip=True,)
348 349
349 350 return _LdapSettingsForm
350 351
351 352
352 353 def UserExtraEmailForm():
353 354 class _UserExtraEmailForm(formencode.Schema):
354 355 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
355 356 return _UserExtraEmailForm
356 357
357 358
358 359 def UserExtraIpForm():
359 360 class _UserExtraIpForm(formencode.Schema):
360 361 ip = v.ValidIp()(not_empty=True)
361 362 return _UserExtraIpForm
362 363
363 364
364 365 def PullRequestForm(repo_id):
365 366 class _PullRequestForm(formencode.Schema):
366 367 allow_extra_fields = True
367 368 filter_extra_fields = True
368 369
369 370 user = v.UnicodeString(strip=True, required=True)
370 371 org_repo = v.UnicodeString(strip=True, required=True)
371 372 org_ref = v.UnicodeString(strip=True, required=True)
372 373 other_repo = v.UnicodeString(strip=True, required=True)
373 374 other_ref = v.UnicodeString(strip=True, required=True)
374 375 revisions = All(#v.NotReviewedRevisions(repo_id)(),
375 376 v.UniqueList(not_empty=True))
376 377 review_members = v.UniqueList(not_empty=True)
377 378
378 379 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
379 380 pullrequest_desc = v.UnicodeString(strip=True, required=False)
380 381
381 382 ancestor_rev = v.UnicodeString(strip=True, required=True)
382 383 merge_rev = v.UnicodeString(strip=True, required=True)
383 384
384 385 return _PullRequestForm
General Comments 0
You need to be logged in to leave comments. Login now