# HG changeset patch # User Marcin Kuzminski # Date 2017-11-09 14:40:31 # Node ID c9f5d931cdb99d9690ed53f4cc18ce2303a68ef5 # Parent 332b2dd35a4adfde30c0379697b6aaf33f675fe5 admin: ported settings controller to pyramid. - NavList dropped pyramid flag as it's pure pyramid now diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py --- a/rhodecode/apps/admin/__init__.py +++ b/rhodecode/apps/admin/__init__.py @@ -20,7 +20,6 @@ from rhodecode.apps._base import ADMIN_PREFIX -from rhodecode.lib.utils2 import str2bool def admin_routes(config): @@ -82,6 +81,88 @@ def admin_routes(config): name='admin_defaults_repositories_update', pattern='/defaults/repositories/update') + # admin settings + + config.add_route( + name='admin_settings', + pattern='/settings') + config.add_route( + name='admin_settings_update', + pattern='/settings/update') + + config.add_route( + name='admin_settings_global', + pattern='/settings/global') + config.add_route( + name='admin_settings_global_update', + pattern='/settings/global/update') + + config.add_route( + name='admin_settings_vcs', + pattern='/settings/vcs') + config.add_route( + name='admin_settings_vcs_update', + pattern='/settings/vcs/update') + config.add_route( + name='admin_settings_vcs_svn_pattern_delete', + pattern='/settings/vcs/svn_pattern_delete') + + config.add_route( + name='admin_settings_mapping', + pattern='/settings/mapping') + config.add_route( + name='admin_settings_mapping_update', + pattern='/settings/mapping/update') + + config.add_route( + name='admin_settings_visual', + pattern='/settings/visual') + config.add_route( + name='admin_settings_visual_update', + pattern='/settings/visual/update') + + + config.add_route( + name='admin_settings_issuetracker', + pattern='/settings/issue-tracker') + config.add_route( + name='admin_settings_issuetracker_update', + pattern='/settings/issue-tracker/update') + config.add_route( + name='admin_settings_issuetracker_test', + pattern='/settings/issue-tracker/test') + config.add_route( + name='admin_settings_issuetracker_delete', + pattern='/settings/issue-tracker/delete') + + config.add_route( + name='admin_settings_email', + pattern='/settings/email') + config.add_route( + name='admin_settings_email_update', + pattern='/settings/email/update') + + config.add_route( + name='admin_settings_hooks', + pattern='/settings/hooks') + config.add_route( + name='admin_settings_hooks_update', + pattern='/settings/hooks/update') + config.add_route( + name='admin_settings_hooks_delete', + pattern='/settings/hooks/delete') + + config.add_route( + name='admin_settings_search', + pattern='/settings/search') + + config.add_route( + name='admin_settings_labs', + pattern='/settings/labs') + config.add_route( + name='admin_settings_labs_update', + pattern='/settings/labs/update') + # global permissions config.add_route( @@ -236,7 +317,7 @@ def admin_routes(config): config.add_route( name='edit_user_ips_delete', pattern='/users/{user_id:\d+}/edit/ips/delete', - user_route_with_default=True) # enabled for default user too + user_route_with_default=True) # enabled for default user too # user perms config.add_route( diff --git a/rhodecode/apps/admin/navigation.py b/rhodecode/apps/admin/navigation.py --- a/rhodecode/apps/admin/navigation.py +++ b/rhodecode/apps/admin/navigation.py @@ -46,65 +46,53 @@ class NavEntry(object): be removed as soon as we are fully migrated to pyramid. """ - def __init__(self, key, name, view_name, pyramid=False): + def __init__(self, key, name, view_name): self.key = key self.name = name self.view_name = view_name - self.pyramid = pyramid def generate_url(self, request): - if self.pyramid: - if hasattr(request, 'route_path'): - return request.route_path(self.view_name) - else: - # TODO: johbo: Remove this after migrating to pyramid. - # We need the pyramid request here to generate URLs to pyramid - # views from within pylons views. - from pyramid.threadlocal import get_current_request - pyramid_request = get_current_request() - return pyramid_request.route_path(self.view_name) - else: - from pylons import url - return url(self.view_name) + return request.route_path(self.view_name) def get_localized_name(self, request): - if hasattr(request, 'translate'): - return request.translate(self.name) - else: - # TODO(marcink): Remove this after migrating to pyramid - from pyramid.threadlocal import get_current_request - pyramid_request = get_current_request() - return pyramid_request.translate(self.name) + return request.translate(self.name) @implementer(IAdminNavigationRegistry) class NavigationRegistry(object): _base_entries = [ - NavEntry('global', _('Global'), 'admin_settings_global'), - NavEntry('vcs', _('VCS'), 'admin_settings_vcs'), - NavEntry('visual', _('Visual'), 'admin_settings_visual'), - NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'), + NavEntry('global', _('Global'), + 'admin_settings_global'), + NavEntry('vcs', _('VCS'), + 'admin_settings_vcs'), + NavEntry('visual', _('Visual'), + 'admin_settings_visual'), + NavEntry('mapping', _('Remap and Rescan'), + 'admin_settings_mapping'), NavEntry('issuetracker', _('Issue Tracker'), 'admin_settings_issuetracker'), - NavEntry('email', _('Email'), 'admin_settings_email'), - NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'), - NavEntry('search', _('Full Text Search'), 'admin_settings_search'), - + NavEntry('email', _('Email'), + 'admin_settings_email'), + NavEntry('hooks', _('Hooks'), + 'admin_settings_hooks'), + NavEntry('search', _('Full Text Search'), + 'admin_settings_search'), NavEntry('integrations', _('Integrations'), - 'global_integrations_home', pyramid=True), + 'global_integrations_home'), NavEntry('system', _('System Info'), - 'admin_settings_system', pyramid=True), + 'admin_settings_system'), NavEntry('process_management', _('Processes'), - 'admin_settings_process_management', pyramid=True), + 'admin_settings_process_management'), NavEntry('sessions', _('User Sessions'), - 'admin_settings_sessions', pyramid=True), + 'admin_settings_sessions'), NavEntry('open_source', _('Open Source Licenses'), - 'admin_settings_open_source', pyramid=True), + 'admin_settings_open_source'), ] - _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs') + _labs_entry = NavEntry('labs', _('Labs'), + 'admin_settings_labs') def __init__(self, labs_active=False): self._registered_entries = collections.OrderedDict() diff --git a/rhodecode/tests/functional/test_admin_settings.py b/rhodecode/apps/admin/tests/test_admin_settings.py rename from rhodecode/tests/functional/test_admin_settings.py rename to rhodecode/apps/admin/tests/test_admin_settings.py --- a/rhodecode/tests/functional/test_admin_settings.py +++ b/rhodecode/apps/admin/tests/test_admin_settings.py @@ -27,7 +27,7 @@ from rhodecode.lib.utils2 import md5 from rhodecode.model.db import RhodeCodeUi from rhodecode.model.meta import Session from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel -from rhodecode.tests import url, assert_session_flash +from rhodecode.tests import assert_session_flash from rhodecode.tests.utils import AssertResponse @@ -35,6 +35,78 @@ UPDATE_DATA_QUALNAME = ( 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data') +def route_path(name, params=None, **kwargs): + import urllib + from rhodecode.apps._base import ADMIN_PREFIX + + base_url = { + + 'admin_settings': + ADMIN_PREFIX +'/settings', + 'admin_settings_update': + ADMIN_PREFIX + '/settings/update', + 'admin_settings_global': + ADMIN_PREFIX + '/settings/global', + 'admin_settings_global_update': + ADMIN_PREFIX + '/settings/global/update', + 'admin_settings_vcs': + ADMIN_PREFIX + '/settings/vcs', + 'admin_settings_vcs_update': + ADMIN_PREFIX + '/settings/vcs/update', + 'admin_settings_vcs_svn_pattern_delete': + ADMIN_PREFIX + '/settings/vcs/svn_pattern_delete', + 'admin_settings_mapping': + ADMIN_PREFIX + '/settings/mapping', + 'admin_settings_mapping_update': + ADMIN_PREFIX + '/settings/mapping/update', + 'admin_settings_visual': + ADMIN_PREFIX + '/settings/visual', + 'admin_settings_visual_update': + ADMIN_PREFIX + '/settings/visual/update', + 'admin_settings_issuetracker': + ADMIN_PREFIX + '/settings/issue-tracker', + 'admin_settings_issuetracker_update': + ADMIN_PREFIX + '/settings/issue-tracker/update', + 'admin_settings_issuetracker_test': + ADMIN_PREFIX + '/settings/issue-tracker/test', + 'admin_settings_issuetracker_delete': + ADMIN_PREFIX + '/settings/issue-tracker/delete', + 'admin_settings_email': + ADMIN_PREFIX + '/settings/email', + 'admin_settings_email_update': + ADMIN_PREFIX + '/settings/email/update', + 'admin_settings_hooks': + ADMIN_PREFIX + '/settings/hooks', + 'admin_settings_hooks_update': + ADMIN_PREFIX + '/settings/hooks/update', + 'admin_settings_hooks_delete': + ADMIN_PREFIX + '/settings/hooks/delete', + 'admin_settings_search': + ADMIN_PREFIX + '/settings/search', + 'admin_settings_labs': + ADMIN_PREFIX + '/settings/labs', + 'admin_settings_labs_update': + ADMIN_PREFIX + '/settings/labs/update', + + 'admin_settings_sessions': + ADMIN_PREFIX + '/settings/sessions', + 'admin_settings_sessions_cleanup': + ADMIN_PREFIX + '/settings/sessions/cleanup', + 'admin_settings_system': + ADMIN_PREFIX + '/settings/system', + 'admin_settings_system_update': + ADMIN_PREFIX + '/settings/system/updates', + 'admin_settings_open_source': + ADMIN_PREFIX + '/settings/open_source', + + + }[name].format(**kwargs) + + if params: + base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) + return base_url + + @pytest.mark.usefixtures('autologin_user', 'app') class TestAdminSettingsController(object): @@ -47,12 +119,12 @@ class TestAdminSettingsController(object 'admin_settings_hooks', 'admin_settings_search', ]) - def test_simple_get(self, urlname, app): - app.get(url(urlname)) + def test_simple_get(self, urlname): + self.app.get(route_path(urlname)) def test_create_custom_hook(self, csrf_token): response = self.app.post( - url('admin_settings_hooks'), + route_path('admin_settings_hooks_update'), params={ 'new_hook_ui_key': 'test_hooks_1', 'new_hook_ui_value': 'cd /tmp', @@ -64,7 +136,7 @@ class TestAdminSettingsController(object def test_create_custom_hook_delete(self, csrf_token): response = self.app.post( - url('admin_settings_hooks'), + route_path('admin_settings_hooks_update'), params={ 'new_hook_ui_key': 'test_hooks_2', 'new_hook_ui_value': 'cd /tmp2', @@ -78,9 +150,9 @@ class TestAdminSettingsController(object # delete self.app.post( - url('admin_settings_hooks'), + route_path('admin_settings_hooks_delete'), params={'hook_id': hook_id, 'csrf_token': csrf_token}) - response = self.app.get(url('admin_settings_hooks')) + response = self.app.get(route_path('admin_settings_hooks')) response.mustcontain(no=['test_hooks_2']) response.mustcontain(no=['cd /tmp2']) @@ -135,7 +207,6 @@ class TestAdminSettingsGlobal(object): def test_title_change(self, csrf_token): old_title = 'RhodeCode' - new_title = old_title + '_changed' for new_title in ['Changed', 'Żółwik', old_title]: response = self.post_and_verify_settings({ @@ -161,7 +232,8 @@ class TestAdminSettingsGlobal(object): 'rhodecode_personal_repo_group_pattern': '${username}', } params.update(settings) - response = self.app.post(url('admin_settings_global'), params=params) + response = self.app.post( + route_path('admin_settings_global_update'), params=params) assert_session_flash(response, 'Updated application settings') app_settings = SettingsModel().get_all_settings() @@ -175,8 +247,8 @@ class TestAdminSettingsGlobal(object): @pytest.mark.usefixtures('autologin_user', 'app') class TestAdminSettingsVcs(object): - def test_contains_svn_default_patterns(self, app): - response = app.get(url('admin_settings_vcs')) + def test_contains_svn_default_patterns(self): + response = self.app.get(route_path('admin_settings_vcs')) expected_patterns = [ '/trunk', '/branches/*', @@ -186,7 +258,7 @@ class TestAdminSettingsVcs(object): response.mustcontain(pattern) def test_add_new_svn_branch_and_tag_pattern( - self, app, backend_svn, form_defaults, disable_sql_cache, + self, backend_svn, form_defaults, disable_sql_cache, csrf_token): form_defaults.update({ 'new_svn_branch': '/exp/branches/*', @@ -194,8 +266,9 @@ class TestAdminSettingsVcs(object): 'csrf_token': csrf_token, }) - response = app.post( - url('admin_settings_vcs'), params=form_defaults, status=302) + response = self.app.post( + route_path('admin_settings_vcs_update'), + params=form_defaults, status=302) response = response.follow() # Expect to find the new values on the page @@ -208,12 +281,12 @@ class TestAdminSettingsVcs(object): assert 'important_tags/v0.5' in repo.tags def test_add_same_svn_value_twice_shows_an_error_message( - self, app, form_defaults, csrf_token, settings_util): + self, form_defaults, csrf_token, settings_util): settings_util.create_rhodecode_ui('vcs_svn_branch', '/test') settings_util.create_rhodecode_ui('vcs_svn_tag', '/test') - response = app.post( - url('admin_settings_vcs'), + response = self.app.post( + route_path('admin_settings_vcs_update'), params={ 'paths_root_path': form_defaults['paths_root_path'], 'new_svn_branch': '/test', @@ -230,14 +303,13 @@ class TestAdminSettingsVcs(object): 'vcs_svn_tag', ]) def test_delete_svn_patterns( - self, section, app, csrf_token, settings_util): + self, section, csrf_token, settings_util): setting = settings_util.create_rhodecode_ui( section, '/test_delete', cleanup=False) - app.post( - url('admin_settings_vcs'), + self.app.post( + route_path('admin_settings_vcs_svn_pattern_delete'), params={ - '_method': 'delete', 'delete_svn_pattern': setting.ui_id, 'csrf_token': csrf_token}, headers={'X-REQUESTED-WITH': 'XMLHttpRequest'}) @@ -246,25 +318,24 @@ class TestAdminSettingsVcs(object): 'vcs_svn_branch', 'vcs_svn_tag', ]) - def test_delete_svn_patterns_raises_400_when_no_xhr( - self, section, app, csrf_token, settings_util): + def test_delete_svn_patterns_raises_404_when_no_xhr( + self, section, csrf_token, settings_util): setting = settings_util.create_rhodecode_ui(section, '/test_delete') - app.post( - url('admin_settings_vcs'), + self.app.post( + route_path('admin_settings_vcs_svn_pattern_delete'), params={ - '_method': 'delete', 'delete_svn_pattern': setting.ui_id, 'csrf_token': csrf_token}, - status=400) + status=404) - def test_extensions_hgsubversion(self, app, form_defaults, csrf_token): + def test_extensions_hgsubversion(self, form_defaults, csrf_token): form_defaults.update({ 'csrf_token': csrf_token, 'extensions_hgsubversion': 'True', }) - response = app.post( - url('admin_settings_vcs'), + response = self.app.post( + route_path('admin_settings_vcs_update'), params=form_defaults, status=302) @@ -275,13 +346,13 @@ class TestAdminSettingsVcs(object): 'value="True" checked="checked" />') response.mustcontain(extensions_input) - def test_extensions_hgevolve(self, app, form_defaults, csrf_token): + def test_extensions_hgevolve(self, form_defaults, csrf_token): form_defaults.update({ 'csrf_token': csrf_token, 'extensions_evolve': 'True', }) - response = app.post( - url('admin_settings_vcs'), + response = self.app.post( + route_path('admin_settings_vcs_update'), params=form_defaults, status=302) @@ -292,20 +363,19 @@ class TestAdminSettingsVcs(object): 'value="True" checked="checked" />') response.mustcontain(extensions_input) - def test_has_a_section_for_pull_request_settings(self, app): - response = app.get(url('admin_settings_vcs')) + def test_has_a_section_for_pull_request_settings(self): + response = self.app.get(route_path('admin_settings_vcs')) response.mustcontain('Pull Request Settings') - def test_has_an_input_for_invalidation_of_inline_comments( - self, app): - response = app.get(url('admin_settings_vcs')) + def test_has_an_input_for_invalidation_of_inline_comments(self): + response = self.app.get(route_path('admin_settings_vcs')) assert_response = AssertResponse(response) assert_response.one_element_exists( '[name=rhodecode_use_outdated_comments]') @pytest.mark.parametrize('new_value', [True, False]) def test_allows_to_change_invalidation_of_inline_comments( - self, app, form_defaults, csrf_token, new_value): + self, form_defaults, csrf_token, new_value): setting_key = 'use_outdated_comments' setting = SettingsModel().create_or_update_setting( setting_key, not new_value, 'bool') @@ -316,8 +386,8 @@ class TestAdminSettingsVcs(object): 'csrf_token': csrf_token, 'rhodecode_use_outdated_comments': str(new_value), }) - response = app.post( - url('admin_settings_vcs'), + response = self.app.post( + route_path('admin_settings_vcs_update'), params=form_defaults, status=302) response = response.follow() @@ -326,7 +396,7 @@ class TestAdminSettingsVcs(object): @pytest.mark.parametrize('new_value', [True, False]) def test_allows_to_change_hg_rebase_merge_strategy( - self, app, form_defaults, csrf_token, new_value): + self, form_defaults, csrf_token, new_value): setting_key = 'hg_use_rebase_for_merging' form_defaults.update({ @@ -336,8 +406,8 @@ class TestAdminSettingsVcs(object): with mock.patch.dict( rhodecode.CONFIG, {'labs_settings_active': 'true'}): - app.post( - url('admin_settings_vcs'), + self.app.post( + route_path('admin_settings_vcs_update'), params=form_defaults, status=302) @@ -353,9 +423,8 @@ class TestAdminSettingsVcs(object): @pytest.fixture def form_defaults(self): - from rhodecode.controllers.admin.settings import SettingsController - controller = SettingsController() - return controller._form_defaults() + from rhodecode.apps.admin.views.settings import AdminSettingsView + return AdminSettingsView._form_defaults() # TODO: johbo: What we really want is to checkpoint before a test run and # reset the session afterwards. @@ -374,14 +443,16 @@ class TestAdminSettingsVcs(object): @pytest.mark.usefixtures('autologin_user', 'app') class TestLabsSettings(object): def test_get_settings_page_disabled(self): - with mock.patch.dict(rhodecode.CONFIG, - {'labs_settings_active': 'false'}): - response = self.app.get(url('admin_settings_labs'), status=302) + with mock.patch.dict( + rhodecode.CONFIG, {'labs_settings_active': 'false'}): - assert response.location.endswith(url('admin_settings')) + response = self.app.get( + route_path('admin_settings_labs'), status=302) + + assert response.location.endswith(route_path('admin_settings')) def test_get_settings_page_enabled(self): - from rhodecode.controllers.admin import settings + from rhodecode.apps.admin.views import settings lab_settings = [ settings.LabSetting( key='rhodecode_bool', @@ -401,7 +472,7 @@ class TestLabsSettings(object): with mock.patch.dict(rhodecode.CONFIG, {'labs_settings_active': 'true'}): with mock.patch.object(settings, '_LAB_SETTINGS', lab_settings): - response = self.app.get(url('admin_settings_labs')) + response = self.app.get(route_path('admin_settings_labs')) assert '' in response assert '' in response @@ -417,9 +488,6 @@ class TestLabsSettings(object): @pytest.mark.usefixtures('app') class TestOpenSourceLicenses(object): - def _get_url(self): - return ADMIN_PREFIX + '/settings/open_source' - def test_records_are_displayed(self, autologin_user): sample_licenses = { "python2.7-pytest-2.7.1": { @@ -433,7 +501,8 @@ class TestOpenSourceLicenses(object): 'rhodecode.apps.admin.views.open_source_licenses.read_opensource_licenses', return_value=sample_licenses) with read_licenses_patch: - response = self.app.get(self._get_url(), status=200) + response = self.app.get( + route_path('admin_settings_open_source'), status=200) assert_response = AssertResponse(response) assert_response.element_contains( @@ -444,29 +513,25 @@ class TestOpenSourceLicenses(object): assert_response.element_contains('.panel-body', license) def test_records_can_be_read(self, autologin_user): - response = self.app.get(self._get_url(), status=200) + response = self.app.get( + route_path('admin_settings_open_source'), status=200) assert_response = AssertResponse(response) assert_response.element_contains( '.panel-heading', 'Licenses of Third Party Packages') def test_forbidden_when_normal_user(self, autologin_regular_user): - self.app.get(self._get_url(), status=404) + self.app.get( + route_path('admin_settings_open_source'), status=404) @pytest.mark.usefixtures('app') class TestUserSessions(object): - def _get_url(self, name='admin_settings_sessions'): - return { - 'admin_settings_sessions': ADMIN_PREFIX + '/settings/sessions', - 'admin_settings_sessions_cleanup': ADMIN_PREFIX + '/settings/sessions/cleanup' - }[name] - def test_forbidden_when_normal_user(self, autologin_regular_user): - self.app.get(self._get_url(), status=404) + self.app.get(route_path('admin_settings_sessions'), status=404) def test_show_sessions_page(self, autologin_user): - response = self.app.get(self._get_url(), status=200) + response = self.app.get(route_path('admin_settings_sessions'), status=200) response.mustcontain('file') def test_cleanup_old_sessions(self, autologin_user, csrf_token): @@ -476,24 +541,19 @@ class TestUserSessions(object): 'expire_days': '60' } response = self.app.post( - self._get_url('admin_settings_sessions_cleanup'), params=post_data, + route_path('admin_settings_sessions_cleanup'), params=post_data, status=302) assert_session_flash(response, 'Cleaned up old sessions') @pytest.mark.usefixtures('app') class TestAdminSystemInfo(object): - def _get_url(self, name='admin_settings_system'): - return { - 'admin_settings_system': ADMIN_PREFIX + '/settings/system', - 'admin_settings_system_update': ADMIN_PREFIX + '/settings/system/updates', - }[name] def test_forbidden_when_normal_user(self, autologin_regular_user): - self.app.get(self._get_url(), status=404) + self.app.get(route_path('admin_settings_system'), status=404) def test_system_info_page(self, autologin_user): - response = self.app.get(self._get_url()) + response = self.app.get(route_path('admin_settings_system')) response.mustcontain('RhodeCode Community Edition, version {}'.format( rhodecode.__version__)) @@ -511,7 +571,7 @@ class TestAdminSystemInfo(object): ] } with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data): - response = self.app.get(self._get_url('admin_settings_system_update')) + response = self.app.get(route_path('admin_settings_system_update')) response.mustcontain('A new version is available') def test_system_update_nothing_new(self, autologin_user): @@ -524,13 +584,13 @@ class TestAdminSystemInfo(object): ] } with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data): - response = self.app.get(self._get_url('admin_settings_system_update')) + response = self.app.get(route_path('admin_settings_system_update')) response.mustcontain( 'You already have the latest stable version.') def test_system_update_bad_response(self, autologin_user): with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')): - response = self.app.get(self._get_url('admin_settings_system_update')) + response = self.app.get(route_path('admin_settings_system_update')) response.mustcontain( 'Bad data sent from update server') @@ -542,12 +602,12 @@ class TestAdminSettingsIssueTracker(obje PATTERN_KEY = RC_PREFIX + SHORT_PATTERN_KEY def test_issuetracker_index(self, autologin_user): - response = self.app.get(url('admin_settings_issuetracker')) + response = self.app.get(route_path('admin_settings_issuetracker')) assert response.status_code == 200 def test_add_empty_issuetracker_pattern( self, request, autologin_user, csrf_token): - post_url = url('admin_settings_issuetracker_save') + post_url = route_path('admin_settings_issuetracker_update') post_data = { 'csrf_token': csrf_token } @@ -557,7 +617,7 @@ class TestAdminSettingsIssueTracker(obje self, request, autologin_user, csrf_token): pattern = 'issuetracker_pat' another_pattern = pattern+'1' - post_url = url('admin_settings_issuetracker_save') + post_url = route_path('admin_settings_issuetracker_update') post_data = { 'new_pattern_pattern_0': pattern, 'new_pattern_url_0': 'url', @@ -600,7 +660,7 @@ class TestAdminSettingsIssueTracker(obje SettingsModel().create_or_update_setting( self.SHORT_PATTERN_KEY+old_uid, old_pattern, 'unicode') - post_url = url('admin_settings_issuetracker_save') + post_url = route_path('admin_settings_issuetracker_update') post_data = { 'new_pattern_pattern_0': pattern, 'new_pattern_url_0': 'url', @@ -634,7 +694,7 @@ class TestAdminSettingsIssueTracker(obje settings_util.create_rhodecode_setting( desc_key, 'old description', 'unicode', cleanup=False) - post_url = url('admin_settings_issuetracker_save') + post_url = route_path('admin_settings_issuetracker_update') post_data = { 'new_pattern_pattern_0': pattern, 'new_pattern_url_0': 'url', @@ -659,7 +719,7 @@ class TestAdminSettingsIssueTracker(obje settings_util.create_rhodecode_setting( self.SHORT_PATTERN_KEY+uid, pattern, 'unicode', cleanup=False) - post_url = url('admin_issuetracker_delete') + post_url = route_path('admin_settings_issuetracker_delete') post_data = { '_method': 'delete', 'uid': uid, diff --git a/rhodecode/apps/admin/views/settings.py b/rhodecode/apps/admin/views/settings.py new file mode 100644 --- /dev/null +++ b/rhodecode/apps/admin/views/settings.py @@ -0,0 +1,754 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-2017 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + + +import logging +import collections + +import datetime +import formencode +import formencode.htmlfill + +import rhodecode +from pyramid.view import view_config +from pyramid.httpexceptions import HTTPFound, HTTPNotFound +from pyramid.renderers import render +from pyramid.response import Response + +from rhodecode.apps._base import BaseAppView +from rhodecode.apps.admin.navigation import navigation_list +from rhodecode.apps.svn_support.config_keys import generate_config +from rhodecode.lib import helpers as h +from rhodecode.lib.auth import ( + LoginRequired, HasPermissionAllDecorator, CSRFRequired) +from rhodecode.lib.celerylib import tasks, run_task +from rhodecode.lib.utils import repo2db_mapper +from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict +from rhodecode.lib.index import searcher_from_config + +from rhodecode.model.db import RhodeCodeUi, Repository +from rhodecode.model.forms import (ApplicationSettingsForm, + ApplicationUiSettingsForm, ApplicationVisualisationForm, + LabsSettingsForm, IssueTrackerPatternsForm) +from rhodecode.model.repo_group import RepoGroupModel + +from rhodecode.model.scm import ScmModel +from rhodecode.model.notification import EmailNotificationModel +from rhodecode.model.meta import Session +from rhodecode.model.settings import ( + IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound, + SettingsModel) + + +log = logging.getLogger(__name__) + + +class AdminSettingsView(BaseAppView): + + def load_default_context(self): + c = self._get_local_tmpl_context() + c.labs_active = str2bool( + rhodecode.CONFIG.get('labs_settings_active', 'true')) + c.navlist = navigation_list(self.request) + self._register_global_c(c) + return c + + @classmethod + def _get_ui_settings(cls): + ret = RhodeCodeUi.query().all() + + if not ret: + raise Exception('Could not get application ui settings !') + settings = {} + for each in ret: + k = each.ui_key + v = each.ui_value + if k == '/': + k = 'root_path' + + if k in ['push_ssl', 'publish', 'enabled']: + v = str2bool(v) + + if k.find('.') != -1: + k = k.replace('.', '_') + + if each.ui_section in ['hooks', 'extensions']: + v = each.ui_active + + settings[each.ui_section + '_' + k] = v + return settings + + @classmethod + def _form_defaults(cls): + defaults = SettingsModel().get_all_settings() + defaults.update(cls._get_ui_settings()) + + defaults.update({ + 'new_svn_branch': '', + 'new_svn_tag': '', + }) + return defaults + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_vcs', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_vcs(self): + c = self.load_default_context() + c.active = 'vcs' + model = VcsSettingsModel() + c.svn_branch_patterns = model.get_global_svn_branch_patterns() + c.svn_tag_patterns = model.get_global_svn_tag_patterns() + + settings = self.request.registry.settings + c.svn_proxy_generate_config = settings[generate_config] + + defaults = self._form_defaults() + + model.create_largeobjects_dirs_if_needed(defaults['paths_root_path']) + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=defaults, + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_vcs_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_vcs_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'vcs' + + model = VcsSettingsModel() + c.svn_branch_patterns = model.get_global_svn_branch_patterns() + c.svn_tag_patterns = model.get_global_svn_tag_patterns() + + settings = self.request.registry.settings + c.svn_proxy_generate_config = settings[generate_config] + + application_form = ApplicationUiSettingsForm()() + + try: + form_result = application_form.to_python(dict(self.request.POST)) + except formencode.Invalid as errors: + h.flash( + _("Some form inputs contain invalid data."), + category='error') + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + try: + if c.visual.allow_repo_location_change: + model.update_global_path_setting( + form_result['paths_root_path']) + + model.update_global_ssl_setting(form_result['web_push_ssl']) + model.update_global_hook_settings(form_result) + + model.create_or_update_global_svn_settings(form_result) + model.create_or_update_global_hg_settings(form_result) + model.create_or_update_global_git_settings(form_result) + model.create_or_update_global_pr_settings(form_result) + except Exception: + log.exception("Exception while updating settings") + h.flash(_('Error occurred during updating ' + 'application settings'), category='error') + else: + Session().commit() + h.flash(_('Updated VCS settings'), category='success') + raise HTTPFound(h.route_path('admin_settings_vcs')) + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST', + renderer='json_ext', xhr=True) + def settings_vcs_delete_svn_pattern(self): + delete_pattern_id = self.request.POST.get('delete_svn_pattern') + model = VcsSettingsModel() + try: + model.delete_global_svn_pattern(delete_pattern_id) + except SettingNotFound: + log.exception( + 'Failed to delete svn_pattern with id %s', delete_pattern_id) + raise HTTPNotFound() + + Session().commit() + return True + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_mapping', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_mapping(self): + c = self.load_default_context() + c.active = 'mapping' + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_mapping_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_mapping_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'mapping' + rm_obsolete = self.request.POST.get('destroy', False) + invalidate_cache = self.request.POST.get('invalidate', False) + log.debug( + 'rescanning repo location with destroy obsolete=%s', rm_obsolete) + + if invalidate_cache: + log.debug('invalidating all repositories cache') + for repo in Repository.get_all(): + ScmModel().mark_for_invalidation(repo.repo_name, delete=True) + + filesystem_repos = ScmModel().repo_scan() + added, removed = repo2db_mapper(filesystem_repos, rm_obsolete) + _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-' + h.flash(_('Repositories successfully ' + 'rescanned added: %s ; removed: %s') % + (_repr(added), _repr(removed)), + category='success') + raise HTTPFound(h.route_path('admin_settings_mapping')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + @view_config( + route_name='admin_settings_global', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_global(self): + c = self.load_default_context() + c.active = 'global' + c.personal_repo_group_default_pattern = RepoGroupModel()\ + .get_personal_group_name_pattern() + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + @view_config( + route_name='admin_settings_global_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_global_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'global' + c.personal_repo_group_default_pattern = RepoGroupModel()\ + .get_personal_group_name_pattern() + application_form = ApplicationSettingsForm()() + try: + form_result = application_form.to_python(dict(self.request.POST)) + except formencode.Invalid as errors: + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + settings = [ + ('title', 'rhodecode_title', 'unicode'), + ('realm', 'rhodecode_realm', 'unicode'), + ('pre_code', 'rhodecode_pre_code', 'unicode'), + ('post_code', 'rhodecode_post_code', 'unicode'), + ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'), + ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'), + ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'), + ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'), + ] + try: + for setting, form_key, type_ in settings: + sett = SettingsModel().create_or_update_setting( + setting, form_result[form_key], type_) + Session().add(sett) + + Session().commit() + SettingsModel().invalidate_settings_cache() + h.flash(_('Updated application settings'), category='success') + except Exception: + log.exception("Exception while updating application settings") + h.flash( + _('Error occurred during updating application settings'), + category='error') + + raise HTTPFound(h.route_path('admin_settings_global')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_visual', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_visual(self): + c = self.load_default_context() + c.active = 'visual' + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_visual_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_visual_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'visual' + application_form = ApplicationVisualisationForm()() + try: + form_result = application_form.to_python(dict(self.request.POST)) + except formencode.Invalid as errors: + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + try: + settings = [ + ('show_public_icon', 'rhodecode_show_public_icon', 'bool'), + ('show_private_icon', 'rhodecode_show_private_icon', 'bool'), + ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'), + ('repository_fields', 'rhodecode_repository_fields', 'bool'), + ('dashboard_items', 'rhodecode_dashboard_items', 'int'), + ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'), + ('show_version', 'rhodecode_show_version', 'bool'), + ('use_gravatar', 'rhodecode_use_gravatar', 'bool'), + ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'), + ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'), + ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'), + ('support_url', 'rhodecode_support_url', 'unicode'), + ('show_revision_number', 'rhodecode_show_revision_number', 'bool'), + ('show_sha_length', 'rhodecode_show_sha_length', 'int'), + ] + for setting, form_key, type_ in settings: + sett = SettingsModel().create_or_update_setting( + setting, form_result[form_key], type_) + Session().add(sett) + + Session().commit() + SettingsModel().invalidate_settings_cache() + h.flash(_('Updated visualisation settings'), category='success') + except Exception: + log.exception("Exception updating visualization settings") + h.flash(_('Error occurred during updating ' + 'visualisation settings'), + category='error') + + raise HTTPFound(h.route_path('admin_settings_visual')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_issuetracker', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_issuetracker(self): + c = self.load_default_context() + c.active = 'issuetracker' + defaults = SettingsModel().get_all_settings() + + entry_key = 'rhodecode_issuetracker_pat_' + + c.issuetracker_entries = {} + for k, v in defaults.items(): + if k.startswith(entry_key): + uid = k[len(entry_key):] + c.issuetracker_entries[uid] = None + + for uid in c.issuetracker_entries: + c.issuetracker_entries[uid] = AttributeDict({ + 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid), + 'url': defaults.get('rhodecode_issuetracker_url_' + uid), + 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid), + 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid), + }) + + return self._get_template_context(c) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_issuetracker_test', request_method='POST', + renderer='string', xhr=True) + def settings_issuetracker_test(self): + return h.urlify_commit_message( + self.request.POST.get('test_text', ''), + 'repo_group/test_repo1') + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_issuetracker_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_issuetracker_update(self): + _ = self.request.translate + self.load_default_context() + settings_model = IssueTrackerSettingsModel() + + form = IssueTrackerPatternsForm()().to_python(self.request.POST) + if form: + for uid in form.get('delete_patterns', []): + settings_model.delete_entries(uid) + + for pattern in form.get('patterns', []): + for setting, value, type_ in pattern: + sett = settings_model.create_or_update_setting( + setting, value, type_) + Session().add(sett) + + Session().commit() + + SettingsModel().invalidate_settings_cache() + h.flash(_('Updated issue tracker entries'), category='success') + raise HTTPFound(h.route_path('admin_settings_issuetracker')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_issuetracker_delete', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_issuetracker_delete(self): + _ = self.request.translate + self.load_default_context() + uid = self.request.POST.get('uid') + try: + IssueTrackerSettingsModel().delete_entries(uid) + except Exception: + log.exception('Failed to delete issue tracker setting %s', uid) + raise HTTPNotFound() + h.flash(_('Removed issue tracker entry'), category='success') + raise HTTPFound(h.route_path('admin_settings_issuetracker')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_email', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_email(self): + c = self.load_default_context() + c.active = 'email' + c.rhodecode_ini = rhodecode.CONFIG + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_email_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_email_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'email' + + test_email = self.request.POST.get('test_email') + + if not test_email: + h.flash(_('Please enter email address'), category='error') + raise HTTPFound(h.route_path('admin_settings_email')) + + email_kwargs = { + 'date': datetime.datetime.now(), + 'user': c.rhodecode_user, + 'rhodecode_version': c.rhodecode_version + } + + (subject, headers, email_body, + email_body_plaintext) = EmailNotificationModel().render_email( + EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs) + + recipients = [test_email] if test_email else None + + run_task(tasks.send_email, recipients, subject, + email_body_plaintext, email_body) + + h.flash(_('Send email task created'), category='success') + raise HTTPFound(h.route_path('admin_settings_email')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_hooks', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_hooks(self): + c = self.load_default_context() + c.active = 'hooks' + + model = SettingsModel() + c.hooks = model.get_builtin_hooks() + c.custom_hooks = model.get_custom_hooks() + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_hooks_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + @view_config( + route_name='admin_settings_hooks_delete', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_hooks_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'hooks' + if c.visual.allow_custom_hooks_settings: + ui_key = self.request.POST.get('new_hook_ui_key') + ui_value = self.request.POST.get('new_hook_ui_value') + + hook_id = self.request.POST.get('hook_id') + new_hook = False + + model = SettingsModel() + try: + if ui_value and ui_key: + model.create_or_update_hook(ui_key, ui_value) + h.flash(_('Added new hook'), category='success') + new_hook = True + elif hook_id: + RhodeCodeUi.delete(hook_id) + Session().commit() + + # check for edits + update = False + _d = self.request.POST.dict_of_lists() + for k, v in zip(_d.get('hook_ui_key', []), + _d.get('hook_ui_value_new', [])): + model.create_or_update_hook(k, v) + update = True + + if update and not new_hook: + h.flash(_('Updated hooks'), category='success') + Session().commit() + except Exception: + log.exception("Exception during hook creation") + h.flash(_('Error occurred during hook creation'), + category='error') + + raise HTTPFound(h.route_path('admin_settings_hooks')) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_search', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_search(self): + c = self.load_default_context() + c.active = 'search' + + searcher = searcher_from_config(self.request.registry.settings) + c.statistics = searcher.statistics() + + return self._get_template_context(c) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_settings_labs', request_method='GET', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_labs(self): + c = self.load_default_context() + if not c.labs_active: + raise HTTPFound(h.route_path('admin_settings')) + + c.active = 'labs' + c.lab_settings = _LAB_SETTINGS + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @CSRFRequired() + @view_config( + route_name='admin_settings_labs_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') + def settings_labs_update(self): + _ = self.request.translate + c = self.load_default_context() + c.active = 'labs' + + application_form = LabsSettingsForm()() + try: + form_result = application_form.to_python(dict(self.request.POST)) + except formencode.Invalid as errors: + h.flash( + _('Some form inputs contain invalid data.'), + category='error') + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + try: + session = Session() + for setting in _LAB_SETTINGS: + setting_name = setting.key[len('rhodecode_'):] + sett = SettingsModel().create_or_update_setting( + setting_name, form_result[setting.key], setting.type) + session.add(sett) + + except Exception: + log.exception('Exception while updating lab settings') + h.flash(_('Error occurred during updating labs settings'), + category='error') + else: + Session().commit() + SettingsModel().invalidate_settings_cache() + h.flash(_('Updated Labs settings'), category='success') + raise HTTPFound(h.route_path('admin_settings_labs')) + + data = render('rhodecode:templates/admin/settings/settings.mako', + self._get_template_context(c), self.request) + html = formencode.htmlfill.render( + data, + defaults=self._form_defaults(), + encoding="UTF-8", + force_defaults=False + ) + return Response(html) + + +# :param key: name of the setting including the 'rhodecode_' prefix +# :param type: the RhodeCodeSetting type to use. +# :param group: the i18ned group in which we should dispaly this setting +# :param label: the i18ned label we should display for this setting +# :param help: the i18ned help we should dispaly for this setting +LabSetting = collections.namedtuple( + 'LabSetting', ('key', 'type', 'group', 'label', 'help')) + + +# This list has to be kept in sync with the form +# rhodecode.model.forms.LabsSettingsForm. +_LAB_SETTINGS = [ + +] diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -172,81 +172,6 @@ def make_map(config): # CUSTOM ROUTES HERE #========================================================================== - # ADMIN SETTINGS ROUTES - with rmap.submapper(path_prefix=ADMIN_PREFIX, - controller='admin/settings') as m: - - # default - m.connect('admin_settings', '/settings', - action='settings_global_update', - conditions={'method': ['POST']}) - m.connect('admin_settings', '/settings', - action='settings_global', conditions={'method': ['GET']}) - - m.connect('admin_settings_vcs', '/settings/vcs', - action='settings_vcs_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_vcs', '/settings/vcs', - action='settings_vcs', - conditions={'method': ['GET']}) - m.connect('admin_settings_vcs', '/settings/vcs', - action='delete_svn_pattern', - conditions={'method': ['DELETE']}) - - m.connect('admin_settings_mapping', '/settings/mapping', - action='settings_mapping_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_mapping', '/settings/mapping', - action='settings_mapping', conditions={'method': ['GET']}) - - m.connect('admin_settings_global', '/settings/global', - action='settings_global_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_global', '/settings/global', - action='settings_global', conditions={'method': ['GET']}) - - m.connect('admin_settings_visual', '/settings/visual', - action='settings_visual_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_visual', '/settings/visual', - action='settings_visual', conditions={'method': ['GET']}) - - m.connect('admin_settings_issuetracker', - '/settings/issue-tracker', action='settings_issuetracker', - conditions={'method': ['GET']}) - m.connect('admin_settings_issuetracker_save', - '/settings/issue-tracker/save', - action='settings_issuetracker_save', - conditions={'method': ['POST']}) - m.connect('admin_issuetracker_test', '/settings/issue-tracker/test', - action='settings_issuetracker_test', - conditions={'method': ['POST']}) - m.connect('admin_issuetracker_delete', - '/settings/issue-tracker/delete', - action='settings_issuetracker_delete', - conditions={'method': ['DELETE']}) - - m.connect('admin_settings_email', '/settings/email', - action='settings_email_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_email', '/settings/email', - action='settings_email', conditions={'method': ['GET']}) - - m.connect('admin_settings_hooks', '/settings/hooks', - action='settings_hooks_update', - conditions={'method': ['POST', 'DELETE']}) - m.connect('admin_settings_hooks', '/settings/hooks', - action='settings_hooks', conditions={'method': ['GET']}) - - m.connect('admin_settings_search', '/settings/search', - action='settings_search', conditions={'method': ['GET']}) - - m.connect('admin_settings_labs', '/settings/labs', - action='settings_labs_update', - conditions={'method': ['POST']}) - m.connect('admin_settings_labs', '/settings/labs', - action='settings_labs', conditions={'method': ['GET']}) - # ADMIN MY ACCOUNT with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/my_account') as m: diff --git a/rhodecode/controllers/admin/__init__.py b/rhodecode/controllers/admin/__init__.py deleted file mode 100644 --- a/rhodecode/controllers/admin/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2010-2017 RhodeCode GmbH -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License, version 3 -# (only), as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -# This program is dual-licensed. If you wish to learn more about the -# RhodeCode Enterprise Edition, including its added features, Support services, -# and proprietary license terms, please see https://rhodecode.com/licenses/ diff --git a/rhodecode/controllers/admin/settings.py b/rhodecode/controllers/admin/settings.py deleted file mode 100644 --- a/rhodecode/controllers/admin/settings.py +++ /dev/null @@ -1,631 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2010-2017 RhodeCode GmbH -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License, version 3 -# (only), as published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -# This program is dual-licensed. If you wish to learn more about the -# RhodeCode Enterprise Edition, including its added features, Support services, -# and proprietary license terms, please see https://rhodecode.com/licenses/ - - -""" -settings controller for rhodecode admin -""" - -import collections -import logging - -import datetime -import formencode -from formencode import htmlfill -from pylons import request, tmpl_context as c, url, config -from pylons.controllers.util import redirect -from pylons.i18n.translation import _ -from pylons.decorators import jsonify -from pyramid.threadlocal import get_current_registry -from webob.exc import HTTPBadRequest - -import rhodecode -from rhodecode.apps.admin.navigation import navigation_list -from rhodecode.apps.svn_support.config_keys import generate_config -from rhodecode.lib import auth -from rhodecode.lib import helpers as h -from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator -from rhodecode.lib.base import BaseController, render -from rhodecode.lib.celerylib import tasks, run_task -from rhodecode.lib.utils import repo2db_mapper -from rhodecode.lib.utils2 import ( - str2bool, safe_unicode, AttributeDict, safe_int) - -from rhodecode.model.db import RhodeCodeUi, Repository -from rhodecode.model.forms import ApplicationSettingsForm, \ - ApplicationUiSettingsForm, ApplicationVisualisationForm, \ - LabsSettingsForm, IssueTrackerPatternsForm -from rhodecode.model.repo_group import RepoGroupModel - -from rhodecode.model.scm import ScmModel -from rhodecode.model.notification import EmailNotificationModel -from rhodecode.model.meta import Session -from rhodecode.model.settings import ( - IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound, - SettingsModel) - - -log = logging.getLogger(__name__) - - -class SettingsController(BaseController): - """REST Controller styled on the Atom Publishing Protocol""" - # To properly map this controller, ensure your config/routing.py - # file has a resource setup: - # map.resource('setting', 'settings', controller='admin/settings', - # path_prefix='/admin', name_prefix='admin_') - - @LoginRequired() - def __before__(self): - super(SettingsController, self).__before__() - c.labs_active = str2bool( - rhodecode.CONFIG.get('labs_settings_active', 'true')) - c.navlist = navigation_list(request) - - def _get_ui_settings(self): - ret = RhodeCodeUi.query().all() - - if not ret: - raise Exception('Could not get application ui settings !') - settings = {} - for each in ret: - k = each.ui_key - v = each.ui_value - if k == '/': - k = 'root_path' - - if k in ['push_ssl', 'publish', 'enabled']: - v = str2bool(v) - - if k.find('.') != -1: - k = k.replace('.', '_') - - if each.ui_section in ['hooks', 'extensions']: - v = each.ui_active - - settings[each.ui_section + '_' + k] = v - return settings - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - @jsonify - def delete_svn_pattern(self): - if not request.is_xhr: - raise HTTPBadRequest() - - delete_pattern_id = request.POST.get('delete_svn_pattern') - model = VcsSettingsModel() - try: - model.delete_global_svn_pattern(delete_pattern_id) - except SettingNotFound: - raise HTTPBadRequest() - - Session().commit() - return True - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_vcs_update(self): - """POST /admin/settings: All items in the collection""" - # url('admin_settings_vcs') - c.active = 'vcs' - - model = VcsSettingsModel() - c.svn_branch_patterns = model.get_global_svn_branch_patterns() - c.svn_tag_patterns = model.get_global_svn_tag_patterns() - - # TODO: Replace with request.registry after migrating to pyramid. - pyramid_settings = get_current_registry().settings - c.svn_proxy_generate_config = pyramid_settings[generate_config] - - application_form = ApplicationUiSettingsForm()() - - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid as errors: - h.flash( - _("Some form inputs contain invalid data."), - category='error') - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8", - force_defaults=False - ) - - try: - if c.visual.allow_repo_location_change: - model.update_global_path_setting( - form_result['paths_root_path']) - - model.update_global_ssl_setting(form_result['web_push_ssl']) - model.update_global_hook_settings(form_result) - - model.create_or_update_global_svn_settings(form_result) - model.create_or_update_global_hg_settings(form_result) - model.create_or_update_global_git_settings(form_result) - model.create_or_update_global_pr_settings(form_result) - except Exception: - log.exception("Exception while updating settings") - h.flash(_('Error occurred during updating ' - 'application settings'), category='error') - else: - Session().commit() - h.flash(_('Updated VCS settings'), category='success') - return redirect(url('admin_settings_vcs')) - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - def settings_vcs(self): - """GET /admin/settings: All items in the collection""" - # url('admin_settings_vcs') - c.active = 'vcs' - model = VcsSettingsModel() - c.svn_branch_patterns = model.get_global_svn_branch_patterns() - c.svn_tag_patterns = model.get_global_svn_tag_patterns() - - # TODO: Replace with request.registry after migrating to pyramid. - pyramid_settings = get_current_registry().settings - c.svn_proxy_generate_config = pyramid_settings[generate_config] - - defaults = self._form_defaults() - - model.create_largeobjects_dirs_if_needed(defaults['paths_root_path']) - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=defaults, - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_mapping_update(self): - """POST /admin/settings/mapping: All items in the collection""" - # url('admin_settings_mapping') - c.active = 'mapping' - rm_obsolete = request.POST.get('destroy', False) - invalidate_cache = request.POST.get('invalidate', False) - log.debug( - 'rescanning repo location with destroy obsolete=%s', rm_obsolete) - - if invalidate_cache: - log.debug('invalidating all repositories cache') - for repo in Repository.get_all(): - ScmModel().mark_for_invalidation(repo.repo_name, delete=True) - - filesystem_repos = ScmModel().repo_scan() - added, removed = repo2db_mapper(filesystem_repos, rm_obsolete) - _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-' - h.flash(_('Repositories successfully ' - 'rescanned added: %s ; removed: %s') % - (_repr(added), _repr(removed)), - category='success') - return redirect(url('admin_settings_mapping')) - - @HasPermissionAllDecorator('hg.admin') - def settings_mapping(self): - """GET /admin/settings/mapping: All items in the collection""" - # url('admin_settings_mapping') - c.active = 'mapping' - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_global_update(self): - """POST /admin/settings/global: All items in the collection""" - # url('admin_settings_global') - c.active = 'global' - c.personal_repo_group_default_pattern = RepoGroupModel()\ - .get_personal_group_name_pattern() - application_form = ApplicationSettingsForm()() - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid as errors: - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8", - force_defaults=False) - - try: - settings = [ - ('title', 'rhodecode_title', 'unicode'), - ('realm', 'rhodecode_realm', 'unicode'), - ('pre_code', 'rhodecode_pre_code', 'unicode'), - ('post_code', 'rhodecode_post_code', 'unicode'), - ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'), - ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'), - ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'), - ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'), - ] - for setting, form_key, type_ in settings: - sett = SettingsModel().create_or_update_setting( - setting, form_result[form_key], type_) - Session().add(sett) - - Session().commit() - SettingsModel().invalidate_settings_cache() - h.flash(_('Updated application settings'), category='success') - except Exception: - log.exception("Exception while updating application settings") - h.flash( - _('Error occurred during updating application settings'), - category='error') - - return redirect(url('admin_settings_global')) - - @HasPermissionAllDecorator('hg.admin') - def settings_global(self): - """GET /admin/settings/global: All items in the collection""" - # url('admin_settings_global') - c.active = 'global' - c.personal_repo_group_default_pattern = RepoGroupModel()\ - .get_personal_group_name_pattern() - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_visual_update(self): - """POST /admin/settings/visual: All items in the collection""" - # url('admin_settings_visual') - c.active = 'visual' - application_form = ApplicationVisualisationForm()() - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid as errors: - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding="UTF-8", - force_defaults=False - ) - - try: - settings = [ - ('show_public_icon', 'rhodecode_show_public_icon', 'bool'), - ('show_private_icon', 'rhodecode_show_private_icon', 'bool'), - ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'), - ('repository_fields', 'rhodecode_repository_fields', 'bool'), - ('dashboard_items', 'rhodecode_dashboard_items', 'int'), - ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'), - ('show_version', 'rhodecode_show_version', 'bool'), - ('use_gravatar', 'rhodecode_use_gravatar', 'bool'), - ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'), - ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'), - ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'), - ('support_url', 'rhodecode_support_url', 'unicode'), - ('show_revision_number', 'rhodecode_show_revision_number', 'bool'), - ('show_sha_length', 'rhodecode_show_sha_length', 'int'), - ] - for setting, form_key, type_ in settings: - sett = SettingsModel().create_or_update_setting( - setting, form_result[form_key], type_) - Session().add(sett) - - Session().commit() - SettingsModel().invalidate_settings_cache() - h.flash(_('Updated visualisation settings'), category='success') - except Exception: - log.exception("Exception updating visualization settings") - h.flash(_('Error occurred during updating ' - 'visualisation settings'), - category='error') - - return redirect(url('admin_settings_visual')) - - @HasPermissionAllDecorator('hg.admin') - def settings_visual(self): - """GET /admin/settings/visual: All items in the collection""" - # url('admin_settings_visual') - c.active = 'visual' - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_issuetracker_test(self): - if request.is_xhr: - return h.urlify_commit_message( - request.POST.get('test_text', ''), - 'repo_group/test_repo1') - else: - raise HTTPBadRequest() - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_issuetracker_delete(self): - uid = request.POST.get('uid') - IssueTrackerSettingsModel().delete_entries(uid) - h.flash(_('Removed issue tracker entry'), category='success') - return redirect(url('admin_settings_issuetracker')) - - @HasPermissionAllDecorator('hg.admin') - def settings_issuetracker(self): - """GET /admin/settings/issue-tracker: All items in the collection""" - # url('admin_settings_issuetracker') - c.active = 'issuetracker' - defaults = SettingsModel().get_all_settings() - - entry_key = 'rhodecode_issuetracker_pat_' - - c.issuetracker_entries = {} - for k, v in defaults.items(): - if k.startswith(entry_key): - uid = k[len(entry_key):] - c.issuetracker_entries[uid] = None - - for uid in c.issuetracker_entries: - c.issuetracker_entries[uid] = AttributeDict({ - 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid), - 'url': defaults.get('rhodecode_issuetracker_url_' + uid), - 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid), - 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid), - }) - - return render('admin/settings/settings.mako') - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_issuetracker_save(self): - settings_model = IssueTrackerSettingsModel() - - form = IssueTrackerPatternsForm()().to_python(request.POST) - if form: - for uid in form.get('delete_patterns', []): - settings_model.delete_entries(uid) - - for pattern in form.get('patterns', []): - for setting, value, type_ in pattern: - sett = settings_model.create_or_update_setting( - setting, value, type_) - Session().add(sett) - - Session().commit() - - SettingsModel().invalidate_settings_cache() - h.flash(_('Updated issue tracker entries'), category='success') - return redirect(url('admin_settings_issuetracker')) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_email_update(self): - """POST /admin/settings/email: All items in the collection""" - # url('admin_settings_email') - c.active = 'email' - - test_email = request.POST.get('test_email') - - if not test_email: - h.flash(_('Please enter email address'), category='error') - return redirect(url('admin_settings_email')) - - email_kwargs = { - 'date': datetime.datetime.now(), - 'user': c.rhodecode_user, - 'rhodecode_version': c.rhodecode_version - } - - (subject, headers, email_body, - email_body_plaintext) = EmailNotificationModel().render_email( - EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs) - - recipients = [test_email] if test_email else None - - run_task(tasks.send_email, recipients, subject, - email_body_plaintext, email_body) - - h.flash(_('Send email task created'), category='success') - return redirect(url('admin_settings_email')) - - @HasPermissionAllDecorator('hg.admin') - def settings_email(self): - """GET /admin/settings/email: All items in the collection""" - # url('admin_settings_email') - c.active = 'email' - c.rhodecode_ini = rhodecode.CONFIG - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_hooks_update(self): - """POST or DELETE /admin/settings/hooks: All items in the collection""" - # url('admin_settings_hooks') - c.active = 'hooks' - if c.visual.allow_custom_hooks_settings: - ui_key = request.POST.get('new_hook_ui_key') - ui_value = request.POST.get('new_hook_ui_value') - - hook_id = request.POST.get('hook_id') - new_hook = False - - model = SettingsModel() - try: - if ui_value and ui_key: - model.create_or_update_hook(ui_key, ui_value) - h.flash(_('Added new hook'), category='success') - new_hook = True - elif hook_id: - RhodeCodeUi.delete(hook_id) - Session().commit() - - # check for edits - update = False - _d = request.POST.dict_of_lists() - for k, v in zip(_d.get('hook_ui_key', []), - _d.get('hook_ui_value_new', [])): - model.create_or_update_hook(k, v) - update = True - - if update and not new_hook: - h.flash(_('Updated hooks'), category='success') - Session().commit() - except Exception: - log.exception("Exception during hook creation") - h.flash(_('Error occurred during hook creation'), - category='error') - - return redirect(url('admin_settings_hooks')) - - @HasPermissionAllDecorator('hg.admin') - def settings_hooks(self): - """GET /admin/settings/hooks: All items in the collection""" - # url('admin_settings_hooks') - c.active = 'hooks' - - model = SettingsModel() - c.hooks = model.get_builtin_hooks() - c.custom_hooks = model.get_custom_hooks() - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding="UTF-8", - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - def settings_search(self): - """GET /admin/settings/search: All items in the collection""" - # url('admin_settings_search') - c.active = 'search' - - from rhodecode.lib.index import searcher_from_config - searcher = searcher_from_config(config) - c.statistics = searcher.statistics() - - return render('admin/settings/settings.mako') - - @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_labs_update(self): - """POST /admin/settings/labs: All items in the collection""" - # url('admin_settings/labs', method={'POST'}) - c.active = 'labs' - - application_form = LabsSettingsForm()() - try: - form_result = application_form.to_python(dict(request.POST)) - except formencode.Invalid as errors: - h.flash( - _('Some form inputs contain invalid data.'), - category='error') - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=errors.value, - errors=errors.error_dict or {}, - prefix_error=False, - encoding='UTF-8', - force_defaults=False - ) - - try: - session = Session() - for setting in _LAB_SETTINGS: - setting_name = setting.key[len('rhodecode_'):] - sett = SettingsModel().create_or_update_setting( - setting_name, form_result[setting.key], setting.type) - session.add(sett) - - except Exception: - log.exception('Exception while updating lab settings') - h.flash(_('Error occurred during updating labs settings'), - category='error') - else: - Session().commit() - SettingsModel().invalidate_settings_cache() - h.flash(_('Updated Labs settings'), category='success') - return redirect(url('admin_settings_labs')) - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding='UTF-8', - force_defaults=False) - - @HasPermissionAllDecorator('hg.admin') - def settings_labs(self): - """GET /admin/settings/labs: All items in the collection""" - # url('admin_settings_labs') - if not c.labs_active: - redirect(url('admin_settings')) - - c.active = 'labs' - c.lab_settings = _LAB_SETTINGS - - return htmlfill.render( - render('admin/settings/settings.mako'), - defaults=self._form_defaults(), - encoding='UTF-8', - force_defaults=False) - - def _form_defaults(self): - defaults = SettingsModel().get_all_settings() - defaults.update(self._get_ui_settings()) - - defaults.update({ - 'new_svn_branch': '', - 'new_svn_tag': '', - }) - return defaults - - -# :param key: name of the setting including the 'rhodecode_' prefix -# :param type: the RhodeCodeSetting type to use. -# :param group: the i18ned group in which we should dispaly this setting -# :param label: the i18ned label we should display for this setting -# :param help: the i18ned help we should dispaly for this setting -LabSetting = collections.namedtuple( - 'LabSetting', ('key', 'type', 'group', 'label', 'help')) - - -# This list has to be kept in sync with the form -# rhodecode.model.forms.LabsSettingsForm. -_LAB_SETTINGS = [ - -] diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -51,6 +51,29 @@ function registerRCRoutes() { pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []); pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []); pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []); + pyroutes.register('admin_settings', '/_admin/settings', []); + pyroutes.register('admin_settings_update', '/_admin/settings/update', []); + pyroutes.register('admin_settings_global', '/_admin/settings/global', []); + pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []); + pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []); + pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []); + pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []); + pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []); + pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []); + pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []); + pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []); + pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []); + pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []); + pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []); + pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []); + pyroutes.register('admin_settings_email', '/_admin/settings/email', []); + pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []); + pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []); + pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []); + pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []); + pyroutes.register('admin_settings_search', '/_admin/settings/search', []); + pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []); + pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []); pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []); pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []); pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []); diff --git a/rhodecode/templates/admin/integrations/form.mako b/rhodecode/templates/admin/integrations/form.mako --- a/rhodecode/templates/admin/integrations/form.mako +++ b/rhodecode/templates/admin/integrations/form.mako @@ -27,7 +27,7 @@ %else: ${h.link_to(_('Admin'),h.route_path('admin_home'))} » - ${h.link_to(_('Settings'),h.url('admin_settings'))} + ${h.link_to(_('Settings'),h.route_path('admin_settings'))} » ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))} » diff --git a/rhodecode/templates/admin/integrations/list.mako b/rhodecode/templates/admin/integrations/list.mako --- a/rhodecode/templates/admin/integrations/list.mako +++ b/rhodecode/templates/admin/integrations/list.mako @@ -13,7 +13,7 @@ %else: ${h.link_to(_('Admin'),h.route_path('admin_home'))} » - ${h.link_to(_('Settings'),h.url('admin_settings'))} + ${h.link_to(_('Settings'),h.route_path('admin_settings'))} %endif %if c.current_IntegrationType: » diff --git a/rhodecode/templates/admin/integrations/new.mako b/rhodecode/templates/admin/integrations/new.mako --- a/rhodecode/templates/admin/integrations/new.mako +++ b/rhodecode/templates/admin/integrations/new.mako @@ -18,7 +18,7 @@ %else: ${h.link_to(_('Admin'),h.route_path('admin_home'))} » - ${h.link_to(_('Settings'),h.url('admin_settings'))} + ${h.link_to(_('Settings'),h.route_path('admin_settings'))} » ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))} %endif diff --git a/rhodecode/templates/admin/repos/repo_add_base.mako b/rhodecode/templates/admin/repos/repo_add_base.mako --- a/rhodecode/templates/admin/repos/repo_add_base.mako +++ b/rhodecode/templates/admin/repos/repo_add_base.mako @@ -33,7 +33,7 @@ add authentication information to the URL: https://username:password@server.company.com/repo-name. - The Git LFS/Mercurial Largefiles objects will not be imported. - For very large repositories, it's recommended to manually copy them into the - RhodeCode storage location and run Remap and Rescan. + RhodeCode storage location and run Remap and Rescan. diff --git a/rhodecode/templates/admin/settings/settings_email.mako b/rhodecode/templates/admin/settings/settings_email.mako --- a/rhodecode/templates/admin/settings/settings_email.mako +++ b/rhodecode/templates/admin/settings/settings_email.mako @@ -34,7 +34,7 @@

${_('Test Email')}

- ${h.secure_form(h.url('admin_settings_email'), request=request)} + ${h.secure_form(h.route_path('admin_settings_email_update'), request=request)}
${h.text('test_email', size=60, placeholder=_('enter valid email'))} diff --git a/rhodecode/templates/admin/settings/settings_global.mako b/rhodecode/templates/admin/settings/settings_global.mako --- a/rhodecode/templates/admin/settings/settings_global.mako +++ b/rhodecode/templates/admin/settings/settings_global.mako @@ -1,4 +1,4 @@ -${h.secure_form(h.url('admin_settings_global'), request=request)} +${h.secure_form(h.route_path('admin_settings_global_update'), request=request)}
diff --git a/rhodecode/templates/admin/settings/settings_hooks.mako b/rhodecode/templates/admin/settings/settings_hooks.mako --- a/rhodecode/templates/admin/settings/settings_hooks.mako +++ b/rhodecode/templates/admin/settings/settings_hooks.mako @@ -28,7 +28,7 @@
% if c.visual.allow_custom_hooks_settings: - ${h.secure_form(h.url('admin_settings_hooks'), request=request)} + ${h.secure_form(h.route_path('admin_settings_hooks_update'), request=request)}
@@ -74,13 +74,12 @@ diff --git a/rhodecode/templates/admin/settings/settings_issuetracker.mako b/rhodecode/templates/admin/settings/settings_issuetracker.mako --- a/rhodecode/templates/admin/settings/settings_issuetracker.mako +++ b/rhodecode/templates/admin/settings/settings_issuetracker.mako @@ -5,11 +5,11 @@

${_('Issue Tracker / Wiki Patterns')}

- ${h.secure_form(h.url('admin_settings_issuetracker_save'), request=request)} + ${h.secure_form(h.route_path('admin_settings_issuetracker_update'), request=request)} ${its.issue_tracker_settings_table( patterns=c.issuetracker_entries.items(), - form_url=h.url('admin_settings_issuetracker'), - delete_url=h.url('admin_issuetracker_delete') + form_url=h.route_path('admin_settings_issuetracker'), + delete_url=h.route_path('admin_settings_issuetracker_delete') )}
@@ -25,7 +25,7 @@
${its.issue_tracker_new_row()} - ${its.issue_tracker_settings_test(test_url=h.url('admin_issuetracker_test'))} + ${its.issue_tracker_settings_test(test_url=h.route_path('admin_settings_issuetracker_test'))}
diff --git a/rhodecode/templates/admin/settings/settings_labs.mako b/rhodecode/templates/admin/settings/settings_labs.mako --- a/rhodecode/templates/admin/settings/settings_labs.mako +++ b/rhodecode/templates/admin/settings/settings_labs.mako @@ -3,7 +3,7 @@

${_('Labs Settings')}

- ${h.secure_form(h.url('admin_settings_labs'), request=request)} + ${h.secure_form(h.route_path('admin_settings_labs_update'), request=request)}
% if not c.lab_settings: diff --git a/rhodecode/templates/admin/settings/settings_mapping.mako b/rhodecode/templates/admin/settings/settings_mapping.mako --- a/rhodecode/templates/admin/settings/settings_mapping.mako +++ b/rhodecode/templates/admin/settings/settings_mapping.mako @@ -1,4 +1,4 @@ -${h.secure_form(h.url('admin_settings_mapping'), request=request)} +${h.secure_form(h.route_path('admin_settings_mapping_update'), request=request)}
diff --git a/rhodecode/templates/admin/settings/settings_vcs.mako b/rhodecode/templates/admin/settings/settings_vcs.mako --- a/rhodecode/templates/admin/settings/settings_vcs.mako +++ b/rhodecode/templates/admin/settings/settings_vcs.mako @@ -1,6 +1,6 @@ <%namespace name="vcss" file="/base/vcs_settings.mako"/> -${h.secure_form(h.url('admin_settings_vcs'), request=request)} +${h.secure_form(h.route_path('admin_settings_vcs_update'), request=request)}
${vcss.vcs_settings_fields( suffix='', @@ -19,13 +19,12 @@