##// END OF EJS Templates
admin: ported settings controller to pyramid....
marcink -
r2333:c9f5d931 default
parent child
Show More
This diff has been collapsed as it changes many lines, (754 lines changed) Show them Hide them
@@ -0,0 +1,754
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23 import collections
24
25 import datetime
26 import formencode
27 import formencode.htmlfill
28
29 import rhodecode
30 from pyramid.view import view_config
31 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
32 from pyramid.renderers import render
33 from pyramid.response import Response
34
35 from rhodecode.apps._base import BaseAppView
36 from rhodecode.apps.admin.navigation import navigation_list
37 from rhodecode.apps.svn_support.config_keys import generate_config
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import (
40 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
41 from rhodecode.lib.celerylib import tasks, run_task
42 from rhodecode.lib.utils import repo2db_mapper
43 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
44 from rhodecode.lib.index import searcher_from_config
45
46 from rhodecode.model.db import RhodeCodeUi, Repository
47 from rhodecode.model.forms import (ApplicationSettingsForm,
48 ApplicationUiSettingsForm, ApplicationVisualisationForm,
49 LabsSettingsForm, IssueTrackerPatternsForm)
50 from rhodecode.model.repo_group import RepoGroupModel
51
52 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.notification import EmailNotificationModel
54 from rhodecode.model.meta import Session
55 from rhodecode.model.settings import (
56 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
57 SettingsModel)
58
59
60 log = logging.getLogger(__name__)
61
62
63 class AdminSettingsView(BaseAppView):
64
65 def load_default_context(self):
66 c = self._get_local_tmpl_context()
67 c.labs_active = str2bool(
68 rhodecode.CONFIG.get('labs_settings_active', 'true'))
69 c.navlist = navigation_list(self.request)
70 self._register_global_c(c)
71 return c
72
73 @classmethod
74 def _get_ui_settings(cls):
75 ret = RhodeCodeUi.query().all()
76
77 if not ret:
78 raise Exception('Could not get application ui settings !')
79 settings = {}
80 for each in ret:
81 k = each.ui_key
82 v = each.ui_value
83 if k == '/':
84 k = 'root_path'
85
86 if k in ['push_ssl', 'publish', 'enabled']:
87 v = str2bool(v)
88
89 if k.find('.') != -1:
90 k = k.replace('.', '_')
91
92 if each.ui_section in ['hooks', 'extensions']:
93 v = each.ui_active
94
95 settings[each.ui_section + '_' + k] = v
96 return settings
97
98 @classmethod
99 def _form_defaults(cls):
100 defaults = SettingsModel().get_all_settings()
101 defaults.update(cls._get_ui_settings())
102
103 defaults.update({
104 'new_svn_branch': '',
105 'new_svn_tag': '',
106 })
107 return defaults
108
109 @LoginRequired()
110 @HasPermissionAllDecorator('hg.admin')
111 @view_config(
112 route_name='admin_settings_vcs', request_method='GET',
113 renderer='rhodecode:templates/admin/settings/settings.mako')
114 def settings_vcs(self):
115 c = self.load_default_context()
116 c.active = 'vcs'
117 model = VcsSettingsModel()
118 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
119 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
120
121 settings = self.request.registry.settings
122 c.svn_proxy_generate_config = settings[generate_config]
123
124 defaults = self._form_defaults()
125
126 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
127
128 data = render('rhodecode:templates/admin/settings/settings.mako',
129 self._get_template_context(c), self.request)
130 html = formencode.htmlfill.render(
131 data,
132 defaults=defaults,
133 encoding="UTF-8",
134 force_defaults=False
135 )
136 return Response(html)
137
138 @LoginRequired()
139 @HasPermissionAllDecorator('hg.admin')
140 @CSRFRequired()
141 @view_config(
142 route_name='admin_settings_vcs_update', request_method='POST',
143 renderer='rhodecode:templates/admin/settings/settings.mako')
144 def settings_vcs_update(self):
145 _ = self.request.translate
146 c = self.load_default_context()
147 c.active = 'vcs'
148
149 model = VcsSettingsModel()
150 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
151 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
152
153 settings = self.request.registry.settings
154 c.svn_proxy_generate_config = settings[generate_config]
155
156 application_form = ApplicationUiSettingsForm()()
157
158 try:
159 form_result = application_form.to_python(dict(self.request.POST))
160 except formencode.Invalid as errors:
161 h.flash(
162 _("Some form inputs contain invalid data."),
163 category='error')
164 data = render('rhodecode:templates/admin/settings/settings.mako',
165 self._get_template_context(c), self.request)
166 html = formencode.htmlfill.render(
167 data,
168 defaults=errors.value,
169 errors=errors.error_dict or {},
170 prefix_error=False,
171 encoding="UTF-8",
172 force_defaults=False
173 )
174 return Response(html)
175
176 try:
177 if c.visual.allow_repo_location_change:
178 model.update_global_path_setting(
179 form_result['paths_root_path'])
180
181 model.update_global_ssl_setting(form_result['web_push_ssl'])
182 model.update_global_hook_settings(form_result)
183
184 model.create_or_update_global_svn_settings(form_result)
185 model.create_or_update_global_hg_settings(form_result)
186 model.create_or_update_global_git_settings(form_result)
187 model.create_or_update_global_pr_settings(form_result)
188 except Exception:
189 log.exception("Exception while updating settings")
190 h.flash(_('Error occurred during updating '
191 'application settings'), category='error')
192 else:
193 Session().commit()
194 h.flash(_('Updated VCS settings'), category='success')
195 raise HTTPFound(h.route_path('admin_settings_vcs'))
196
197 data = render('rhodecode:templates/admin/settings/settings.mako',
198 self._get_template_context(c), self.request)
199 html = formencode.htmlfill.render(
200 data,
201 defaults=self._form_defaults(),
202 encoding="UTF-8",
203 force_defaults=False
204 )
205 return Response(html)
206
207 @LoginRequired()
208 @HasPermissionAllDecorator('hg.admin')
209 @CSRFRequired()
210 @view_config(
211 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
212 renderer='json_ext', xhr=True)
213 def settings_vcs_delete_svn_pattern(self):
214 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
215 model = VcsSettingsModel()
216 try:
217 model.delete_global_svn_pattern(delete_pattern_id)
218 except SettingNotFound:
219 log.exception(
220 'Failed to delete svn_pattern with id %s', delete_pattern_id)
221 raise HTTPNotFound()
222
223 Session().commit()
224 return True
225
226 @LoginRequired()
227 @HasPermissionAllDecorator('hg.admin')
228 @view_config(
229 route_name='admin_settings_mapping', request_method='GET',
230 renderer='rhodecode:templates/admin/settings/settings.mako')
231 def settings_mapping(self):
232 c = self.load_default_context()
233 c.active = 'mapping'
234
235 data = render('rhodecode:templates/admin/settings/settings.mako',
236 self._get_template_context(c), self.request)
237 html = formencode.htmlfill.render(
238 data,
239 defaults=self._form_defaults(),
240 encoding="UTF-8",
241 force_defaults=False
242 )
243 return Response(html)
244
245 @LoginRequired()
246 @HasPermissionAllDecorator('hg.admin')
247 @CSRFRequired()
248 @view_config(
249 route_name='admin_settings_mapping_update', request_method='POST',
250 renderer='rhodecode:templates/admin/settings/settings.mako')
251 def settings_mapping_update(self):
252 _ = self.request.translate
253 c = self.load_default_context()
254 c.active = 'mapping'
255 rm_obsolete = self.request.POST.get('destroy', False)
256 invalidate_cache = self.request.POST.get('invalidate', False)
257 log.debug(
258 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
259
260 if invalidate_cache:
261 log.debug('invalidating all repositories cache')
262 for repo in Repository.get_all():
263 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
264
265 filesystem_repos = ScmModel().repo_scan()
266 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
267 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
268 h.flash(_('Repositories successfully '
269 'rescanned added: %s ; removed: %s') %
270 (_repr(added), _repr(removed)),
271 category='success')
272 raise HTTPFound(h.route_path('admin_settings_mapping'))
273
274 @LoginRequired()
275 @HasPermissionAllDecorator('hg.admin')
276 @view_config(
277 route_name='admin_settings', request_method='GET',
278 renderer='rhodecode:templates/admin/settings/settings.mako')
279 @view_config(
280 route_name='admin_settings_global', request_method='GET',
281 renderer='rhodecode:templates/admin/settings/settings.mako')
282 def settings_global(self):
283 c = self.load_default_context()
284 c.active = 'global'
285 c.personal_repo_group_default_pattern = RepoGroupModel()\
286 .get_personal_group_name_pattern()
287
288 data = render('rhodecode:templates/admin/settings/settings.mako',
289 self._get_template_context(c), self.request)
290 html = formencode.htmlfill.render(
291 data,
292 defaults=self._form_defaults(),
293 encoding="UTF-8",
294 force_defaults=False
295 )
296 return Response(html)
297
298 @LoginRequired()
299 @HasPermissionAllDecorator('hg.admin')
300 @CSRFRequired()
301 @view_config(
302 route_name='admin_settings_update', request_method='POST',
303 renderer='rhodecode:templates/admin/settings/settings.mako')
304 @view_config(
305 route_name='admin_settings_global_update', request_method='POST',
306 renderer='rhodecode:templates/admin/settings/settings.mako')
307 def settings_global_update(self):
308 _ = self.request.translate
309 c = self.load_default_context()
310 c.active = 'global'
311 c.personal_repo_group_default_pattern = RepoGroupModel()\
312 .get_personal_group_name_pattern()
313 application_form = ApplicationSettingsForm()()
314 try:
315 form_result = application_form.to_python(dict(self.request.POST))
316 except formencode.Invalid as errors:
317 data = render('rhodecode:templates/admin/settings/settings.mako',
318 self._get_template_context(c), self.request)
319 html = formencode.htmlfill.render(
320 data,
321 defaults=errors.value,
322 errors=errors.error_dict or {},
323 prefix_error=False,
324 encoding="UTF-8",
325 force_defaults=False
326 )
327 return Response(html)
328
329 settings = [
330 ('title', 'rhodecode_title', 'unicode'),
331 ('realm', 'rhodecode_realm', 'unicode'),
332 ('pre_code', 'rhodecode_pre_code', 'unicode'),
333 ('post_code', 'rhodecode_post_code', 'unicode'),
334 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
335 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
336 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
337 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
338 ]
339 try:
340 for setting, form_key, type_ in settings:
341 sett = SettingsModel().create_or_update_setting(
342 setting, form_result[form_key], type_)
343 Session().add(sett)
344
345 Session().commit()
346 SettingsModel().invalidate_settings_cache()
347 h.flash(_('Updated application settings'), category='success')
348 except Exception:
349 log.exception("Exception while updating application settings")
350 h.flash(
351 _('Error occurred during updating application settings'),
352 category='error')
353
354 raise HTTPFound(h.route_path('admin_settings_global'))
355
356 @LoginRequired()
357 @HasPermissionAllDecorator('hg.admin')
358 @view_config(
359 route_name='admin_settings_visual', request_method='GET',
360 renderer='rhodecode:templates/admin/settings/settings.mako')
361 def settings_visual(self):
362 c = self.load_default_context()
363 c.active = 'visual'
364
365 data = render('rhodecode:templates/admin/settings/settings.mako',
366 self._get_template_context(c), self.request)
367 html = formencode.htmlfill.render(
368 data,
369 defaults=self._form_defaults(),
370 encoding="UTF-8",
371 force_defaults=False
372 )
373 return Response(html)
374
375 @LoginRequired()
376 @HasPermissionAllDecorator('hg.admin')
377 @CSRFRequired()
378 @view_config(
379 route_name='admin_settings_visual_update', request_method='POST',
380 renderer='rhodecode:templates/admin/settings/settings.mako')
381 def settings_visual_update(self):
382 _ = self.request.translate
383 c = self.load_default_context()
384 c.active = 'visual'
385 application_form = ApplicationVisualisationForm()()
386 try:
387 form_result = application_form.to_python(dict(self.request.POST))
388 except formencode.Invalid as errors:
389 data = render('rhodecode:templates/admin/settings/settings.mako',
390 self._get_template_context(c), self.request)
391 html = formencode.htmlfill.render(
392 data,
393 defaults=errors.value,
394 errors=errors.error_dict or {},
395 prefix_error=False,
396 encoding="UTF-8",
397 force_defaults=False
398 )
399 return Response(html)
400
401 try:
402 settings = [
403 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
404 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
405 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
406 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
407 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
408 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
409 ('show_version', 'rhodecode_show_version', 'bool'),
410 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
411 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
412 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
413 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
414 ('support_url', 'rhodecode_support_url', 'unicode'),
415 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
416 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
417 ]
418 for setting, form_key, type_ in settings:
419 sett = SettingsModel().create_or_update_setting(
420 setting, form_result[form_key], type_)
421 Session().add(sett)
422
423 Session().commit()
424 SettingsModel().invalidate_settings_cache()
425 h.flash(_('Updated visualisation settings'), category='success')
426 except Exception:
427 log.exception("Exception updating visualization settings")
428 h.flash(_('Error occurred during updating '
429 'visualisation settings'),
430 category='error')
431
432 raise HTTPFound(h.route_path('admin_settings_visual'))
433
434 @LoginRequired()
435 @HasPermissionAllDecorator('hg.admin')
436 @view_config(
437 route_name='admin_settings_issuetracker', request_method='GET',
438 renderer='rhodecode:templates/admin/settings/settings.mako')
439 def settings_issuetracker(self):
440 c = self.load_default_context()
441 c.active = 'issuetracker'
442 defaults = SettingsModel().get_all_settings()
443
444 entry_key = 'rhodecode_issuetracker_pat_'
445
446 c.issuetracker_entries = {}
447 for k, v in defaults.items():
448 if k.startswith(entry_key):
449 uid = k[len(entry_key):]
450 c.issuetracker_entries[uid] = None
451
452 for uid in c.issuetracker_entries:
453 c.issuetracker_entries[uid] = AttributeDict({
454 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
455 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
456 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
457 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
458 })
459
460 return self._get_template_context(c)
461
462 @LoginRequired()
463 @HasPermissionAllDecorator('hg.admin')
464 @CSRFRequired()
465 @view_config(
466 route_name='admin_settings_issuetracker_test', request_method='POST',
467 renderer='string', xhr=True)
468 def settings_issuetracker_test(self):
469 return h.urlify_commit_message(
470 self.request.POST.get('test_text', ''),
471 'repo_group/test_repo1')
472
473 @LoginRequired()
474 @HasPermissionAllDecorator('hg.admin')
475 @CSRFRequired()
476 @view_config(
477 route_name='admin_settings_issuetracker_update', request_method='POST',
478 renderer='rhodecode:templates/admin/settings/settings.mako')
479 def settings_issuetracker_update(self):
480 _ = self.request.translate
481 self.load_default_context()
482 settings_model = IssueTrackerSettingsModel()
483
484 form = IssueTrackerPatternsForm()().to_python(self.request.POST)
485 if form:
486 for uid in form.get('delete_patterns', []):
487 settings_model.delete_entries(uid)
488
489 for pattern in form.get('patterns', []):
490 for setting, value, type_ in pattern:
491 sett = settings_model.create_or_update_setting(
492 setting, value, type_)
493 Session().add(sett)
494
495 Session().commit()
496
497 SettingsModel().invalidate_settings_cache()
498 h.flash(_('Updated issue tracker entries'), category='success')
499 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
500
501 @LoginRequired()
502 @HasPermissionAllDecorator('hg.admin')
503 @CSRFRequired()
504 @view_config(
505 route_name='admin_settings_issuetracker_delete', request_method='POST',
506 renderer='rhodecode:templates/admin/settings/settings.mako')
507 def settings_issuetracker_delete(self):
508 _ = self.request.translate
509 self.load_default_context()
510 uid = self.request.POST.get('uid')
511 try:
512 IssueTrackerSettingsModel().delete_entries(uid)
513 except Exception:
514 log.exception('Failed to delete issue tracker setting %s', uid)
515 raise HTTPNotFound()
516 h.flash(_('Removed issue tracker entry'), category='success')
517 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
518
519 @LoginRequired()
520 @HasPermissionAllDecorator('hg.admin')
521 @view_config(
522 route_name='admin_settings_email', request_method='GET',
523 renderer='rhodecode:templates/admin/settings/settings.mako')
524 def settings_email(self):
525 c = self.load_default_context()
526 c.active = 'email'
527 c.rhodecode_ini = rhodecode.CONFIG
528
529 data = render('rhodecode:templates/admin/settings/settings.mako',
530 self._get_template_context(c), self.request)
531 html = formencode.htmlfill.render(
532 data,
533 defaults=self._form_defaults(),
534 encoding="UTF-8",
535 force_defaults=False
536 )
537 return Response(html)
538
539 @LoginRequired()
540 @HasPermissionAllDecorator('hg.admin')
541 @CSRFRequired()
542 @view_config(
543 route_name='admin_settings_email_update', request_method='POST',
544 renderer='rhodecode:templates/admin/settings/settings.mako')
545 def settings_email_update(self):
546 _ = self.request.translate
547 c = self.load_default_context()
548 c.active = 'email'
549
550 test_email = self.request.POST.get('test_email')
551
552 if not test_email:
553 h.flash(_('Please enter email address'), category='error')
554 raise HTTPFound(h.route_path('admin_settings_email'))
555
556 email_kwargs = {
557 'date': datetime.datetime.now(),
558 'user': c.rhodecode_user,
559 'rhodecode_version': c.rhodecode_version
560 }
561
562 (subject, headers, email_body,
563 email_body_plaintext) = EmailNotificationModel().render_email(
564 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
565
566 recipients = [test_email] if test_email else None
567
568 run_task(tasks.send_email, recipients, subject,
569 email_body_plaintext, email_body)
570
571 h.flash(_('Send email task created'), category='success')
572 raise HTTPFound(h.route_path('admin_settings_email'))
573
574 @LoginRequired()
575 @HasPermissionAllDecorator('hg.admin')
576 @view_config(
577 route_name='admin_settings_hooks', request_method='GET',
578 renderer='rhodecode:templates/admin/settings/settings.mako')
579 def settings_hooks(self):
580 c = self.load_default_context()
581 c.active = 'hooks'
582
583 model = SettingsModel()
584 c.hooks = model.get_builtin_hooks()
585 c.custom_hooks = model.get_custom_hooks()
586
587 data = render('rhodecode:templates/admin/settings/settings.mako',
588 self._get_template_context(c), self.request)
589 html = formencode.htmlfill.render(
590 data,
591 defaults=self._form_defaults(),
592 encoding="UTF-8",
593 force_defaults=False
594 )
595 return Response(html)
596
597 @LoginRequired()
598 @HasPermissionAllDecorator('hg.admin')
599 @CSRFRequired()
600 @view_config(
601 route_name='admin_settings_hooks_update', request_method='POST',
602 renderer='rhodecode:templates/admin/settings/settings.mako')
603 @view_config(
604 route_name='admin_settings_hooks_delete', request_method='POST',
605 renderer='rhodecode:templates/admin/settings/settings.mako')
606 def settings_hooks_update(self):
607 _ = self.request.translate
608 c = self.load_default_context()
609 c.active = 'hooks'
610 if c.visual.allow_custom_hooks_settings:
611 ui_key = self.request.POST.get('new_hook_ui_key')
612 ui_value = self.request.POST.get('new_hook_ui_value')
613
614 hook_id = self.request.POST.get('hook_id')
615 new_hook = False
616
617 model = SettingsModel()
618 try:
619 if ui_value and ui_key:
620 model.create_or_update_hook(ui_key, ui_value)
621 h.flash(_('Added new hook'), category='success')
622 new_hook = True
623 elif hook_id:
624 RhodeCodeUi.delete(hook_id)
625 Session().commit()
626
627 # check for edits
628 update = False
629 _d = self.request.POST.dict_of_lists()
630 for k, v in zip(_d.get('hook_ui_key', []),
631 _d.get('hook_ui_value_new', [])):
632 model.create_or_update_hook(k, v)
633 update = True
634
635 if update and not new_hook:
636 h.flash(_('Updated hooks'), category='success')
637 Session().commit()
638 except Exception:
639 log.exception("Exception during hook creation")
640 h.flash(_('Error occurred during hook creation'),
641 category='error')
642
643 raise HTTPFound(h.route_path('admin_settings_hooks'))
644
645 @LoginRequired()
646 @HasPermissionAllDecorator('hg.admin')
647 @view_config(
648 route_name='admin_settings_search', request_method='GET',
649 renderer='rhodecode:templates/admin/settings/settings.mako')
650 def settings_search(self):
651 c = self.load_default_context()
652 c.active = 'search'
653
654 searcher = searcher_from_config(self.request.registry.settings)
655 c.statistics = searcher.statistics()
656
657 return self._get_template_context(c)
658
659 @LoginRequired()
660 @HasPermissionAllDecorator('hg.admin')
661 @view_config(
662 route_name='admin_settings_labs', request_method='GET',
663 renderer='rhodecode:templates/admin/settings/settings.mako')
664 def settings_labs(self):
665 c = self.load_default_context()
666 if not c.labs_active:
667 raise HTTPFound(h.route_path('admin_settings'))
668
669 c.active = 'labs'
670 c.lab_settings = _LAB_SETTINGS
671
672 data = render('rhodecode:templates/admin/settings/settings.mako',
673 self._get_template_context(c), self.request)
674 html = formencode.htmlfill.render(
675 data,
676 defaults=self._form_defaults(),
677 encoding="UTF-8",
678 force_defaults=False
679 )
680 return Response(html)
681
682 @LoginRequired()
683 @HasPermissionAllDecorator('hg.admin')
684 @CSRFRequired()
685 @view_config(
686 route_name='admin_settings_labs_update', request_method='POST',
687 renderer='rhodecode:templates/admin/settings/settings.mako')
688 def settings_labs_update(self):
689 _ = self.request.translate
690 c = self.load_default_context()
691 c.active = 'labs'
692
693 application_form = LabsSettingsForm()()
694 try:
695 form_result = application_form.to_python(dict(self.request.POST))
696 except formencode.Invalid as errors:
697 h.flash(
698 _('Some form inputs contain invalid data.'),
699 category='error')
700 data = render('rhodecode:templates/admin/settings/settings.mako',
701 self._get_template_context(c), self.request)
702 html = formencode.htmlfill.render(
703 data,
704 defaults=errors.value,
705 errors=errors.error_dict or {},
706 prefix_error=False,
707 encoding="UTF-8",
708 force_defaults=False
709 )
710 return Response(html)
711
712 try:
713 session = Session()
714 for setting in _LAB_SETTINGS:
715 setting_name = setting.key[len('rhodecode_'):]
716 sett = SettingsModel().create_or_update_setting(
717 setting_name, form_result[setting.key], setting.type)
718 session.add(sett)
719
720 except Exception:
721 log.exception('Exception while updating lab settings')
722 h.flash(_('Error occurred during updating labs settings'),
723 category='error')
724 else:
725 Session().commit()
726 SettingsModel().invalidate_settings_cache()
727 h.flash(_('Updated Labs settings'), category='success')
728 raise HTTPFound(h.route_path('admin_settings_labs'))
729
730 data = render('rhodecode:templates/admin/settings/settings.mako',
731 self._get_template_context(c), self.request)
732 html = formencode.htmlfill.render(
733 data,
734 defaults=self._form_defaults(),
735 encoding="UTF-8",
736 force_defaults=False
737 )
738 return Response(html)
739
740
741 # :param key: name of the setting including the 'rhodecode_' prefix
742 # :param type: the RhodeCodeSetting type to use.
743 # :param group: the i18ned group in which we should dispaly this setting
744 # :param label: the i18ned label we should display for this setting
745 # :param help: the i18ned help we should dispaly for this setting
746 LabSetting = collections.namedtuple(
747 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
748
749
750 # This list has to be kept in sync with the form
751 # rhodecode.model.forms.LabsSettingsForm.
752 _LAB_SETTINGS = [
753
754 ]
@@ -20,7 +20,6
20 20
21 21
22 22 from rhodecode.apps._base import ADMIN_PREFIX
23 from rhodecode.lib.utils2 import str2bool
24 23
25 24
26 25 def admin_routes(config):
@@ -82,6 +81,88 def admin_routes(config):
82 81 name='admin_defaults_repositories_update',
83 82 pattern='/defaults/repositories/update')
84 83
84 # admin settings
85
86 config.add_route(
87 name='admin_settings',
88 pattern='/settings')
89 config.add_route(
90 name='admin_settings_update',
91 pattern='/settings/update')
92
93 config.add_route(
94 name='admin_settings_global',
95 pattern='/settings/global')
96 config.add_route(
97 name='admin_settings_global_update',
98 pattern='/settings/global/update')
99
100 config.add_route(
101 name='admin_settings_vcs',
102 pattern='/settings/vcs')
103 config.add_route(
104 name='admin_settings_vcs_update',
105 pattern='/settings/vcs/update')
106 config.add_route(
107 name='admin_settings_vcs_svn_pattern_delete',
108 pattern='/settings/vcs/svn_pattern_delete')
109
110 config.add_route(
111 name='admin_settings_mapping',
112 pattern='/settings/mapping')
113 config.add_route(
114 name='admin_settings_mapping_update',
115 pattern='/settings/mapping/update')
116
117 config.add_route(
118 name='admin_settings_visual',
119 pattern='/settings/visual')
120 config.add_route(
121 name='admin_settings_visual_update',
122 pattern='/settings/visual/update')
123
124
125 config.add_route(
126 name='admin_settings_issuetracker',
127 pattern='/settings/issue-tracker')
128 config.add_route(
129 name='admin_settings_issuetracker_update',
130 pattern='/settings/issue-tracker/update')
131 config.add_route(
132 name='admin_settings_issuetracker_test',
133 pattern='/settings/issue-tracker/test')
134 config.add_route(
135 name='admin_settings_issuetracker_delete',
136 pattern='/settings/issue-tracker/delete')
137
138 config.add_route(
139 name='admin_settings_email',
140 pattern='/settings/email')
141 config.add_route(
142 name='admin_settings_email_update',
143 pattern='/settings/email/update')
144
145 config.add_route(
146 name='admin_settings_hooks',
147 pattern='/settings/hooks')
148 config.add_route(
149 name='admin_settings_hooks_update',
150 pattern='/settings/hooks/update')
151 config.add_route(
152 name='admin_settings_hooks_delete',
153 pattern='/settings/hooks/delete')
154
155 config.add_route(
156 name='admin_settings_search',
157 pattern='/settings/search')
158
159 config.add_route(
160 name='admin_settings_labs',
161 pattern='/settings/labs')
162 config.add_route(
163 name='admin_settings_labs_update',
164 pattern='/settings/labs/update')
165
85 166 # global permissions
86 167
87 168 config.add_route(
@@ -236,7 +317,7 def admin_routes(config):
236 317 config.add_route(
237 318 name='edit_user_ips_delete',
238 319 pattern='/users/{user_id:\d+}/edit/ips/delete',
239 user_route_with_default=True) # enabled for default user too
320 user_route_with_default=True) # enabled for default user too
240 321
241 322 # user perms
242 323 config.add_route(
@@ -46,65 +46,53 class NavEntry(object):
46 46 be removed as soon as we are fully migrated to pyramid.
47 47 """
48 48
49 def __init__(self, key, name, view_name, pyramid=False):
49 def __init__(self, key, name, view_name):
50 50 self.key = key
51 51 self.name = name
52 52 self.view_name = view_name
53 self.pyramid = pyramid
54 53
55 54 def generate_url(self, request):
56 if self.pyramid:
57 if hasattr(request, 'route_path'):
58 return request.route_path(self.view_name)
59 else:
60 # TODO: johbo: Remove this after migrating to pyramid.
61 # We need the pyramid request here to generate URLs to pyramid
62 # views from within pylons views.
63 from pyramid.threadlocal import get_current_request
64 pyramid_request = get_current_request()
65 return pyramid_request.route_path(self.view_name)
66 else:
67 from pylons import url
68 return url(self.view_name)
55 return request.route_path(self.view_name)
69 56
70 57 def get_localized_name(self, request):
71 if hasattr(request, 'translate'):
72 return request.translate(self.name)
73 else:
74 # TODO(marcink): Remove this after migrating to pyramid
75 from pyramid.threadlocal import get_current_request
76 pyramid_request = get_current_request()
77 return pyramid_request.translate(self.name)
58 return request.translate(self.name)
78 59
79 60
80 61 @implementer(IAdminNavigationRegistry)
81 62 class NavigationRegistry(object):
82 63
83 64 _base_entries = [
84 NavEntry('global', _('Global'), 'admin_settings_global'),
85 NavEntry('vcs', _('VCS'), 'admin_settings_vcs'),
86 NavEntry('visual', _('Visual'), 'admin_settings_visual'),
87 NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'),
65 NavEntry('global', _('Global'),
66 'admin_settings_global'),
67 NavEntry('vcs', _('VCS'),
68 'admin_settings_vcs'),
69 NavEntry('visual', _('Visual'),
70 'admin_settings_visual'),
71 NavEntry('mapping', _('Remap and Rescan'),
72 'admin_settings_mapping'),
88 73 NavEntry('issuetracker', _('Issue Tracker'),
89 74 'admin_settings_issuetracker'),
90 NavEntry('email', _('Email'), 'admin_settings_email'),
91 NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
92 NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
93
75 NavEntry('email', _('Email'),
76 'admin_settings_email'),
77 NavEntry('hooks', _('Hooks'),
78 'admin_settings_hooks'),
79 NavEntry('search', _('Full Text Search'),
80 'admin_settings_search'),
94 81 NavEntry('integrations', _('Integrations'),
95 'global_integrations_home', pyramid=True),
82 'global_integrations_home'),
96 83 NavEntry('system', _('System Info'),
97 'admin_settings_system', pyramid=True),
84 'admin_settings_system'),
98 85 NavEntry('process_management', _('Processes'),
99 'admin_settings_process_management', pyramid=True),
86 'admin_settings_process_management'),
100 87 NavEntry('sessions', _('User Sessions'),
101 'admin_settings_sessions', pyramid=True),
88 'admin_settings_sessions'),
102 89 NavEntry('open_source', _('Open Source Licenses'),
103 'admin_settings_open_source', pyramid=True),
90 'admin_settings_open_source'),
104 91
105 92 ]
106 93
107 _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs')
94 _labs_entry = NavEntry('labs', _('Labs'),
95 'admin_settings_labs')
108 96
109 97 def __init__(self, labs_active=False):
110 98 self._registered_entries = collections.OrderedDict()
@@ -27,7 +27,7 from rhodecode.lib.utils2 import md5
27 27 from rhodecode.model.db import RhodeCodeUi
28 28 from rhodecode.model.meta import Session
29 29 from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel
30 from rhodecode.tests import url, assert_session_flash
30 from rhodecode.tests import assert_session_flash
31 31 from rhodecode.tests.utils import AssertResponse
32 32
33 33
@@ -35,6 +35,78 UPDATE_DATA_QUALNAME = (
35 35 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
36 36
37 37
38 def route_path(name, params=None, **kwargs):
39 import urllib
40 from rhodecode.apps._base import ADMIN_PREFIX
41
42 base_url = {
43
44 'admin_settings':
45 ADMIN_PREFIX +'/settings',
46 'admin_settings_update':
47 ADMIN_PREFIX + '/settings/update',
48 'admin_settings_global':
49 ADMIN_PREFIX + '/settings/global',
50 'admin_settings_global_update':
51 ADMIN_PREFIX + '/settings/global/update',
52 'admin_settings_vcs':
53 ADMIN_PREFIX + '/settings/vcs',
54 'admin_settings_vcs_update':
55 ADMIN_PREFIX + '/settings/vcs/update',
56 'admin_settings_vcs_svn_pattern_delete':
57 ADMIN_PREFIX + '/settings/vcs/svn_pattern_delete',
58 'admin_settings_mapping':
59 ADMIN_PREFIX + '/settings/mapping',
60 'admin_settings_mapping_update':
61 ADMIN_PREFIX + '/settings/mapping/update',
62 'admin_settings_visual':
63 ADMIN_PREFIX + '/settings/visual',
64 'admin_settings_visual_update':
65 ADMIN_PREFIX + '/settings/visual/update',
66 'admin_settings_issuetracker':
67 ADMIN_PREFIX + '/settings/issue-tracker',
68 'admin_settings_issuetracker_update':
69 ADMIN_PREFIX + '/settings/issue-tracker/update',
70 'admin_settings_issuetracker_test':
71 ADMIN_PREFIX + '/settings/issue-tracker/test',
72 'admin_settings_issuetracker_delete':
73 ADMIN_PREFIX + '/settings/issue-tracker/delete',
74 'admin_settings_email':
75 ADMIN_PREFIX + '/settings/email',
76 'admin_settings_email_update':
77 ADMIN_PREFIX + '/settings/email/update',
78 'admin_settings_hooks':
79 ADMIN_PREFIX + '/settings/hooks',
80 'admin_settings_hooks_update':
81 ADMIN_PREFIX + '/settings/hooks/update',
82 'admin_settings_hooks_delete':
83 ADMIN_PREFIX + '/settings/hooks/delete',
84 'admin_settings_search':
85 ADMIN_PREFIX + '/settings/search',
86 'admin_settings_labs':
87 ADMIN_PREFIX + '/settings/labs',
88 'admin_settings_labs_update':
89 ADMIN_PREFIX + '/settings/labs/update',
90
91 'admin_settings_sessions':
92 ADMIN_PREFIX + '/settings/sessions',
93 'admin_settings_sessions_cleanup':
94 ADMIN_PREFIX + '/settings/sessions/cleanup',
95 'admin_settings_system':
96 ADMIN_PREFIX + '/settings/system',
97 'admin_settings_system_update':
98 ADMIN_PREFIX + '/settings/system/updates',
99 'admin_settings_open_source':
100 ADMIN_PREFIX + '/settings/open_source',
101
102
103 }[name].format(**kwargs)
104
105 if params:
106 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
107 return base_url
108
109
38 110 @pytest.mark.usefixtures('autologin_user', 'app')
39 111 class TestAdminSettingsController(object):
40 112
@@ -47,12 +119,12 class TestAdminSettingsController(object
47