##// END OF EJS Templates
admin: ported settings controller to pyramid....
marcink -
r2333:c9f5d931 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (754 lines changed) Show them Hide them
@@ -0,0 +1,754 b''
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 b''
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 b' 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(
@@ -46,65 +46,53 b' 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 55 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)
69 56
70 57 def get_localized_name(self, request):
71 if hasattr(request, 'translate'):
72 58 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)
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 b' 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 b' 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 b' class TestAdminSettingsController(object'
47 119 'admin_settings_hooks',
48 120 'admin_settings_search',
49 121 ])
50 def test_simple_get(self, urlname, app):
51 app.get(url(urlname))
122 def test_simple_get(self, urlname):
123 self.app.get(route_path(urlname))
52 124
53 125 def test_create_custom_hook(self, csrf_token):
54 126 response = self.app.post(
55 url('admin_settings_hooks'),
127 route_path('admin_settings_hooks_update'),
56 128 params={
57 129 'new_hook_ui_key': 'test_hooks_1',
58 130 'new_hook_ui_value': 'cd /tmp',
@@ -64,7 +136,7 b' class TestAdminSettingsController(object'
64 136
65 137 def test_create_custom_hook_delete(self, csrf_token):
66 138 response = self.app.post(
67 url('admin_settings_hooks'),
139 route_path('admin_settings_hooks_update'),
68 140 params={
69 141 'new_hook_ui_key': 'test_hooks_2',
70 142 'new_hook_ui_value': 'cd /tmp2',
@@ -78,9 +150,9 b' class TestAdminSettingsController(object'
78 150
79 151 # delete
80 152 self.app.post(
81 url('admin_settings_hooks'),
153 route_path('admin_settings_hooks_delete'),
82 154 params={'hook_id': hook_id, 'csrf_token': csrf_token})
83 response = self.app.get(url('admin_settings_hooks'))
155 response = self.app.get(route_path('admin_settings_hooks'))
84 156 response.mustcontain(no=['test_hooks_2'])
85 157 response.mustcontain(no=['cd /tmp2'])
86 158
@@ -135,7 +207,6 b' class TestAdminSettingsGlobal(object):'
135 207
136 208 def test_title_change(self, csrf_token):
137 209 old_title = 'RhodeCode'
138 new_title = old_title + '_changed'
139 210
140 211 for new_title in ['Changed', 'Żółwik', old_title]:
141 212 response = self.post_and_verify_settings({
@@ -161,7 +232,8 b' class TestAdminSettingsGlobal(object):'
161 232 'rhodecode_personal_repo_group_pattern': '${username}',
162 233 }
163 234 params.update(settings)
164 response = self.app.post(url('admin_settings_global'), params=params)
235 response = self.app.post(
236 route_path('admin_settings_global_update'), params=params)
165 237
166 238 assert_session_flash(response, 'Updated application settings')
167 239 app_settings = SettingsModel().get_all_settings()
@@ -175,8 +247,8 b' class TestAdminSettingsGlobal(object):'
175 247 @pytest.mark.usefixtures('autologin_user', 'app')
176 248 class TestAdminSettingsVcs(object):
177 249
178 def test_contains_svn_default_patterns(self, app):
179 response = app.get(url('admin_settings_vcs'))
250 def test_contains_svn_default_patterns(self):
251 response = self.app.get(route_path('admin_settings_vcs'))
180 252 expected_patterns = [
181 253 '/trunk',
182 254 '/branches/*',
@@ -186,7 +258,7 b' class TestAdminSettingsVcs(object):'
186 258 response.mustcontain(pattern)
187 259
188 260 def test_add_new_svn_branch_and_tag_pattern(
189 self, app, backend_svn, form_defaults, disable_sql_cache,
261 self, backend_svn, form_defaults, disable_sql_cache,
190 262 csrf_token):
191 263 form_defaults.update({
192 264 'new_svn_branch': '/exp/branches/*',
@@ -194,8 +266,9 b' class TestAdminSettingsVcs(object):'
194 266 'csrf_token': csrf_token,
195 267 })
196 268
197 response = app.post(
198 url('admin_settings_vcs'), params=form_defaults, status=302)
269 response = self.app.post(
270 route_path('admin_settings_vcs_update'),
271 params=form_defaults, status=302)
199 272 response = response.follow()
200 273
201 274 # Expect to find the new values on the page
@@ -208,12 +281,12 b' class TestAdminSettingsVcs(object):'
208 281 assert 'important_tags/v0.5' in repo.tags
209 282
210 283 def test_add_same_svn_value_twice_shows_an_error_message(
211 self, app, form_defaults, csrf_token, settings_util):
284 self, form_defaults, csrf_token, settings_util):
212 285 settings_util.create_rhodecode_ui('vcs_svn_branch', '/test')
213 286 settings_util.create_rhodecode_ui('vcs_svn_tag', '/test')
214 287
215 response = app.post(
216 url('admin_settings_vcs'),
288 response = self.app.post(
289 route_path('admin_settings_vcs_update'),
217 290 params={
218 291 'paths_root_path': form_defaults['paths_root_path'],
219 292 'new_svn_branch': '/test',
@@ -230,14 +303,13 b' class TestAdminSettingsVcs(object):'
230 303 'vcs_svn_tag',
231 304 ])
232 305 def test_delete_svn_patterns(
233 self, section, app, csrf_token, settings_util):
306 self, section, csrf_token, settings_util):
234 307 setting = settings_util.create_rhodecode_ui(
235 308 section, '/test_delete', cleanup=False)
236 309
237 app.post(
238 url('admin_settings_vcs'),
310 self.app.post(
311 route_path('admin_settings_vcs_svn_pattern_delete'),
239 312 params={
240 '_method': 'delete',
241 313 'delete_svn_pattern': setting.ui_id,
242 314 'csrf_token': csrf_token},
243 315 headers={'X-REQUESTED-WITH': 'XMLHttpRequest'})
@@ -246,25 +318,24 b' class TestAdminSettingsVcs(object):'
246 318 'vcs_svn_branch',
247 319 'vcs_svn_tag',
248 320 ])
249 def test_delete_svn_patterns_raises_400_when_no_xhr(
250 self, section, app, csrf_token, settings_util):
321 def test_delete_svn_patterns_raises_404_when_no_xhr(
322 self, section, csrf_token, settings_util):
251 323 setting = settings_util.create_rhodecode_ui(section, '/test_delete')
252 324
253 app.post(
254 url('admin_settings_vcs'),
325 self.app.post(
326 route_path('admin_settings_vcs_svn_pattern_delete'),
255 327 params={
256 '_method': 'delete',
257 328 'delete_svn_pattern': setting.ui_id,
258 329 'csrf_token': csrf_token},
259 status=400)
330 status=404)
260 331
261 def test_extensions_hgsubversion(self, app, form_defaults, csrf_token):
332 def test_extensions_hgsubversion(self, form_defaults, csrf_token):
262 333 form_defaults.update({
263 334 'csrf_token': csrf_token,
264 335 'extensions_hgsubversion': 'True',
265 336 })
266 response = app.post(
267 url('admin_settings_vcs'),
337 response = self.app.post(
338 route_path('admin_settings_vcs_update'),
268 339 params=form_defaults,
269 340 status=302)
270 341
@@ -275,13 +346,13 b' class TestAdminSettingsVcs(object):'
275 346 'value="True" checked="checked" />')
276 347 response.mustcontain(extensions_input)
277 348
278 def test_extensions_hgevolve(self, app, form_defaults, csrf_token):
349 def test_extensions_hgevolve(self, form_defaults, csrf_token):
279 350 form_defaults.update({
280 351 'csrf_token': csrf_token,
281 352 'extensions_evolve': 'True',
282 353 })
283 response = app.post(
284 url('admin_settings_vcs'),
354 response = self.app.post(
355 route_path('admin_settings_vcs_update'),
285 356 params=form_defaults,
286 357 status=302)
287 358
@@ -292,20 +363,19 b' class TestAdminSettingsVcs(object):'
292 363 'value="True" checked="checked" />')
293 364 response.mustcontain(extensions_input)
294 365
295 def test_has_a_section_for_pull_request_settings(self, app):
296 response = app.get(url('admin_settings_vcs'))
366 def test_has_a_section_for_pull_request_settings(self):
367 response = self.app.get(route_path('admin_settings_vcs'))
297 368 response.mustcontain('Pull Request Settings')
298 369
299 def test_has_an_input_for_invalidation_of_inline_comments(
300 self, app):
301 response = app.get(url('admin_settings_vcs'))
370 def test_has_an_input_for_invalidation_of_inline_comments(self):
371 response = self.app.get(route_path('admin_settings_vcs'))
302 372 assert_response = AssertResponse(response)
303 373 assert_response.one_element_exists(
304 374 '[name=rhodecode_use_outdated_comments]')
305 375
306 376 @pytest.mark.parametrize('new_value', [True, False])
307 377 def test_allows_to_change_invalidation_of_inline_comments(
308 self, app, form_defaults, csrf_token, new_value):
378 self, form_defaults, csrf_token, new_value):
309 379 setting_key = 'use_outdated_comments'
310 380 setting = SettingsModel().create_or_update_setting(
311 381 setting_key, not new_value, 'bool')
@@ -316,8 +386,8 b' class TestAdminSettingsVcs(object):'
316 386 'csrf_token': csrf_token,
317 387 'rhodecode_use_outdated_comments': str(new_value),
318 388 })
319 response = app.post(
320 url('admin_settings_vcs'),
389 response = self.app.post(
390 route_path('admin_settings_vcs_update'),
321 391 params=form_defaults,
322 392 status=302)
323 393 response = response.follow()
@@ -326,7 +396,7 b' class TestAdminSettingsVcs(object):'
326 396
327 397 @pytest.mark.parametrize('new_value', [True, False])
328 398 def test_allows_to_change_hg_rebase_merge_strategy(
329 self, app, form_defaults, csrf_token, new_value):
399 self, form_defaults, csrf_token, new_value):
330 400 setting_key = 'hg_use_rebase_for_merging'
331 401
332 402 form_defaults.update({
@@ -336,8 +406,8 b' class TestAdminSettingsVcs(object):'
336 406
337 407 with mock.patch.dict(
338 408 rhodecode.CONFIG, {'labs_settings_active': 'true'}):
339 app.post(
340 url('admin_settings_vcs'),
409 self.app.post(
410 route_path('admin_settings_vcs_update'),
341 411 params=form_defaults,
342 412 status=302)
343 413
@@ -353,9 +423,8 b' class TestAdminSettingsVcs(object):'
353 423
354 424 @pytest.fixture
355 425 def form_defaults(self):
356 from rhodecode.controllers.admin.settings import SettingsController
357 controller = SettingsController()
358 return controller._form_defaults()
426 from rhodecode.apps.admin.views.settings import AdminSettingsView
427 return AdminSettingsView._form_defaults()
359 428
360 429 # TODO: johbo: What we really want is to checkpoint before a test run and
361 430 # reset the session afterwards.
@@ -374,14 +443,16 b' class TestAdminSettingsVcs(object):'
374 443 @pytest.mark.usefixtures('autologin_user', 'app')
375 444 class TestLabsSettings(object):
376 445 def test_get_settings_page_disabled(self):
377 with mock.patch.dict(rhodecode.CONFIG,
378 {'labs_settings_active': 'false'}):
379 response = self.app.get(url('admin_settings_labs'), status=302)
446 with mock.patch.dict(
447 rhodecode.CONFIG, {'labs_settings_active': 'false'}):
380 448
381 assert response.location.endswith(url('admin_settings'))
449 response = self.app.get(
450 route_path('admin_settings_labs'), status=302)
451
452 assert response.location.endswith(route_path('admin_settings'))
382 453
383 454 def test_get_settings_page_enabled(self):
384 from rhodecode.controllers.admin import settings
455 from rhodecode.apps.admin.views import settings
385 456 lab_settings = [
386 457 settings.LabSetting(
387 458 key='rhodecode_bool',
@@ -401,7 +472,7 b' class TestLabsSettings(object):'
401 472 with mock.patch.dict(rhodecode.CONFIG,
402 473 {'labs_settings_active': 'true'}):
403 474 with mock.patch.object(settings, '_LAB_SETTINGS', lab_settings):
404 response = self.app.get(url('admin_settings_labs'))
475 response = self.app.get(route_path('admin_settings_labs'))
405 476
406 477 assert '<label>bool group:</label>' in response
407 478 assert '<label for="rhodecode_bool">bool label</label>' in response
@@ -417,9 +488,6 b' class TestLabsSettings(object):'
417 488 @pytest.mark.usefixtures('app')
418 489 class TestOpenSourceLicenses(object):
419 490
420 def _get_url(self):
421 return ADMIN_PREFIX + '/settings/open_source'
422
423 491 def test_records_are_displayed(self, autologin_user):
424 492 sample_licenses = {
425 493 "python2.7-pytest-2.7.1": {
@@ -433,7 +501,8 b' class TestOpenSourceLicenses(object):'
433 501 'rhodecode.apps.admin.views.open_source_licenses.read_opensource_licenses',
434 502 return_value=sample_licenses)
435 503 with read_licenses_patch:
436 response = self.app.get(self._get_url(), status=200)
504 response = self.app.get(
505 route_path('admin_settings_open_source'), status=200)
437 506
438 507 assert_response = AssertResponse(response)
439 508 assert_response.element_contains(
@@ -444,29 +513,25 b' class TestOpenSourceLicenses(object):'
444 513 assert_response.element_contains('.panel-body', license)
445 514
446 515 def test_records_can_be_read(self, autologin_user):
447 response = self.app.get(self._get_url(), status=200)
516 response = self.app.get(
517 route_path('admin_settings_open_source'), status=200)
448 518 assert_response = AssertResponse(response)
449 519 assert_response.element_contains(
450 520 '.panel-heading', 'Licenses of Third Party Packages')
451 521
452 522 def test_forbidden_when_normal_user(self, autologin_regular_user):
453 self.app.get(self._get_url(), status=404)
523 self.app.get(
524 route_path('admin_settings_open_source'), status=404)
454 525
455 526
456 527 @pytest.mark.usefixtures('app')
457 528 class TestUserSessions(object):
458 529
459 def _get_url(self, name='admin_settings_sessions'):
460 return {
461 'admin_settings_sessions': ADMIN_PREFIX + '/settings/sessions',
462 'admin_settings_sessions_cleanup': ADMIN_PREFIX + '/settings/sessions/cleanup'
463 }[name]
464
465 530 def test_forbidden_when_normal_user(self, autologin_regular_user):
466 self.app.get(self._get_url(), status=404)
531 self.app.get(route_path('admin_settings_sessions'), status=404)
467 532
468 533 def test_show_sessions_page(self, autologin_user):
469 response = self.app.get(self._get_url(), status=200)
534 response = self.app.get(route_path('admin_settings_sessions'), status=200)
470 535 response.mustcontain('file')
471 536
472 537 def test_cleanup_old_sessions(self, autologin_user, csrf_token):
@@ -476,24 +541,19 b' class TestUserSessions(object):'
476 541 'expire_days': '60'
477 542 }
478 543 response = self.app.post(
479 self._get_url('admin_settings_sessions_cleanup'), params=post_data,
544 route_path('admin_settings_sessions_cleanup'), params=post_data,
480 545 status=302)
481 546 assert_session_flash(response, 'Cleaned up old sessions')
482 547
483 548
484 549 @pytest.mark.usefixtures('app')
485 550 class TestAdminSystemInfo(object):
486 def _get_url(self, name='admin_settings_system'):
487 return {
488 'admin_settings_system': ADMIN_PREFIX + '/settings/system',
489 'admin_settings_system_update': ADMIN_PREFIX + '/settings/system/updates',
490 }[name]
491 551
492 552 def test_forbidden_when_normal_user(self, autologin_regular_user):
493 self.app.get(self._get_url(), status=404)
553 self.app.get(route_path('admin_settings_system'), status=404)
494 554
495 555 def test_system_info_page(self, autologin_user):
496 response = self.app.get(self._get_url())
556 response = self.app.get(route_path('admin_settings_system'))
497 557 response.mustcontain('RhodeCode Community Edition, version {}'.format(
498 558 rhodecode.__version__))
499 559
@@ -511,7 +571,7 b' class TestAdminSystemInfo(object):'
511 571 ]
512 572 }
513 573 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
514 response = self.app.get(self._get_url('admin_settings_system_update'))
574 response = self.app.get(route_path('admin_settings_system_update'))
515 575 response.mustcontain('A <b>new version</b> is available')
516 576
517 577 def test_system_update_nothing_new(self, autologin_user):
@@ -524,13 +584,13 b' class TestAdminSystemInfo(object):'
524 584 ]
525 585 }
526 586 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
527 response = self.app.get(self._get_url('admin_settings_system_update'))
587 response = self.app.get(route_path('admin_settings_system_update'))
528 588 response.mustcontain(
529 589 'You already have the <b>latest</b> stable version.')
530 590
531 591 def test_system_update_bad_response(self, autologin_user):
532 592 with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
533 response = self.app.get(self._get_url('admin_settings_system_update'))
593 response = self.app.get(route_path('admin_settings_system_update'))
534 594 response.mustcontain(
535 595 'Bad data sent from update server')
536 596
@@ -542,12 +602,12 b' class TestAdminSettingsIssueTracker(obje'
542 602 PATTERN_KEY = RC_PREFIX + SHORT_PATTERN_KEY
543 603
544 604 def test_issuetracker_index(self, autologin_user):
545 response = self.app.get(url('admin_settings_issuetracker'))
605 response = self.app.get(route_path('admin_settings_issuetracker'))
546 606 assert response.status_code == 200
547 607
548 608 def test_add_empty_issuetracker_pattern(
549 609 self, request, autologin_user, csrf_token):
550 post_url = url('admin_settings_issuetracker_save')
610 post_url = route_path('admin_settings_issuetracker_update')
551 611 post_data = {
552 612 'csrf_token': csrf_token
553 613 }
@@ -557,7 +617,7 b' class TestAdminSettingsIssueTracker(obje'
557 617 self, request, autologin_user, csrf_token):
558 618 pattern = 'issuetracker_pat'
559 619 another_pattern = pattern+'1'
560 post_url = url('admin_settings_issuetracker_save')
620 post_url = route_path('admin_settings_issuetracker_update')
561 621 post_data = {
562 622 'new_pattern_pattern_0': pattern,
563 623 'new_pattern_url_0': 'url',
@@ -600,7 +660,7 b' class TestAdminSettingsIssueTracker(obje'
600 660 SettingsModel().create_or_update_setting(
601 661 self.SHORT_PATTERN_KEY+old_uid, old_pattern, 'unicode')
602 662
603 post_url = url('admin_settings_issuetracker_save')
663 post_url = route_path('admin_settings_issuetracker_update')
604 664 post_data = {
605 665 'new_pattern_pattern_0': pattern,
606 666 'new_pattern_url_0': 'url',
@@ -634,7 +694,7 b' class TestAdminSettingsIssueTracker(obje'
634 694 settings_util.create_rhodecode_setting(
635 695 desc_key, 'old description', 'unicode', cleanup=False)
636 696
637 post_url = url('admin_settings_issuetracker_save')
697 post_url = route_path('admin_settings_issuetracker_update')
638 698 post_data = {
639 699 'new_pattern_pattern_0': pattern,
640 700 'new_pattern_url_0': 'url',
@@ -659,7 +719,7 b' class TestAdminSettingsIssueTracker(obje'
659 719 settings_util.create_rhodecode_setting(
660 720 self.SHORT_PATTERN_KEY+uid, pattern, 'unicode', cleanup=False)
661 721
662 post_url = url('admin_issuetracker_delete')
722 post_url = route_path('admin_settings_issuetracker_delete')
663 723 post_data = {
664 724 '_method': 'delete',
665 725 'uid': uid,
@@ -172,81 +172,6 b' def make_map(config):'
172 172 # CUSTOM ROUTES HERE
173 173 #==========================================================================
174 174
175 # ADMIN SETTINGS ROUTES
176 with rmap.submapper(path_prefix=ADMIN_PREFIX,
177 controller='admin/settings') as m:
178
179 # default
180 m.connect('admin_settings', '/settings',
181 action='settings_global_update',
182 conditions={'method': ['POST']})
183 m.connect('admin_settings', '/settings',
184 action='settings_global', conditions={'method': ['GET']})
185
186 m.connect('admin_settings_vcs', '/settings/vcs',
187 action='settings_vcs_update',
188 conditions={'method': ['POST']})
189 m.connect('admin_settings_vcs', '/settings/vcs',
190 action='settings_vcs',
191 conditions={'method': ['GET']})
192 m.connect('admin_settings_vcs', '/settings/vcs',
193 action='delete_svn_pattern',
194 conditions={'method': ['DELETE']})
195
196 m.connect('admin_settings_mapping', '/settings/mapping',
197 action='settings_mapping_update',
198 conditions={'method': ['POST']})
199 m.connect('admin_settings_mapping', '/settings/mapping',
200 action='settings_mapping', conditions={'method': ['GET']})
201
202 m.connect('admin_settings_global', '/settings/global',
203 action='settings_global_update',
204 conditions={'method': ['POST']})
205 m.connect('admin_settings_global', '/settings/global',
206 action='settings_global', conditions={'method': ['GET']})
207
208 m.connect('admin_settings_visual', '/settings/visual',
209 action='settings_visual_update',
210 conditions={'method': ['POST']})
211 m.connect('admin_settings_visual', '/settings/visual',
212 action='settings_visual', conditions={'method': ['GET']})
213
214 m.connect('admin_settings_issuetracker',
215 '/settings/issue-tracker', action='settings_issuetracker',
216 conditions={'method': ['GET']})
217 m.connect('admin_settings_issuetracker_save',
218 '/settings/issue-tracker/save',
219 action='settings_issuetracker_save',
220 conditions={'method': ['POST']})
221 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
222 action='settings_issuetracker_test',
223 conditions={'method': ['POST']})
224 m.connect('admin_issuetracker_delete',
225 '/settings/issue-tracker/delete',
226 action='settings_issuetracker_delete',
227 conditions={'method': ['DELETE']})
228
229 m.connect('admin_settings_email', '/settings/email',
230 action='settings_email_update',
231 conditions={'method': ['POST']})
232 m.connect('admin_settings_email', '/settings/email',
233 action='settings_email', conditions={'method': ['GET']})
234
235 m.connect('admin_settings_hooks', '/settings/hooks',
236 action='settings_hooks_update',
237 conditions={'method': ['POST', 'DELETE']})
238 m.connect('admin_settings_hooks', '/settings/hooks',
239 action='settings_hooks', conditions={'method': ['GET']})
240
241 m.connect('admin_settings_search', '/settings/search',
242 action='settings_search', conditions={'method': ['GET']})
243
244 m.connect('admin_settings_labs', '/settings/labs',
245 action='settings_labs_update',
246 conditions={'method': ['POST']})
247 m.connect('admin_settings_labs', '/settings/labs',
248 action='settings_labs', conditions={'method': ['GET']})
249
250 175 # ADMIN MY ACCOUNT
251 176 with rmap.submapper(path_prefix=ADMIN_PREFIX,
252 177 controller='admin/my_account') as m:
@@ -51,6 +51,29 b' function registerRCRoutes() {'
51 51 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
52 52 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
53 53 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
54 pyroutes.register('admin_settings', '/_admin/settings', []);
55 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
56 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
57 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
58 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
59 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
60 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
61 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
62 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
63 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
64 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
65 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
66 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
67 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
68 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
69 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
70 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
71 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
72 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
73 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
74 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
75 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
76 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
54 77 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
55 78 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
56 79 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
@@ -27,7 +27,7 b''
27 27 %else:
28 28 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
29 29 &raquo;
30 ${h.link_to(_('Settings'),h.url('admin_settings'))}
30 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
31 31 &raquo;
32 32 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
33 33 &raquo;
@@ -13,7 +13,7 b''
13 13 %else:
14 14 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
15 15 &raquo;
16 ${h.link_to(_('Settings'),h.url('admin_settings'))}
16 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
17 17 %endif
18 18 %if c.current_IntegrationType:
19 19 &raquo;
@@ -18,7 +18,7 b''
18 18 %else:
19 19 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
20 20 &raquo;
21 ${h.link_to(_('Settings'),h.url('admin_settings'))}
21 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
22 22 &raquo;
23 23 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
24 24 %endif
@@ -33,7 +33,7 b''
33 33 add authentication information to the URL: https://username:password@server.company.com/repo-name.
34 34 - The Git LFS/Mercurial Largefiles objects will not be imported.
35 35 - For very large repositories, it's recommended to manually copy them into the
36 RhodeCode <a href="${h.url('admin_settings_vcs', anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.url('admin_settings_mapping')}">Remap and Rescan</a>.
36 RhodeCode <a href="${h.route_path('admin_settings_vcs', _anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.route_path('admin_settings_mapping')}">Remap and Rescan</a>.
37 37 </pre>
38 38 </span>
39 39 </div>
@@ -34,7 +34,7 b''
34 34 <h3 class="panel-title">${_('Test Email')}</h3>
35 35 </div>
36 36 <div class="panel-body">
37 ${h.secure_form(h.url('admin_settings_email'), request=request)}
37 ${h.secure_form(h.route_path('admin_settings_email_update'), request=request)}
38 38
39 39 <div class="field input">
40 40 ${h.text('test_email', size=60, placeholder=_('enter valid email'))}
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_global'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_global_update'), request=request)}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading" id="branding-options">
@@ -28,7 +28,7 b''
28 28 </div>
29 29 <div class="panel-body">
30 30 % if c.visual.allow_custom_hooks_settings:
31 ${h.secure_form(h.url('admin_settings_hooks'), request=request)}
31 ${h.secure_form(h.route_path('admin_settings_hooks_update'), request=request)}
32 32 <div class="form">
33 33 <div class="fields">
34 34
@@ -74,13 +74,12 b''
74 74
75 75 <script type="text/javascript">
76 76 function ajaxActionHook(hook_id,field_id) {
77 var sUrl = "${h.url('admin_settings_hooks')}";
77 var sUrl = "${h.route_path('admin_settings_hooks_delete')}";
78 78 var callback = function (o) {
79 79 var elem = $("#"+field_id);
80 80 elem.remove();
81 81 };
82 82 var postData = {
83 '_method': 'delete',
84 83 'hook_id': hook_id,
85 84 'csrf_token': CSRF_TOKEN
86 85 };
@@ -89,5 +88,5 b' function ajaxActionHook(hook_id,field_id'
89 88 .fail(function (data, textStatus, errorThrown) {
90 89 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
91 90 });
92 };
91 }
93 92 </script>
@@ -5,11 +5,11 b''
5 5 <h3 class="panel-title">${_('Issue Tracker / Wiki Patterns')}</h3>
6 6 </div>
7 7 <div class="panel-body">
8 ${h.secure_form(h.url('admin_settings_issuetracker_save'), request=request)}
8 ${h.secure_form(h.route_path('admin_settings_issuetracker_update'), request=request)}
9 9 ${its.issue_tracker_settings_table(
10 10 patterns=c.issuetracker_entries.items(),
11 form_url=h.url('admin_settings_issuetracker'),
12 delete_url=h.url('admin_issuetracker_delete')
11 form_url=h.route_path('admin_settings_issuetracker'),
12 delete_url=h.route_path('admin_settings_issuetracker_delete')
13 13 )}
14 14 <div class="buttons">
15 15 <button type="submit" class="btn btn-primary" id="save">${_('Save')}</button>
@@ -25,7 +25,7 b''
25 25 </div>
26 26 <div class="panel-body">
27 27 ${its.issue_tracker_new_row()}
28 ${its.issue_tracker_settings_test(test_url=h.url('admin_issuetracker_test'))}
28 ${its.issue_tracker_settings_test(test_url=h.route_path('admin_settings_issuetracker_test'))}
29 29 </div>
30 30 </div>
31 31
@@ -3,7 +3,7 b''
3 3 <h3 class="panel-title">${_('Labs Settings')}</h3>
4 4 </div>
5 5 <div class="panel-body">
6 ${h.secure_form(h.url('admin_settings_labs'), request=request)}
6 ${h.secure_form(h.route_path('admin_settings_labs_update'), request=request)}
7 7 <div class="form">
8 8 <div class="fields">
9 9 % if not c.lab_settings:
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_mapping'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_mapping_update'), request=request)}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading">
@@ -1,6 +1,6 b''
1 1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
2 2
3 ${h.secure_form(h.url('admin_settings_vcs'), request=request)}
3 ${h.secure_form(h.route_path('admin_settings_vcs_update'), request=request)}
4 4 <div>
5 5 ${vcss.vcs_settings_fields(
6 6 suffix='',
@@ -19,13 +19,12 b''
19 19 <script type="text/javascript">
20 20
21 21 function ajaxDeletePattern(pattern_id, field_id) {
22 var sUrl = "${h.url('admin_settings_vcs')}";
22 var sUrl = "${h.route_path('admin_settings_vcs_svn_pattern_delete')}";
23 23 var callback = function (o) {
24 24 var elem = $("#"+field_id);
25 25 elem.remove();
26 26 };
27 27 var postData = {
28 '_method': 'delete',
29 28 'delete_svn_pattern': pattern_id,
30 29 'csrf_token': CSRF_TOKEN
31 30 };
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_visual'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_visual_update'), request=request)}
2 2
3 3 <div class="panel panel-default">
4 4 <div class="panel-heading" id="general">
@@ -81,7 +81,7 b''
81 81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
82 82 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
83 83 <li><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
84 <li class="last"><a href="${h.url('admin_settings')}">${_('Settings')}</a></li>
84 <li class="last"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
85 85 </ul>
86 86 </%def>
87 87
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (631 lines changed) Show them Hide them
General Comments 0
You need to be logged in to leave comments. Login now