diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py index 448d6923..998b5876 100644 --- 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 index 891607ec..77022907 100644 --- 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 similarity index 75% rename from rhodecode/tests/functional/test_admin_settings.py rename to rhodecode/apps/admin/tests/test_admin_settings.py index efac41d1..99860f49 100644 --- 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(object): 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(object): 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(object): 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(object): 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(object): 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/controllers/admin/settings.py b/rhodecode/apps/admin/views/settings.py similarity index 55% rename from rhodecode/controllers/admin/settings.py rename to rhodecode/apps/admin/views/settings.py index 65932503..9f1034f6 100644 --- a/rhodecode/controllers/admin/settings.py +++ b/rhodecode/apps/admin/views/settings.py @@ -19,39 +19,34 @@ # and proprietary license terms, please see https://rhodecode.com/licenses/ -""" -settings controller for rhodecode admin -""" - -import collections import logging +import collections 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 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 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.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, safe_int) +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.forms import (ApplicationSettingsForm, + ApplicationUiSettingsForm, ApplicationVisualisationForm, + LabsSettingsForm, IssueTrackerPatternsForm) from rhodecode.model.repo_group import RepoGroupModel from rhodecode.model.scm import ScmModel @@ -65,21 +60,18 @@ from rhodecode.model.settings import ( 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_') +class AdminSettingsView(BaseAppView): - @LoginRequired() - def __before__(self): - super(SettingsController, self).__before__() + 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(request) + c.navlist = navigation_list(self.request) + self._register_global_c(c) + return c - def _get_ui_settings(self): + @classmethod + def _get_ui_settings(cls): ret = RhodeCodeUi.query().all() if not ret: @@ -103,54 +95,83 @@ class SettingsController(BaseController): 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() + @classmethod + def _form_defaults(cls): + defaults = SettingsModel().get_all_settings() + defaults.update(cls._get_ui_settings()) - delete_pattern_id = request.POST.get('delete_svn_pattern') + 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() - try: - model.delete_global_svn_pattern(delete_pattern_id) - except SettingNotFound: - raise HTTPBadRequest() + c.svn_branch_patterns = model.get_global_svn_branch_patterns() + c.svn_tag_patterns = model.get_global_svn_tag_patterns() - Session().commit() - return True + 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') - @auth.CSRFRequired() + @CSRFRequired() + @view_config( + route_name='admin_settings_vcs_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') def settings_vcs_update(self): - """POST /admin/settings: All items in the collection""" - # url('admin_settings_vcs') + _ = 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() - # TODO: Replace with request.registry after migrating to pyramid. - pyramid_settings = get_current_registry().settings - c.svn_proxy_generate_config = pyramid_settings[generate_config] + settings = self.request.registry.settings + c.svn_proxy_generate_config = settings[generate_config] application_form = ApplicationUiSettingsForm()() try: - form_result = application_form.to_python(dict(request.POST)) + 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') - return htmlfill.render( - render('admin/settings/settings.mako'), + 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: @@ -171,44 +192,68 @@ class SettingsController(BaseController): else: Session().commit() h.flash(_('Updated VCS settings'), category='success') - return redirect(url('admin_settings_vcs')) + raise HTTPFound(h.route_path('admin_settings_vcs')) - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) + force_defaults=False + ) + return Response(html) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - def settings_vcs(self): - """GET /admin/settings: All items in the collection""" - # url('admin_settings_vcs') - c.active = 'vcs' + @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() - c.svn_branch_patterns = model.get_global_svn_branch_patterns() - c.svn_tag_patterns = model.get_global_svn_tag_patterns() + 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() - # 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) + Session().commit() + return True + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_mapping_update(self): - """POST /admin/settings/mapping: All items in the collection""" - # url('admin_settings_mapping') + @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' - rm_obsolete = request.POST.get('destroy', False) - invalidate_cache = request.POST.get('invalidate', False) + + 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) @@ -224,51 +269,74 @@ class SettingsController(BaseController): 'rescanned added: %s ; removed: %s') % (_repr(added), _repr(removed)), category='success') - return redirect(url('admin_settings_mapping')) + raise HTTPFound(h.route_path('admin_settings_mapping')) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - def settings_mapping(self): - """GET /admin/settings/mapping: All items in the collection""" - # url('admin_settings_mapping') - c.active = 'mapping' + @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() - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) + force_defaults=False + ) + return Response(html) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() + @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): - """POST /admin/settings/global: All items in the collection""" - # url('admin_settings_global') + _ = 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(request.POST)) + form_result = application_form.to_python(dict(self.request.POST)) except formencode.Invalid as errors: - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) + 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: - 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_) @@ -283,40 +351,52 @@ class SettingsController(BaseController): _('Error occurred during updating application settings'), category='error') - return redirect(url('admin_settings_global')) + raise HTTPFound(h.route_path('admin_settings_global')) + @LoginRequired() @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() + @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' - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) + force_defaults=False + ) + return Response(html) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() + @CSRFRequired() + @view_config( + route_name='admin_settings_visual_update', request_method='POST', + renderer='rhodecode:templates/admin/settings/settings.mako') def settings_visual_update(self): - """POST /admin/settings/visual: All items in the collection""" - # url('admin_settings_visual') + _ = self.request.translate + c = self.load_default_context() c.active = 'visual' application_form = ApplicationVisualisationForm()() try: - form_result = application_form.to_python(dict(request.POST)) + form_result = application_form.to_python(dict(self.request.POST)) except formencode.Invalid as errors: - return htmlfill.render( - render('admin/settings/settings.mako'), + 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 = [ @@ -349,42 +429,15 @@ class SettingsController(BaseController): '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')) + 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): - """GET /admin/settings/issue-tracker: All items in the collection""" - # url('admin_settings_issuetracker') + c = self.load_default_context() c.active = 'issuetracker' defaults = SettingsModel().get_all_settings() @@ -404,14 +457,31 @@ class SettingsController(BaseController): 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid), }) - return render('admin/settings/settings.mako') + return self._get_template_context(c) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() - def settings_issuetracker_save(self): + @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(request.POST) + form = IssueTrackerPatternsForm()().to_python(self.request.POST) if form: for uid in form.get('delete_patterns', []): settings_model.delete_entries(uid) @@ -426,20 +496,62 @@ class SettingsController(BaseController): SettingsModel().invalidate_settings_cache() h.flash(_('Updated issue tracker entries'), category='success') - return redirect(url('admin_settings_issuetracker')) + raise HTTPFound(h.route_path('admin_settings_issuetracker')) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() + @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): - """POST /admin/settings/email: All items in the collection""" - # url('admin_settings_email') + _ = self.request.translate + c = self.load_default_context() c.active = 'email' - test_email = request.POST.get('test_email') + test_email = self.request.POST.get('test_email') if not test_email: h.flash(_('Please enter email address'), category='error') - return redirect(url('admin_settings_email')) + raise HTTPFound(h.route_path('admin_settings_email')) email_kwargs = { 'date': datetime.datetime.now(), @@ -457,32 +569,49 @@ class SettingsController(BaseController): email_body_plaintext, email_body) h.flash(_('Send email task created'), category='success') - return redirect(url('admin_settings_email')) + raise HTTPFound(h.route_path('admin_settings_email')) + @LoginRequired() @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 + @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' - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) + force_defaults=False + ) + return Response(html) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() + @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): - """POST or DELETE /admin/settings/hooks: All items in the collection""" - # url('admin_settings_hooks') + _ = self.request.translate + c = self.load_default_context() 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') + ui_key = self.request.POST.get('new_hook_ui_key') + ui_value = self.request.POST.get('new_hook_ui_value') - hook_id = request.POST.get('hook_id') + hook_id = self.request.POST.get('hook_id') new_hook = False model = SettingsModel() @@ -497,7 +626,7 @@ class SettingsController(BaseController): # check for edits update = False - _d = request.POST.dict_of_lists() + _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) @@ -511,58 +640,74 @@ class SettingsController(BaseController): 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) + 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): - """GET /admin/settings/search: All items in the collection""" - # url('admin_settings_search') + c = self.load_default_context() c.active = 'search' - from rhodecode.lib.index import searcher_from_config - searcher = searcher_from_config(config) + searcher = searcher_from_config(self.request.registry.settings) c.statistics = searcher.statistics() - return render('admin/settings/settings.mako') + return self._get_template_context(c) + @LoginRequired() @HasPermissionAllDecorator('hg.admin') - @auth.CSRFRequired() + @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): - """POST /admin/settings/labs: All items in the collection""" - # url('admin_settings/labs', method={'POST'}) + _ = self.request.translate + c = self.load_default_context() c.active = 'labs' application_form = LabsSettingsForm()() try: - form_result = application_form.to_python(dict(request.POST)) + 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') - return htmlfill.render( - render('admin/settings/settings.mako'), + 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', + encoding="UTF-8", force_defaults=False ) + return Response(html) try: session = Session() @@ -580,39 +725,17 @@ class SettingsController(BaseController): Session().commit() SettingsModel().invalidate_settings_cache() h.flash(_('Updated Labs settings'), category='success') - return redirect(url('admin_settings_labs')) + raise HTTPFound(h.route_path('admin_settings_labs')) - return htmlfill.render( - render('admin/settings/settings.mako'), + 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) - - @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 + encoding="UTF-8", + force_defaults=False + ) + return Response(html) # :param key: name of the setting including the 'rhodecode_' prefix diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py index eaf14076..0e61f22d 100644 --- 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 index a917aefe..00000000 --- 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/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js index 18c71aa3..4ad20881 100644 --- 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 index 1d6536f4..35d3fcf5 100644 --- 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 index 3b520dc0..075517f1 100644 --- 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 index d5290b89..ce18c4f9 100644 --- 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 index 900afd52..cd05ea90 100644 --- a/rhodecode/templates/admin/repos/repo_add_base.mako +++ b/rhodecode/templates/admin/repos/repo_add_base.mako @@ -33,7 +33,7 @@ ${h.secure_form(h.route_path('repo_create'), request=request)} 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 index 4fa3070d..1b3751d0 100644 --- 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 index 8e5a60d2..6069d416 100644 --- 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 index 3b039789..d395be03 100644 --- 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 index 742f088c..9493ff5f 100644 --- 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 index 414883cf..946d13dd 100644 --- 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 index a582f39a..2108bebe 100644 --- 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 index 8de74be3..4f37f110 100644 --- 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 @@ ${h.end_form()}