##// END OF EJS Templates
fix(svn-configs): cleanup code and fixed generate config on repo settings page which should not be visible
super-admin -
r5395:c07fca24 default
parent child Browse files
Show More
@@ -1,711 +1,708 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19
19
20 import logging
20 import logging
21 import collections
21 import collections
22
22
23 import datetime
23 import datetime
24 import formencode
24 import formencode
25 import formencode.htmlfill
25 import formencode.htmlfill
26
26
27 import rhodecode
27 import rhodecode
28
28
29 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
29 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
30 from pyramid.renderers import render
30 from pyramid.renderers import render
31 from pyramid.response import Response
31 from pyramid.response import Response
32
32
33 from rhodecode.apps._base import BaseAppView
33 from rhodecode.apps._base import BaseAppView
34 from rhodecode.apps._base.navigation import navigation_list
34 from rhodecode.apps._base.navigation import navigation_list
35 from rhodecode.apps.svn_support.config_keys import generate_config
35 from rhodecode.apps.svn_support import config_keys
36 from rhodecode.lib import helpers as h
36 from rhodecode.lib import helpers as h
37 from rhodecode.lib.auth import (
37 from rhodecode.lib.auth import (
38 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
38 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
39 from rhodecode.lib.celerylib import tasks, run_task
39 from rhodecode.lib.celerylib import tasks, run_task
40 from rhodecode.lib.str_utils import safe_str
40 from rhodecode.lib.str_utils import safe_str
41 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_repo_store_path
41 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_repo_store_path
42 from rhodecode.lib.utils2 import str2bool, AttributeDict
42 from rhodecode.lib.utils2 import str2bool, AttributeDict
43 from rhodecode.lib.index import searcher_from_config
43 from rhodecode.lib.index import searcher_from_config
44
44
45 from rhodecode.model.db import RhodeCodeUi, Repository
45 from rhodecode.model.db import RhodeCodeUi, Repository
46 from rhodecode.model.forms import (ApplicationSettingsForm,
46 from rhodecode.model.forms import (ApplicationSettingsForm,
47 ApplicationUiSettingsForm, ApplicationVisualisationForm,
47 ApplicationUiSettingsForm, ApplicationVisualisationForm,
48 LabsSettingsForm, IssueTrackerPatternsForm)
48 LabsSettingsForm, IssueTrackerPatternsForm)
49 from rhodecode.model.permission import PermissionModel
49 from rhodecode.model.permission import PermissionModel
50 from rhodecode.model.repo_group import RepoGroupModel
50 from rhodecode.model.repo_group import RepoGroupModel
51
51
52 from rhodecode.model.scm import ScmModel
52 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.notification import EmailNotificationModel
53 from rhodecode.model.notification import EmailNotificationModel
54 from rhodecode.model.meta import Session
54 from rhodecode.model.meta import Session
55 from rhodecode.model.settings import (
55 from rhodecode.model.settings import (
56 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
56 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
57 SettingsModel)
57 SettingsModel)
58
58
59
59
60 log = logging.getLogger(__name__)
60 log = logging.getLogger(__name__)
61
61
62
62
63 class AdminSettingsView(BaseAppView):
63 class AdminSettingsView(BaseAppView):
64
64
65 def load_default_context(self):
65 def load_default_context(self):
66 c = self._get_local_tmpl_context()
66 c = self._get_local_tmpl_context()
67 c.labs_active = str2bool(
67 c.labs_active = str2bool(
68 rhodecode.CONFIG.get('labs_settings_active', 'true'))
68 rhodecode.CONFIG.get('labs_settings_active', 'true'))
69 c.navlist = navigation_list(self.request)
69 c.navlist = navigation_list(self.request)
70 return c
70 return c
71
71
72 @classmethod
72 @classmethod
73 def _get_ui_settings(cls):
73 def _get_ui_settings(cls):
74 ret = RhodeCodeUi.query().all()
74 ret = RhodeCodeUi.query().all()
75
75
76 if not ret:
76 if not ret:
77 raise Exception('Could not get application ui settings !')
77 raise Exception('Could not get application ui settings !')
78 settings = {}
78 settings = {}
79 for each in ret:
79 for each in ret:
80 k = each.ui_key
80 k = each.ui_key
81 v = each.ui_value
81 v = each.ui_value
82 if k == '/':
82 if k == '/':
83 k = 'root_path'
83 k = 'root_path'
84
84
85 if k in ['push_ssl', 'publish', 'enabled']:
85 if k in ['push_ssl', 'publish', 'enabled']:
86 v = str2bool(v)
86 v = str2bool(v)
87
87
88 if k.find('.') != -1:
88 if k.find('.') != -1:
89 k = k.replace('.', '_')
89 k = k.replace('.', '_')
90
90
91 if each.ui_section in ['hooks', 'extensions']:
91 if each.ui_section in ['hooks', 'extensions']:
92 v = each.ui_active
92 v = each.ui_active
93
93
94 settings[each.ui_section + '_' + k] = v
94 settings[each.ui_section + '_' + k] = v
95 return settings
95 return settings
96
96
97 @classmethod
97 @classmethod
98 def _form_defaults(cls):
98 def _form_defaults(cls):
99 defaults = SettingsModel().get_all_settings()
99 defaults = SettingsModel().get_all_settings()
100 defaults.update(cls._get_ui_settings())
100 defaults.update(cls._get_ui_settings())
101
101
102 defaults.update({
102 defaults.update({
103 'new_svn_branch': '',
103 'new_svn_branch': '',
104 'new_svn_tag': '',
104 'new_svn_tag': '',
105 })
105 })
106 return defaults
106 return defaults
107
107
108 @LoginRequired()
108 @LoginRequired()
109 @HasPermissionAllDecorator('hg.admin')
109 @HasPermissionAllDecorator('hg.admin')
110 def settings_vcs(self):
110 def settings_vcs(self):
111 c = self.load_default_context()
111 c = self.load_default_context()
112 c.active = 'vcs'
112 c.active = 'vcs'
113 model = VcsSettingsModel()
113 model = VcsSettingsModel()
114 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
114 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
115 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
115 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
116
116 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
117 settings = self.request.registry.settings
117 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
118 c.svn_generate_config = settings[generate_config]
119 c.svn_config_path = rhodecode.ConfigGet().get_str('svn.proxy.config_file_path')
120 defaults = self._form_defaults()
118 defaults = self._form_defaults()
121
119
122 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
120 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
123
121
124 data = render('rhodecode:templates/admin/settings/settings.mako',
122 data = render('rhodecode:templates/admin/settings/settings.mako',
125 self._get_template_context(c), self.request)
123 self._get_template_context(c), self.request)
126 html = formencode.htmlfill.render(
124 html = formencode.htmlfill.render(
127 data,
125 data,
128 defaults=defaults,
126 defaults=defaults,
129 encoding="UTF-8",
127 encoding="UTF-8",
130 force_defaults=False
128 force_defaults=False
131 )
129 )
132 return Response(html)
130 return Response(html)
133
131
134 @LoginRequired()
132 @LoginRequired()
135 @HasPermissionAllDecorator('hg.admin')
133 @HasPermissionAllDecorator('hg.admin')
136 @CSRFRequired()
134 @CSRFRequired()
137 def settings_vcs_update(self):
135 def settings_vcs_update(self):
138 _ = self.request.translate
136 _ = self.request.translate
139 c = self.load_default_context()
137 c = self.load_default_context()
140 c.active = 'vcs'
138 c.active = 'vcs'
141
139
142 model = VcsSettingsModel()
140 model = VcsSettingsModel()
143 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
141 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
144 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
142 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
145
143
146 settings = self.request.registry.settings
144 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
147 c.svn_generate_config = settings[generate_config]
145 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
148 c.svn_config_path = rhodecode.ConfigGet().get_str('svn.proxy.config_file_path')
149 application_form = ApplicationUiSettingsForm(self.request.translate)()
146 application_form = ApplicationUiSettingsForm(self.request.translate)()
150
147
151 try:
148 try:
152 form_result = application_form.to_python(dict(self.request.POST))
149 form_result = application_form.to_python(dict(self.request.POST))
153 except formencode.Invalid as errors:
150 except formencode.Invalid as errors:
154 h.flash(
151 h.flash(
155 _("Some form inputs contain invalid data."),
152 _("Some form inputs contain invalid data."),
156 category='error')
153 category='error')
157 data = render('rhodecode:templates/admin/settings/settings.mako',
154 data = render('rhodecode:templates/admin/settings/settings.mako',
158 self._get_template_context(c), self.request)
155 self._get_template_context(c), self.request)
159 html = formencode.htmlfill.render(
156 html = formencode.htmlfill.render(
160 data,
157 data,
161 defaults=errors.value,
158 defaults=errors.value,
162 errors=errors.unpack_errors() or {},
159 errors=errors.unpack_errors() or {},
163 prefix_error=False,
160 prefix_error=False,
164 encoding="UTF-8",
161 encoding="UTF-8",
165 force_defaults=False
162 force_defaults=False
166 )
163 )
167 return Response(html)
164 return Response(html)
168
165
169 try:
166 try:
170 model.update_global_ssl_setting(form_result['web_push_ssl'])
167 model.update_global_ssl_setting(form_result['web_push_ssl'])
171 model.update_global_hook_settings(form_result)
168 model.update_global_hook_settings(form_result)
172
169
173 model.create_or_update_global_svn_settings(form_result)
170 model.create_or_update_global_svn_settings(form_result)
174 model.create_or_update_global_hg_settings(form_result)
171 model.create_or_update_global_hg_settings(form_result)
175 model.create_or_update_global_git_settings(form_result)
172 model.create_or_update_global_git_settings(form_result)
176 model.create_or_update_global_pr_settings(form_result)
173 model.create_or_update_global_pr_settings(form_result)
177 except Exception:
174 except Exception:
178 log.exception("Exception while updating settings")
175 log.exception("Exception while updating settings")
179 h.flash(_('Error occurred during updating '
176 h.flash(_('Error occurred during updating '
180 'application settings'), category='error')
177 'application settings'), category='error')
181 else:
178 else:
182 Session().commit()
179 Session().commit()
183 h.flash(_('Updated VCS settings'), category='success')
180 h.flash(_('Updated VCS settings'), category='success')
184 raise HTTPFound(h.route_path('admin_settings_vcs'))
181 raise HTTPFound(h.route_path('admin_settings_vcs'))
185
182
186 data = render('rhodecode:templates/admin/settings/settings.mako',
183 data = render('rhodecode:templates/admin/settings/settings.mako',
187 self._get_template_context(c), self.request)
184 self._get_template_context(c), self.request)
188 html = formencode.htmlfill.render(
185 html = formencode.htmlfill.render(
189 data,
186 data,
190 defaults=self._form_defaults(),
187 defaults=self._form_defaults(),
191 encoding="UTF-8",
188 encoding="UTF-8",
192 force_defaults=False
189 force_defaults=False
193 )
190 )
194 return Response(html)
191 return Response(html)
195
192
196 @LoginRequired()
193 @LoginRequired()
197 @HasPermissionAllDecorator('hg.admin')
194 @HasPermissionAllDecorator('hg.admin')
198 @CSRFRequired()
195 @CSRFRequired()
199 def settings_vcs_delete_svn_pattern(self):
196 def settings_vcs_delete_svn_pattern(self):
200 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
197 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
201 model = VcsSettingsModel()
198 model = VcsSettingsModel()
202 try:
199 try:
203 model.delete_global_svn_pattern(delete_pattern_id)
200 model.delete_global_svn_pattern(delete_pattern_id)
204 except SettingNotFound:
201 except SettingNotFound:
205 log.exception(
202 log.exception(
206 'Failed to delete svn_pattern with id %s', delete_pattern_id)
203 'Failed to delete svn_pattern with id %s', delete_pattern_id)
207 raise HTTPNotFound()
204 raise HTTPNotFound()
208
205
209 Session().commit()
206 Session().commit()
210 return True
207 return True
211
208
212 @LoginRequired()
209 @LoginRequired()
213 @HasPermissionAllDecorator('hg.admin')
210 @HasPermissionAllDecorator('hg.admin')
214 def settings_mapping(self):
211 def settings_mapping(self):
215 c = self.load_default_context()
212 c = self.load_default_context()
216 c.active = 'mapping'
213 c.active = 'mapping'
217 c.storage_path = get_rhodecode_repo_store_path()
214 c.storage_path = get_rhodecode_repo_store_path()
218 data = render('rhodecode:templates/admin/settings/settings.mako',
215 data = render('rhodecode:templates/admin/settings/settings.mako',
219 self._get_template_context(c), self.request)
216 self._get_template_context(c), self.request)
220 html = formencode.htmlfill.render(
217 html = formencode.htmlfill.render(
221 data,
218 data,
222 defaults=self._form_defaults(),
219 defaults=self._form_defaults(),
223 encoding="UTF-8",
220 encoding="UTF-8",
224 force_defaults=False
221 force_defaults=False
225 )
222 )
226 return Response(html)
223 return Response(html)
227
224
228 @LoginRequired()
225 @LoginRequired()
229 @HasPermissionAllDecorator('hg.admin')
226 @HasPermissionAllDecorator('hg.admin')
230 @CSRFRequired()
227 @CSRFRequired()
231 def settings_mapping_update(self):
228 def settings_mapping_update(self):
232 _ = self.request.translate
229 _ = self.request.translate
233 c = self.load_default_context()
230 c = self.load_default_context()
234 c.active = 'mapping'
231 c.active = 'mapping'
235 rm_obsolete = self.request.POST.get('destroy', False)
232 rm_obsolete = self.request.POST.get('destroy', False)
236 invalidate_cache = self.request.POST.get('invalidate', False)
233 invalidate_cache = self.request.POST.get('invalidate', False)
237 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
234 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
238
235
239 if invalidate_cache:
236 if invalidate_cache:
240 log.debug('invalidating all repositories cache')
237 log.debug('invalidating all repositories cache')
241 for repo in Repository.get_all():
238 for repo in Repository.get_all():
242 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
239 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
243
240
244 filesystem_repos = ScmModel().repo_scan()
241 filesystem_repos = ScmModel().repo_scan()
245 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, force_hooks_rebuild=True)
242 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, force_hooks_rebuild=True)
246 PermissionModel().trigger_permission_flush()
243 PermissionModel().trigger_permission_flush()
247
244
248 def _repr(rm_repo):
245 def _repr(rm_repo):
249 return ', '.join(map(safe_str, rm_repo)) or '-'
246 return ', '.join(map(safe_str, rm_repo)) or '-'
250
247
251 h.flash(_('Repositories successfully '
248 h.flash(_('Repositories successfully '
252 'rescanned added: %s ; removed: %s') %
249 'rescanned added: %s ; removed: %s') %
253 (_repr(added), _repr(removed)),
250 (_repr(added), _repr(removed)),
254 category='success')
251 category='success')
255 raise HTTPFound(h.route_path('admin_settings_mapping'))
252 raise HTTPFound(h.route_path('admin_settings_mapping'))
256
253
257 @LoginRequired()
254 @LoginRequired()
258 @HasPermissionAllDecorator('hg.admin')
255 @HasPermissionAllDecorator('hg.admin')
259 def settings_global(self):
256 def settings_global(self):
260 c = self.load_default_context()
257 c = self.load_default_context()
261 c.active = 'global'
258 c.active = 'global'
262 c.personal_repo_group_default_pattern = RepoGroupModel()\
259 c.personal_repo_group_default_pattern = RepoGroupModel()\
263 .get_personal_group_name_pattern()
260 .get_personal_group_name_pattern()
264
261
265 data = render('rhodecode:templates/admin/settings/settings.mako',
262 data = render('rhodecode:templates/admin/settings/settings.mako',
266 self._get_template_context(c), self.request)
263 self._get_template_context(c), self.request)
267 html = formencode.htmlfill.render(
264 html = formencode.htmlfill.render(
268 data,
265 data,
269 defaults=self._form_defaults(),
266 defaults=self._form_defaults(),
270 encoding="UTF-8",
267 encoding="UTF-8",
271 force_defaults=False
268 force_defaults=False
272 )
269 )
273 return Response(html)
270 return Response(html)
274
271
275 @LoginRequired()
272 @LoginRequired()
276 @HasPermissionAllDecorator('hg.admin')
273 @HasPermissionAllDecorator('hg.admin')
277 @CSRFRequired()
274 @CSRFRequired()
278 def settings_global_update(self):
275 def settings_global_update(self):
279 _ = self.request.translate
276 _ = self.request.translate
280 c = self.load_default_context()
277 c = self.load_default_context()
281 c.active = 'global'
278 c.active = 'global'
282 c.personal_repo_group_default_pattern = RepoGroupModel()\
279 c.personal_repo_group_default_pattern = RepoGroupModel()\
283 .get_personal_group_name_pattern()
280 .get_personal_group_name_pattern()
284 application_form = ApplicationSettingsForm(self.request.translate)()
281 application_form = ApplicationSettingsForm(self.request.translate)()
285 try:
282 try:
286 form_result = application_form.to_python(dict(self.request.POST))
283 form_result = application_form.to_python(dict(self.request.POST))
287 except formencode.Invalid as errors:
284 except formencode.Invalid as errors:
288 h.flash(
285 h.flash(
289 _("Some form inputs contain invalid data."),
286 _("Some form inputs contain invalid data."),
290 category='error')
287 category='error')
291 data = render('rhodecode:templates/admin/settings/settings.mako',
288 data = render('rhodecode:templates/admin/settings/settings.mako',
292 self._get_template_context(c), self.request)
289 self._get_template_context(c), self.request)
293 html = formencode.htmlfill.render(
290 html = formencode.htmlfill.render(
294 data,
291 data,
295 defaults=errors.value,
292 defaults=errors.value,
296 errors=errors.unpack_errors() or {},
293 errors=errors.unpack_errors() or {},
297 prefix_error=False,
294 prefix_error=False,
298 encoding="UTF-8",
295 encoding="UTF-8",
299 force_defaults=False
296 force_defaults=False
300 )
297 )
301 return Response(html)
298 return Response(html)
302
299
303 settings = [
300 settings = [
304 ('title', 'rhodecode_title', 'unicode'),
301 ('title', 'rhodecode_title', 'unicode'),
305 ('realm', 'rhodecode_realm', 'unicode'),
302 ('realm', 'rhodecode_realm', 'unicode'),
306 ('pre_code', 'rhodecode_pre_code', 'unicode'),
303 ('pre_code', 'rhodecode_pre_code', 'unicode'),
307 ('post_code', 'rhodecode_post_code', 'unicode'),
304 ('post_code', 'rhodecode_post_code', 'unicode'),
308 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
305 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
309 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
306 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
310 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
307 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
311 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
308 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
312 ]
309 ]
313
310
314 try:
311 try:
315 for setting, form_key, type_ in settings:
312 for setting, form_key, type_ in settings:
316 sett = SettingsModel().create_or_update_setting(
313 sett = SettingsModel().create_or_update_setting(
317 setting, form_result[form_key], type_)
314 setting, form_result[form_key], type_)
318 Session().add(sett)
315 Session().add(sett)
319
316
320 Session().commit()
317 Session().commit()
321 SettingsModel().invalidate_settings_cache()
318 SettingsModel().invalidate_settings_cache()
322 h.flash(_('Updated application settings'), category='success')
319 h.flash(_('Updated application settings'), category='success')
323 except Exception:
320 except Exception:
324 log.exception("Exception while updating application settings")
321 log.exception("Exception while updating application settings")
325 h.flash(
322 h.flash(
326 _('Error occurred during updating application settings'),
323 _('Error occurred during updating application settings'),
327 category='error')
324 category='error')
328
325
329 raise HTTPFound(h.route_path('admin_settings_global'))
326 raise HTTPFound(h.route_path('admin_settings_global'))
330
327
331 @LoginRequired()
328 @LoginRequired()
332 @HasPermissionAllDecorator('hg.admin')
329 @HasPermissionAllDecorator('hg.admin')
333 def settings_visual(self):
330 def settings_visual(self):
334 c = self.load_default_context()
331 c = self.load_default_context()
335 c.active = 'visual'
332 c.active = 'visual'
336
333
337 data = render('rhodecode:templates/admin/settings/settings.mako',
334 data = render('rhodecode:templates/admin/settings/settings.mako',
338 self._get_template_context(c), self.request)
335 self._get_template_context(c), self.request)
339 html = formencode.htmlfill.render(
336 html = formencode.htmlfill.render(
340 data,
337 data,
341 defaults=self._form_defaults(),
338 defaults=self._form_defaults(),
342 encoding="UTF-8",
339 encoding="UTF-8",
343 force_defaults=False
340 force_defaults=False
344 )
341 )
345 return Response(html)
342 return Response(html)
346
343
347 @LoginRequired()
344 @LoginRequired()
348 @HasPermissionAllDecorator('hg.admin')
345 @HasPermissionAllDecorator('hg.admin')
349 @CSRFRequired()
346 @CSRFRequired()
350 def settings_visual_update(self):
347 def settings_visual_update(self):
351 _ = self.request.translate
348 _ = self.request.translate
352 c = self.load_default_context()
349 c = self.load_default_context()
353 c.active = 'visual'
350 c.active = 'visual'
354 application_form = ApplicationVisualisationForm(self.request.translate)()
351 application_form = ApplicationVisualisationForm(self.request.translate)()
355 try:
352 try:
356 form_result = application_form.to_python(dict(self.request.POST))
353 form_result = application_form.to_python(dict(self.request.POST))
357 except formencode.Invalid as errors:
354 except formencode.Invalid as errors:
358 h.flash(
355 h.flash(
359 _("Some form inputs contain invalid data."),
356 _("Some form inputs contain invalid data."),
360 category='error')
357 category='error')
361 data = render('rhodecode:templates/admin/settings/settings.mako',
358 data = render('rhodecode:templates/admin/settings/settings.mako',
362 self._get_template_context(c), self.request)
359 self._get_template_context(c), self.request)
363 html = formencode.htmlfill.render(
360 html = formencode.htmlfill.render(
364 data,
361 data,
365 defaults=errors.value,
362 defaults=errors.value,
366 errors=errors.unpack_errors() or {},
363 errors=errors.unpack_errors() or {},
367 prefix_error=False,
364 prefix_error=False,
368 encoding="UTF-8",
365 encoding="UTF-8",
369 force_defaults=False
366 force_defaults=False
370 )
367 )
371 return Response(html)
368 return Response(html)
372
369
373 try:
370 try:
374 settings = [
371 settings = [
375 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
372 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
376 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
373 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
377 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
374 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
378 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
375 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
379 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
376 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
380 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
377 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
381 ('show_version', 'rhodecode_show_version', 'bool'),
378 ('show_version', 'rhodecode_show_version', 'bool'),
382 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
379 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
383 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
380 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
384 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
381 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
385 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
382 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
386 ('clone_uri_id_tmpl', 'rhodecode_clone_uri_id_tmpl', 'unicode'),
383 ('clone_uri_id_tmpl', 'rhodecode_clone_uri_id_tmpl', 'unicode'),
387 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
384 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
388 ('support_url', 'rhodecode_support_url', 'unicode'),
385 ('support_url', 'rhodecode_support_url', 'unicode'),
389 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
386 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
390 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
387 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
391 ]
388 ]
392 for setting, form_key, type_ in settings:
389 for setting, form_key, type_ in settings:
393 sett = SettingsModel().create_or_update_setting(
390 sett = SettingsModel().create_or_update_setting(
394 setting, form_result[form_key], type_)
391 setting, form_result[form_key], type_)
395 Session().add(sett)
392 Session().add(sett)
396
393
397 Session().commit()
394 Session().commit()
398 SettingsModel().invalidate_settings_cache()
395 SettingsModel().invalidate_settings_cache()
399 h.flash(_('Updated visualisation settings'), category='success')
396 h.flash(_('Updated visualisation settings'), category='success')
400 except Exception:
397 except Exception:
401 log.exception("Exception updating visualization settings")
398 log.exception("Exception updating visualization settings")
402 h.flash(_('Error occurred during updating '
399 h.flash(_('Error occurred during updating '
403 'visualisation settings'),
400 'visualisation settings'),
404 category='error')
401 category='error')
405
402
406 raise HTTPFound(h.route_path('admin_settings_visual'))
403 raise HTTPFound(h.route_path('admin_settings_visual'))
407
404
408 @LoginRequired()
405 @LoginRequired()
409 @HasPermissionAllDecorator('hg.admin')
406 @HasPermissionAllDecorator('hg.admin')
410 def settings_issuetracker(self):
407 def settings_issuetracker(self):
411 c = self.load_default_context()
408 c = self.load_default_context()
412 c.active = 'issuetracker'
409 c.active = 'issuetracker'
413 defaults = c.rc_config
410 defaults = c.rc_config
414
411
415 entry_key = 'rhodecode_issuetracker_pat_'
412 entry_key = 'rhodecode_issuetracker_pat_'
416
413
417 c.issuetracker_entries = {}
414 c.issuetracker_entries = {}
418 for k, v in defaults.items():
415 for k, v in defaults.items():
419 if k.startswith(entry_key):
416 if k.startswith(entry_key):
420 uid = k[len(entry_key):]
417 uid = k[len(entry_key):]
421 c.issuetracker_entries[uid] = None
418 c.issuetracker_entries[uid] = None
422
419
423 for uid in c.issuetracker_entries:
420 for uid in c.issuetracker_entries:
424 c.issuetracker_entries[uid] = AttributeDict({
421 c.issuetracker_entries[uid] = AttributeDict({
425 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
422 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
426 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
423 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
427 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
424 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
428 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
425 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
429 })
426 })
430
427
431 return self._get_template_context(c)
428 return self._get_template_context(c)
432
429
433 @LoginRequired()
430 @LoginRequired()
434 @HasPermissionAllDecorator('hg.admin')
431 @HasPermissionAllDecorator('hg.admin')
435 @CSRFRequired()
432 @CSRFRequired()
436 def settings_issuetracker_test(self):
433 def settings_issuetracker_test(self):
437 error_container = []
434 error_container = []
438
435
439 urlified_commit = h.urlify_commit_message(
436 urlified_commit = h.urlify_commit_message(
440 self.request.POST.get('test_text', ''),
437 self.request.POST.get('test_text', ''),
441 'repo_group/test_repo1', error_container=error_container)
438 'repo_group/test_repo1', error_container=error_container)
442 if error_container:
439 if error_container:
443 def converter(inp):
440 def converter(inp):
444 return h.html_escape(inp)
441 return h.html_escape(inp)
445
442
446 return 'ERRORS: ' + '\n'.join(map(converter, error_container))
443 return 'ERRORS: ' + '\n'.join(map(converter, error_container))
447
444
448 return urlified_commit
445 return urlified_commit
449
446
450 @LoginRequired()
447 @LoginRequired()
451 @HasPermissionAllDecorator('hg.admin')
448 @HasPermissionAllDecorator('hg.admin')
452 @CSRFRequired()
449 @CSRFRequired()
453 def settings_issuetracker_update(self):
450 def settings_issuetracker_update(self):
454 _ = self.request.translate
451 _ = self.request.translate
455 self.load_default_context()
452 self.load_default_context()
456 settings_model = IssueTrackerSettingsModel()
453 settings_model = IssueTrackerSettingsModel()
457
454
458 try:
455 try:
459 form = IssueTrackerPatternsForm(self.request.translate)()
456 form = IssueTrackerPatternsForm(self.request.translate)()
460 data = form.to_python(self.request.POST)
457 data = form.to_python(self.request.POST)
461 except formencode.Invalid as errors:
458 except formencode.Invalid as errors:
462 log.exception('Failed to add new pattern')
459 log.exception('Failed to add new pattern')
463 error = errors
460 error = errors
464 h.flash(_(f'Invalid issue tracker pattern: {error}'),
461 h.flash(_(f'Invalid issue tracker pattern: {error}'),
465 category='error')
462 category='error')
466 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
463 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
467
464
468 if data:
465 if data:
469 for uid in data.get('delete_patterns', []):
466 for uid in data.get('delete_patterns', []):
470 settings_model.delete_entries(uid)
467 settings_model.delete_entries(uid)
471
468
472 for pattern in data.get('patterns', []):
469 for pattern in data.get('patterns', []):
473 for setting, value, type_ in pattern:
470 for setting, value, type_ in pattern:
474 sett = settings_model.create_or_update_setting(
471 sett = settings_model.create_or_update_setting(
475 setting, value, type_)
472 setting, value, type_)
476 Session().add(sett)
473 Session().add(sett)
477
474
478 Session().commit()
475 Session().commit()
479
476
480 SettingsModel().invalidate_settings_cache()
477 SettingsModel().invalidate_settings_cache()
481 h.flash(_('Updated issue tracker entries'), category='success')
478 h.flash(_('Updated issue tracker entries'), category='success')
482 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
479 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
483
480
484 @LoginRequired()
481 @LoginRequired()
485 @HasPermissionAllDecorator('hg.admin')
482 @HasPermissionAllDecorator('hg.admin')
486 @CSRFRequired()
483 @CSRFRequired()
487 def settings_issuetracker_delete(self):
484 def settings_issuetracker_delete(self):
488 _ = self.request.translate
485 _ = self.request.translate
489 self.load_default_context()
486 self.load_default_context()
490 uid = self.request.POST.get('uid')
487 uid = self.request.POST.get('uid')
491 try:
488 try:
492 IssueTrackerSettingsModel().delete_entries(uid)
489 IssueTrackerSettingsModel().delete_entries(uid)
493 except Exception:
490 except Exception:
494 log.exception('Failed to delete issue tracker setting %s', uid)
491 log.exception('Failed to delete issue tracker setting %s', uid)
495 raise HTTPNotFound()
492 raise HTTPNotFound()
496
493
497 SettingsModel().invalidate_settings_cache()
494 SettingsModel().invalidate_settings_cache()
498 h.flash(_('Removed issue tracker entry.'), category='success')
495 h.flash(_('Removed issue tracker entry.'), category='success')
499
496
500 return {'deleted': uid}
497 return {'deleted': uid}
501
498
502 @LoginRequired()
499 @LoginRequired()
503 @HasPermissionAllDecorator('hg.admin')
500 @HasPermissionAllDecorator('hg.admin')
504 def settings_email(self):
501 def settings_email(self):
505 c = self.load_default_context()
502 c = self.load_default_context()
506 c.active = 'email'
503 c.active = 'email'
507 c.rhodecode_ini = rhodecode.CONFIG
504 c.rhodecode_ini = rhodecode.CONFIG
508
505
509 data = render('rhodecode:templates/admin/settings/settings.mako',
506 data = render('rhodecode:templates/admin/settings/settings.mako',
510 self._get_template_context(c), self.request)
507 self._get_template_context(c), self.request)
511 html = formencode.htmlfill.render(
508 html = formencode.htmlfill.render(
512 data,
509 data,
513 defaults=self._form_defaults(),
510 defaults=self._form_defaults(),
514 encoding="UTF-8",
511 encoding="UTF-8",
515 force_defaults=False
512 force_defaults=False
516 )
513 )
517 return Response(html)
514 return Response(html)
518
515
519 @LoginRequired()
516 @LoginRequired()
520 @HasPermissionAllDecorator('hg.admin')
517 @HasPermissionAllDecorator('hg.admin')
521 @CSRFRequired()
518 @CSRFRequired()
522 def settings_email_update(self):
519 def settings_email_update(self):
523 _ = self.request.translate
520 _ = self.request.translate
524 c = self.load_default_context()
521 c = self.load_default_context()
525 c.active = 'email'
522 c.active = 'email'
526
523
527 test_email = self.request.POST.get('test_email')
524 test_email = self.request.POST.get('test_email')
528
525
529 if not test_email:
526 if not test_email:
530 h.flash(_('Please enter email address'), category='error')
527 h.flash(_('Please enter email address'), category='error')
531 raise HTTPFound(h.route_path('admin_settings_email'))
528 raise HTTPFound(h.route_path('admin_settings_email'))
532
529
533 email_kwargs = {
530 email_kwargs = {
534 'date': datetime.datetime.now(),
531 'date': datetime.datetime.now(),
535 'user': self._rhodecode_db_user
532 'user': self._rhodecode_db_user
536 }
533 }
537
534
538 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
535 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
539 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
536 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
540
537
541 recipients = [test_email] if test_email else None
538 recipients = [test_email] if test_email else None
542
539
543 run_task(tasks.send_email, recipients, subject,
540 run_task(tasks.send_email, recipients, subject,
544 email_body_plaintext, email_body)
541 email_body_plaintext, email_body)
545
542
546 h.flash(_('Send email task created'), category='success')
543 h.flash(_('Send email task created'), category='success')
547 raise HTTPFound(h.route_path('admin_settings_email'))
544 raise HTTPFound(h.route_path('admin_settings_email'))
548
545
549 @LoginRequired()
546 @LoginRequired()
550 @HasPermissionAllDecorator('hg.admin')
547 @HasPermissionAllDecorator('hg.admin')
551 def settings_hooks(self):
548 def settings_hooks(self):
552 c = self.load_default_context()
549 c = self.load_default_context()
553 c.active = 'hooks'
550 c.active = 'hooks'
554
551
555 model = SettingsModel()
552 model = SettingsModel()
556 c.hooks = model.get_builtin_hooks()
553 c.hooks = model.get_builtin_hooks()
557 c.custom_hooks = model.get_custom_hooks()
554 c.custom_hooks = model.get_custom_hooks()
558
555
559 data = render('rhodecode:templates/admin/settings/settings.mako',
556 data = render('rhodecode:templates/admin/settings/settings.mako',
560 self._get_template_context(c), self.request)
557 self._get_template_context(c), self.request)
561 html = formencode.htmlfill.render(
558 html = formencode.htmlfill.render(
562 data,
559 data,
563 defaults=self._form_defaults(),
560 defaults=self._form_defaults(),
564 encoding="UTF-8",
561 encoding="UTF-8",
565 force_defaults=False
562 force_defaults=False
566 )
563 )
567 return Response(html)
564 return Response(html)
568
565
569 @LoginRequired()
566 @LoginRequired()
570 @HasPermissionAllDecorator('hg.admin')
567 @HasPermissionAllDecorator('hg.admin')
571 @CSRFRequired()
568 @CSRFRequired()
572 def settings_hooks_update(self):
569 def settings_hooks_update(self):
573 _ = self.request.translate
570 _ = self.request.translate
574 c = self.load_default_context()
571 c = self.load_default_context()
575 c.active = 'hooks'
572 c.active = 'hooks'
576 if c.visual.allow_custom_hooks_settings:
573 if c.visual.allow_custom_hooks_settings:
577 ui_key = self.request.POST.get('new_hook_ui_key')
574 ui_key = self.request.POST.get('new_hook_ui_key')
578 ui_value = self.request.POST.get('new_hook_ui_value')
575 ui_value = self.request.POST.get('new_hook_ui_value')
579
576
580 hook_id = self.request.POST.get('hook_id')
577 hook_id = self.request.POST.get('hook_id')
581 new_hook = False
578 new_hook = False
582
579
583 model = SettingsModel()
580 model = SettingsModel()
584 try:
581 try:
585 if ui_value and ui_key:
582 if ui_value and ui_key:
586 model.create_or_update_hook(ui_key, ui_value)
583 model.create_or_update_hook(ui_key, ui_value)
587 h.flash(_('Added new hook'), category='success')
584 h.flash(_('Added new hook'), category='success')
588 new_hook = True
585 new_hook = True
589 elif hook_id:
586 elif hook_id:
590 RhodeCodeUi.delete(hook_id)
587 RhodeCodeUi.delete(hook_id)
591 Session().commit()
588 Session().commit()
592
589
593 # check for edits
590 # check for edits
594 update = False
591 update = False
595 _d = self.request.POST.dict_of_lists()
592 _d = self.request.POST.dict_of_lists()
596 for k, v in zip(_d.get('hook_ui_key', []),
593 for k, v in zip(_d.get('hook_ui_key', []),
597 _d.get('hook_ui_value_new', [])):
594 _d.get('hook_ui_value_new', [])):
598 model.create_or_update_hook(k, v)
595 model.create_or_update_hook(k, v)
599 update = True
596 update = True
600
597
601 if update and not new_hook:
598 if update and not new_hook:
602 h.flash(_('Updated hooks'), category='success')
599 h.flash(_('Updated hooks'), category='success')
603 Session().commit()
600 Session().commit()
604 except Exception:
601 except Exception:
605 log.exception("Exception during hook creation")
602 log.exception("Exception during hook creation")
606 h.flash(_('Error occurred during hook creation'),
603 h.flash(_('Error occurred during hook creation'),
607 category='error')
604 category='error')
608
605
609 raise HTTPFound(h.route_path('admin_settings_hooks'))
606 raise HTTPFound(h.route_path('admin_settings_hooks'))
610
607
611 @LoginRequired()
608 @LoginRequired()
612 @HasPermissionAllDecorator('hg.admin')
609 @HasPermissionAllDecorator('hg.admin')
613 def settings_search(self):
610 def settings_search(self):
614 c = self.load_default_context()
611 c = self.load_default_context()
615 c.active = 'search'
612 c.active = 'search'
616
613
617 c.searcher = searcher_from_config(self.request.registry.settings)
614 c.searcher = searcher_from_config(self.request.registry.settings)
618 c.statistics = c.searcher.statistics(self.request.translate)
615 c.statistics = c.searcher.statistics(self.request.translate)
619
616
620 return self._get_template_context(c)
617 return self._get_template_context(c)
621
618
622 @LoginRequired()
619 @LoginRequired()
623 @HasPermissionAllDecorator('hg.admin')
620 @HasPermissionAllDecorator('hg.admin')
624 def settings_labs(self):
621 def settings_labs(self):
625 c = self.load_default_context()
622 c = self.load_default_context()
626 if not c.labs_active:
623 if not c.labs_active:
627 raise HTTPFound(h.route_path('admin_settings'))
624 raise HTTPFound(h.route_path('admin_settings'))
628
625
629 c.active = 'labs'
626 c.active = 'labs'
630 c.lab_settings = _LAB_SETTINGS
627 c.lab_settings = _LAB_SETTINGS
631
628
632 data = render('rhodecode:templates/admin/settings/settings.mako',
629 data = render('rhodecode:templates/admin/settings/settings.mako',
633 self._get_template_context(c), self.request)
630 self._get_template_context(c), self.request)
634 html = formencode.htmlfill.render(
631 html = formencode.htmlfill.render(
635 data,
632 data,
636 defaults=self._form_defaults(),
633 defaults=self._form_defaults(),
637 encoding="UTF-8",
634 encoding="UTF-8",
638 force_defaults=False
635 force_defaults=False
639 )
636 )
640 return Response(html)
637 return Response(html)
641
638
642 @LoginRequired()
639 @LoginRequired()
643 @HasPermissionAllDecorator('hg.admin')
640 @HasPermissionAllDecorator('hg.admin')
644 @CSRFRequired()
641 @CSRFRequired()
645 def settings_labs_update(self):
642 def settings_labs_update(self):
646 _ = self.request.translate
643 _ = self.request.translate
647 c = self.load_default_context()
644 c = self.load_default_context()
648 c.active = 'labs'
645 c.active = 'labs'
649
646
650 application_form = LabsSettingsForm(self.request.translate)()
647 application_form = LabsSettingsForm(self.request.translate)()
651 try:
648 try:
652 form_result = application_form.to_python(dict(self.request.POST))
649 form_result = application_form.to_python(dict(self.request.POST))
653 except formencode.Invalid as errors:
650 except formencode.Invalid as errors:
654 h.flash(
651 h.flash(
655 _("Some form inputs contain invalid data."),
652 _("Some form inputs contain invalid data."),
656 category='error')
653 category='error')
657 data = render('rhodecode:templates/admin/settings/settings.mako',
654 data = render('rhodecode:templates/admin/settings/settings.mako',
658 self._get_template_context(c), self.request)
655 self._get_template_context(c), self.request)
659 html = formencode.htmlfill.render(
656 html = formencode.htmlfill.render(
660 data,
657 data,
661 defaults=errors.value,
658 defaults=errors.value,
662 errors=errors.unpack_errors() or {},
659 errors=errors.unpack_errors() or {},
663 prefix_error=False,
660 prefix_error=False,
664 encoding="UTF-8",
661 encoding="UTF-8",
665 force_defaults=False
662 force_defaults=False
666 )
663 )
667 return Response(html)
664 return Response(html)
668
665
669 try:
666 try:
670 session = Session()
667 session = Session()
671 for setting in _LAB_SETTINGS:
668 for setting in _LAB_SETTINGS:
672 setting_name = setting.key[len('rhodecode_'):]
669 setting_name = setting.key[len('rhodecode_'):]
673 sett = SettingsModel().create_or_update_setting(
670 sett = SettingsModel().create_or_update_setting(
674 setting_name, form_result[setting.key], setting.type)
671 setting_name, form_result[setting.key], setting.type)
675 session.add(sett)
672 session.add(sett)
676
673
677 except Exception:
674 except Exception:
678 log.exception('Exception while updating lab settings')
675 log.exception('Exception while updating lab settings')
679 h.flash(_('Error occurred during updating labs settings'),
676 h.flash(_('Error occurred during updating labs settings'),
680 category='error')
677 category='error')
681 else:
678 else:
682 Session().commit()
679 Session().commit()
683 SettingsModel().invalidate_settings_cache()
680 SettingsModel().invalidate_settings_cache()
684 h.flash(_('Updated Labs settings'), category='success')
681 h.flash(_('Updated Labs settings'), category='success')
685 raise HTTPFound(h.route_path('admin_settings_labs'))
682 raise HTTPFound(h.route_path('admin_settings_labs'))
686
683
687 data = render('rhodecode:templates/admin/settings/settings.mako',
684 data = render('rhodecode:templates/admin/settings/settings.mako',
688 self._get_template_context(c), self.request)
685 self._get_template_context(c), self.request)
689 html = formencode.htmlfill.render(
686 html = formencode.htmlfill.render(
690 data,
687 data,
691 defaults=self._form_defaults(),
688 defaults=self._form_defaults(),
692 encoding="UTF-8",
689 encoding="UTF-8",
693 force_defaults=False
690 force_defaults=False
694 )
691 )
695 return Response(html)
692 return Response(html)
696
693
697
694
698 # :param key: name of the setting including the 'rhodecode_' prefix
695 # :param key: name of the setting including the 'rhodecode_' prefix
699 # :param type: the RhodeCodeSetting type to use.
696 # :param type: the RhodeCodeSetting type to use.
700 # :param group: the i18ned group in which we should dispaly this setting
697 # :param group: the i18ned group in which we should dispaly this setting
701 # :param label: the i18ned label we should display for this setting
698 # :param label: the i18ned label we should display for this setting
702 # :param help: the i18ned help we should dispaly for this setting
699 # :param help: the i18ned help we should dispaly for this setting
703 LabSetting = collections.namedtuple(
700 LabSetting = collections.namedtuple(
704 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
701 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
705
702
706
703
707 # This list has to be kept in sync with the form
704 # This list has to be kept in sync with the form
708 # rhodecode.model.forms.LabsSettingsForm.
705 # rhodecode.model.forms.LabsSettingsForm.
709 _LAB_SETTINGS = [
706 _LAB_SETTINGS = [
710
707
711 ]
708 ]
@@ -1,157 +1,162 b''
1 # Copyright (C) 2017-2023 RhodeCode GmbH
1 # Copyright (C) 2017-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20
20
21 import formencode
21 import formencode
22 import formencode.htmlfill
22 import formencode.htmlfill
23 from pyramid.httpexceptions import HTTPFound, HTTPBadRequest
23 from pyramid.httpexceptions import HTTPFound, HTTPBadRequest
24 from pyramid.response import Response
24 from pyramid.response import Response
25 from pyramid.renderers import render
25 from pyramid.renderers import render
26
26
27 import rhodecode
27 from rhodecode.apps._base import RepoAppView
28 from rhodecode.apps._base import RepoAppView
29 from rhodecode.apps.svn_support import config_keys
28 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
29 from rhodecode.lib.auth import (
31 from rhodecode.lib.auth import (
30 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
32 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
31 from rhodecode.model.forms import RepoVcsSettingsForm
33 from rhodecode.model.forms import RepoVcsSettingsForm
32 from rhodecode.model.meta import Session
34 from rhodecode.model.meta import Session
33 from rhodecode.model.settings import VcsSettingsModel, SettingNotFound
35 from rhodecode.model.settings import VcsSettingsModel, SettingNotFound
34
36
35 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
36
38
37
39
38 class RepoSettingsVcsView(RepoAppView):
40 class RepoSettingsVcsView(RepoAppView):
39 def load_default_context(self):
41 def load_default_context(self):
40 c = self._get_local_tmpl_context()
42 c = self._get_local_tmpl_context()
41
42
43 return c
43 return c
44
44
45 def _vcs_form_defaults(self, repo_name):
45 def _vcs_form_defaults(self, repo_name):
46 model = VcsSettingsModel(repo=repo_name)
46 model = VcsSettingsModel(repo=repo_name)
47 global_defaults = model.get_global_settings()
47 global_defaults = model.get_global_settings()
48
48
49 repo_defaults = {}
49 repo_defaults = {}
50 repo_defaults.update(global_defaults)
50 repo_defaults.update(global_defaults)
51 repo_defaults.update(model.get_repo_settings())
51 repo_defaults.update(model.get_repo_settings())
52
52
53 global_defaults = {
53 global_defaults = {
54 f'{k}_inherited': global_defaults[k]
54 f'{k}_inherited': global_defaults[k]
55 for k in global_defaults}
55 for k in global_defaults}
56
56
57 defaults = {
57 defaults = {
58 'inherit_global_settings': model.inherit_global_settings
58 'inherit_global_settings': model.inherit_global_settings
59 }
59 }
60 defaults.update(global_defaults)
60 defaults.update(global_defaults)
61 defaults.update(repo_defaults)
61 defaults.update(repo_defaults)
62 defaults.update({
62 defaults.update({
63 'new_svn_branch': '',
63 'new_svn_branch': '',
64 'new_svn_tag': '',
64 'new_svn_tag': '',
65 })
65 })
66 return defaults
66 return defaults
67
67
68 @LoginRequired()
68 @LoginRequired()
69 @HasRepoPermissionAnyDecorator('repository.admin')
69 @HasRepoPermissionAnyDecorator('repository.admin')
70 def repo_vcs_settings(self):
70 def repo_vcs_settings(self):
71 c = self.load_default_context()
71 c = self.load_default_context()
72 model = VcsSettingsModel(repo=self.db_repo_name)
72 model = VcsSettingsModel(repo=self.db_repo_name)
73
73
74 c.active = 'vcs'
74 c.active = 'vcs'
75 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
75 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
76 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
76 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
77 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
77 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
78 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
78 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
79
79
80 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
81 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
82
80 defaults = self._vcs_form_defaults(self.db_repo_name)
83 defaults = self._vcs_form_defaults(self.db_repo_name)
81 c.inherit_global_settings = defaults['inherit_global_settings']
84 c.inherit_global_settings = defaults['inherit_global_settings']
82
85
83 data = render('rhodecode:templates/admin/repos/repo_edit.mako',
86 data = render('rhodecode:templates/admin/repos/repo_edit.mako',
84 self._get_template_context(c), self.request)
87 self._get_template_context(c), self.request)
85 html = formencode.htmlfill.render(
88 html = formencode.htmlfill.render(
86 data,
89 data,
87 defaults=defaults,
90 defaults=defaults,
88 encoding="UTF-8",
91 encoding="UTF-8",
89 force_defaults=False
92 force_defaults=False
90 )
93 )
91 return Response(html)
94 return Response(html)
92
95
93 @LoginRequired()
96 @LoginRequired()
94 @HasRepoPermissionAnyDecorator('repository.admin')
97 @HasRepoPermissionAnyDecorator('repository.admin')
95 @CSRFRequired()
98 @CSRFRequired()
96 def repo_settings_vcs_update(self):
99 def repo_settings_vcs_update(self):
97 _ = self.request.translate
100 _ = self.request.translate
98 c = self.load_default_context()
101 c = self.load_default_context()
99 c.active = 'vcs'
102 c.active = 'vcs'
100
103
101 model = VcsSettingsModel(repo=self.db_repo_name)
104 model = VcsSettingsModel(repo=self.db_repo_name)
102 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
105 c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
103 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
106 c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
104 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
107 c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
105 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
108 c.svn_tag_patterns = model.get_repo_svn_tag_patterns()
109 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
110 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
106
111
107 defaults = self._vcs_form_defaults(self.db_repo_name)
112 defaults = self._vcs_form_defaults(self.db_repo_name)
108 c.inherit_global_settings = defaults['inherit_global_settings']
113 c.inherit_global_settings = defaults['inherit_global_settings']
109
114
110 application_form = RepoVcsSettingsForm(self.request.translate, self.db_repo_name)()
115 application_form = RepoVcsSettingsForm(self.request.translate, self.db_repo_name)()
111 try:
116 try:
112 form_result = application_form.to_python(dict(self.request.POST))
117 form_result = application_form.to_python(dict(self.request.POST))
113 except formencode.Invalid as errors:
118 except formencode.Invalid as errors:
114 h.flash(_("Some form inputs contain invalid data."),
119 h.flash(_("Some form inputs contain invalid data."),
115 category='error')
120 category='error')
116
121
117 data = render('rhodecode:templates/admin/repos/repo_edit.mako',
122 data = render('rhodecode:templates/admin/repos/repo_edit.mako',
118 self._get_template_context(c), self.request)
123 self._get_template_context(c), self.request)
119 html = formencode.htmlfill.render(
124 html = formencode.htmlfill.render(
120 data,
125 data,
121 defaults=errors.value,
126 defaults=errors.value,
122 errors=errors.error_dict or {},
127 errors=errors.error_dict or {},
123 encoding="UTF-8",
128 encoding="UTF-8",
124 force_defaults=False
129 force_defaults=False
125 )
130 )
126 return Response(html)
131 return Response(html)
127
132
128 try:
133 try:
129 inherit_global_settings = form_result['inherit_global_settings']
134 inherit_global_settings = form_result['inherit_global_settings']
130 model.create_or_update_repo_settings(
135 model.create_or_update_repo_settings(
131 form_result, inherit_global_settings=inherit_global_settings)
136 form_result, inherit_global_settings=inherit_global_settings)
132 Session().commit()
137 Session().commit()
133 h.flash(_('Updated VCS settings'), category='success')
138 h.flash(_('Updated VCS settings'), category='success')
134 except Exception:
139 except Exception:
135 log.exception("Exception while updating settings")
140 log.exception("Exception while updating settings")
136 h.flash(
141 h.flash(
137 _('Error occurred during updating repository VCS settings'),
142 _('Error occurred during updating repository VCS settings'),
138 category='error')
143 category='error')
139
144
140 raise HTTPFound(
145 raise HTTPFound(
141 h.route_path('edit_repo_vcs', repo_name=self.db_repo_name))
146 h.route_path('edit_repo_vcs', repo_name=self.db_repo_name))
142
147
143 @LoginRequired()
148 @LoginRequired()
144 @HasRepoPermissionAnyDecorator('repository.admin')
149 @HasRepoPermissionAnyDecorator('repository.admin')
145 @CSRFRequired()
150 @CSRFRequired()
146 def repo_settings_delete_svn_pattern(self):
151 def repo_settings_delete_svn_pattern(self):
147 self.load_default_context()
152 self.load_default_context()
148 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
153 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
149 model = VcsSettingsModel(repo=self.db_repo_name)
154 model = VcsSettingsModel(repo=self.db_repo_name)
150 try:
155 try:
151 model.delete_repo_svn_pattern(delete_pattern_id)
156 model.delete_repo_svn_pattern(delete_pattern_id)
152 except SettingNotFound:
157 except SettingNotFound:
153 log.exception('Failed to delete SVN pattern')
158 log.exception('Failed to delete SVN pattern')
154 raise HTTPBadRequest()
159 raise HTTPBadRequest()
155
160
156 Session().commit()
161 Session().commit()
157 return True
162 return True
@@ -1,64 +1,53 b''
1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
2
2
3 ${h.secure_form(h.route_path('admin_settings_vcs_update'), request=request)}
3 ${h.secure_form(h.route_path('admin_settings_vcs_update'), request=request)}
4 <div>
4 <div>
5 ${vcss.vcs_settings_fields(
5 ${vcss.vcs_settings_fields(
6 suffix='',
6 suffix='',
7 svn_tag_patterns=c.svn_tag_patterns,
7 svn_tag_patterns=c.svn_tag_patterns,
8 svn_branch_patterns=c.svn_branch_patterns,
8 svn_branch_patterns=c.svn_branch_patterns,
9 display_globals=True
9 display_globals=True
10 )}
10 )}
11 <div class="buttons">
11 <div class="buttons">
12 ${h.submit('save',_('Save settings'),class_="btn")}
12 ${h.submit('save',_('Save settings'),class_="btn")}
13 ${h.reset('reset',_('Reset'),class_="btn")}
13 ${h.reset('reset',_('Reset'),class_="btn")}
14 </div>
14 </div>
15 </div>
15 </div>
16 ${h.end_form()}
16 ${h.end_form()}
17
17
18 <script type="text/javascript">
18 <script type="text/javascript">
19
19
20 function ajaxDeletePattern(pattern_id, field_id) {
20 function ajaxDeletePattern(pattern_id, field_id) {
21 var sUrl = "${h.route_path('admin_settings_vcs_svn_pattern_delete')}";
21 var sUrl = "${h.route_path('admin_settings_vcs_svn_pattern_delete')}";
22 var callback = function (o) {
22 var callback = function (o) {
23 var elem = $("#"+field_id);
23 var elem = $("#"+field_id);
24 elem.remove();
24 elem.remove();
25 };
25 };
26 var postData = {
26 var postData = {
27 'delete_svn_pattern': pattern_id,
27 'delete_svn_pattern': pattern_id,
28 'csrf_token': CSRF_TOKEN
28 'csrf_token': CSRF_TOKEN
29 };
29 };
30 var request = $.post(sUrl, postData)
30 var request = $.post(sUrl, postData)
31 .done(callback)
31 .done(callback)
32 .fail(function (data, textStatus, errorThrown) {
32 .fail(function (data, textStatus, errorThrown) {
33 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
33 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
34 });
34 });
35 };
35 };
36
36
37 $(document).ready(function() {
37 $(document).ready(function() {
38
38
39 var unlockpath = function() {
39 var unlockpath = function() {
40 $('#path_unlock_icon').removeClass('icon-lock').addClass('icon-unlock');
40 $('#path_unlock_icon').removeClass('icon-lock').addClass('icon-unlock');
41 $('#paths_root_path').removeAttr('readonly').removeClass('disabled');
41 $('#paths_root_path').removeAttr('readonly').removeClass('disabled');
42 };
42 };
43
43
44 $('#path_unlock').on('click', function(e) {
44 $('#path_unlock').on('click', function(e) {
45 unlockpath();
45 unlockpath();
46 });
46 });
47
47
48 if ($('.locked_input').children().hasClass('error-message')) {
48 if ($('.locked_input').children().hasClass('error-message')) {
49 unlockpath();
49 unlockpath();
50 }
50 }
51
51
52 /* On click handler for the `Generate Apache Config` button. It sends a
53 POST request to trigger the (re)generation of the mod_dav_svn config. */
54 $('#vcs_svn_generate_cfg').on('click', function(event) {
55 event.preventDefault();
56 var url = "${h.route_path('admin_settings_vcs_svn_generate_cfg')}";
57 var jqxhr = $.post(url, {'csrf_token': CSRF_TOKEN});
58 jqxhr.done(function(data) {
59 $.Topic('/notifications').publish(data);
60 });
61 });
62
63 });
52 });
64 </script>
53 </script>
@@ -1,328 +1,347 b''
1 ## snippet for displaying vcs settings
1 ## snippet for displaying vcs settings
2 ## usage:
2 ## usage:
3 ## <%namespace name="vcss" file="/base/vcssettings.mako"/>
3 ## <%namespace name="vcss" file="/base/vcssettings.mako"/>
4 ## ${vcss.vcs_settings_fields()}
4 ## ${vcss.vcs_settings_fields()}
5
5
6 <%def name="vcs_settings_fields(suffix='', svn_branch_patterns=None, svn_tag_patterns=None, repo_type=None, display_globals=False, **kwargs)">
6 <%def name="vcs_settings_fields(suffix='', svn_branch_patterns=None, svn_tag_patterns=None, repo_type=None, display_globals=False, **kwargs)">
7 % if display_globals:
7 % if display_globals:
8 <div class="panel panel-default">
8 <div class="panel panel-default">
9 <div class="panel-heading" id="general">
9 <div class="panel-heading" id="general">
10 <h3 class="panel-title">${_('General')}<a class="permalink" href="#general"> ΒΆ</a></h3>
10 <h3 class="panel-title">${_('General')}<a class="permalink" href="#general"> ΒΆ</a></h3>
11 </div>
11 </div>
12 <div class="panel-body">
12 <div class="panel-body">
13 <div class="field">
13 <div class="field">
14 <div class="checkbox">
14 <div class="checkbox">
15 ${h.checkbox('web_push_ssl' + suffix, 'True')}
15 ${h.checkbox('web_push_ssl' + suffix, 'True')}
16 <label for="web_push_ssl${suffix}">${_('Require SSL for vcs operations')}</label>
16 <label for="web_push_ssl${suffix}">${_('Require SSL for vcs operations')}</label>
17 </div>
17 </div>
18 <div class="label">
18 <div class="label">
19 <span class="help-block">${_('Activate to set RhodeCode to require SSL for pushing or pulling. If SSL certificate is missing it will return a HTTP Error 406: Not Acceptable.')}</span>
19 <span class="help-block">${_('Activate to set RhodeCode to require SSL for pushing or pulling. If SSL certificate is missing it will return a HTTP Error 406: Not Acceptable.')}</span>
20 </div>
20 </div>
21 </div>
21 </div>
22 </div>
22 </div>
23 </div>
23 </div>
24 % endif
24 % endif
25
25
26 % if display_globals or repo_type in ['git', 'hg']:
26 % if display_globals or repo_type in ['git', 'hg']:
27 <div class="panel panel-default">
27 <div class="panel panel-default">
28 <div class="panel-heading" id="vcs-hooks-options">
28 <div class="panel-heading" id="vcs-hooks-options">
29 <h3 class="panel-title">${_('Internal Hooks')}<a class="permalink" href="#vcs-hooks-options"> ΒΆ</a></h3>
29 <h3 class="panel-title">${_('Internal Hooks')}<a class="permalink" href="#vcs-hooks-options"> ΒΆ</a></h3>
30 </div>
30 </div>
31 <div class="panel-body">
31 <div class="panel-body">
32 <div class="field">
32 <div class="field">
33 <div class="checkbox">
33 <div class="checkbox">
34 ${h.checkbox('hooks_changegroup_repo_size' + suffix, 'True', **kwargs)}
34 ${h.checkbox('hooks_changegroup_repo_size' + suffix, 'True', **kwargs)}
35 <label for="hooks_changegroup_repo_size${suffix}">${_('Show repository size after push')}</label>
35 <label for="hooks_changegroup_repo_size${suffix}">${_('Show repository size after push')}</label>
36 </div>
36 </div>
37
37
38 <div class="label">
38 <div class="label">
39 <span class="help-block">${_('Trigger a hook that calculates repository size after each push.')}</span>
39 <span class="help-block">${_('Trigger a hook that calculates repository size after each push.')}</span>
40 </div>
40 </div>
41 <div class="checkbox">
41 <div class="checkbox">
42 ${h.checkbox('hooks_changegroup_push_logger' + suffix, 'True', **kwargs)}
42 ${h.checkbox('hooks_changegroup_push_logger' + suffix, 'True', **kwargs)}
43 <label for="hooks_changegroup_push_logger${suffix}">${_('Execute pre/post push hooks')}</label>
43 <label for="hooks_changegroup_push_logger${suffix}">${_('Execute pre/post push hooks')}</label>
44 </div>
44 </div>
45 <div class="label">
45 <div class="label">
46 <span class="help-block">${_('Execute Built in pre/post push hooks. This also executes rcextensions hooks.')}</span>
46 <span class="help-block">${_('Execute Built in pre/post push hooks. This also executes rcextensions hooks.')}</span>
47 </div>
47 </div>
48 <div class="checkbox">
48 <div class="checkbox">
49 ${h.checkbox('hooks_outgoing_pull_logger' + suffix, 'True', **kwargs)}
49 ${h.checkbox('hooks_outgoing_pull_logger' + suffix, 'True', **kwargs)}
50 <label for="hooks_outgoing_pull_logger${suffix}">${_('Execute pre/post pull hooks')}</label>
50 <label for="hooks_outgoing_pull_logger${suffix}">${_('Execute pre/post pull hooks')}</label>
51 </div>
51 </div>
52 <div class="label">
52 <div class="label">
53 <span class="help-block">${_('Execute Built in pre/post pull hooks. This also executes rcextensions hooks.')}</span>
53 <span class="help-block">${_('Execute Built in pre/post pull hooks. This also executes rcextensions hooks.')}</span>
54 </div>
54 </div>
55 </div>
55 </div>
56 </div>
56 </div>
57 </div>
57 </div>
58 % endif
58 % endif
59
59
60 % if display_globals or repo_type in ['hg']:
60 % if display_globals or repo_type in ['hg']:
61 <div class="panel panel-default">
61 <div class="panel panel-default">
62 <div class="panel-heading" id="vcs-hg-options">
62 <div class="panel-heading" id="vcs-hg-options">
63 <h3 class="panel-title">${_('Mercurial Settings')}<a class="permalink" href="#vcs-hg-options"> ΒΆ</a></h3>
63 <h3 class="panel-title">${_('Mercurial Settings')}<a class="permalink" href="#vcs-hg-options"> ΒΆ</a></h3>
64 </div>
64 </div>
65 <div class="panel-body">
65 <div class="panel-body">
66 <div class="checkbox">
66 <div class="checkbox">
67 ${h.checkbox('extensions_largefiles' + suffix, 'True', **kwargs)}
67 ${h.checkbox('extensions_largefiles' + suffix, 'True', **kwargs)}
68 <label for="extensions_largefiles${suffix}">${_('Enable largefiles extension')}</label>
68 <label for="extensions_largefiles${suffix}">${_('Enable largefiles extension')}</label>
69 </div>
69 </div>
70 <div class="label">
70 <div class="label">
71 % if display_globals:
71 % if display_globals:
72 <span class="help-block">${_('Enable Largefiles extensions for all repositories.')}</span>
72 <span class="help-block">${_('Enable Largefiles extensions for all repositories.')}</span>
73 % else:
73 % else:
74 <span class="help-block">${_('Enable Largefiles extensions for this repository.')}</span>
74 <span class="help-block">${_('Enable Largefiles extensions for this repository.')}</span>
75 % endif
75 % endif
76 </div>
76 </div>
77
77
78 % if display_globals:
78 % if display_globals:
79 <div class="field">
79 <div class="field">
80 <div class="input">
80 <div class="input">
81 ${h.text('largefiles_usercache' + suffix, size=59)}
81 ${h.text('largefiles_usercache' + suffix, size=59)}
82 </div>
82 </div>
83 </div>
83 </div>
84 <div class="label">
84 <div class="label">
85 <span class="help-block">${_('Filesystem location where Mercurial largefile objects should be stored.')}</span>
85 <span class="help-block">${_('Filesystem location where Mercurial largefile objects should be stored.')}</span>
86 </div>
86 </div>
87 % endif
87 % endif
88
88
89 <div class="checkbox">
89 <div class="checkbox">
90 ${h.checkbox('phases_publish' + suffix, 'True', **kwargs)}
90 ${h.checkbox('phases_publish' + suffix, 'True', **kwargs)}
91 <label for="phases_publish${suffix}">${_('Set repositories as publishing') if display_globals else _('Set repository as publishing')}</label>
91 <label for="phases_publish${suffix}">${_('Set repositories as publishing') if display_globals else _('Set repository as publishing')}</label>
92 </div>
92 </div>
93 <div class="label">
93 <div class="label">
94 <span class="help-block">${_('When this is enabled all commits in the repository are seen as public commits by clients.')}</span>
94 <span class="help-block">${_('When this is enabled all commits in the repository are seen as public commits by clients.')}</span>
95 </div>
95 </div>
96
96
97 <div class="checkbox">
97 <div class="checkbox">
98 ${h.checkbox('extensions_evolve' + suffix, 'True', **kwargs)}
98 ${h.checkbox('extensions_evolve' + suffix, 'True', **kwargs)}
99 <label for="extensions_evolve${suffix}">${_('Enable Evolve and Topic extension')}</label>
99 <label for="extensions_evolve${suffix}">${_('Enable Evolve and Topic extension')}</label>
100 </div>
100 </div>
101 <div class="label">
101 <div class="label">
102 % if display_globals:
102 % if display_globals:
103 <span class="help-block">${_('Enable Evolve and Topic extensions for all repositories.')}</span>
103 <span class="help-block">${_('Enable Evolve and Topic extensions for all repositories.')}</span>
104 % else:
104 % else:
105 <span class="help-block">${_('Enable Evolve and Topic extensions for this repository.')}</span>
105 <span class="help-block">${_('Enable Evolve and Topic extensions for this repository.')}</span>
106 % endif
106 % endif
107 </div>
107 </div>
108
108
109 </div>
109 </div>
110 </div>
110 </div>
111 % endif
111 % endif
112
112
113 % if display_globals or repo_type in ['git']:
113 % if display_globals or repo_type in ['git']:
114 <div class="panel panel-default">
114 <div class="panel panel-default">
115 <div class="panel-heading" id="vcs-git-options">
115 <div class="panel-heading" id="vcs-git-options">
116 <h3 class="panel-title">${_('Git Settings')}<a class="permalink" href="#vcs-git-options"> ΒΆ</a></h3>
116 <h3 class="panel-title">${_('Git Settings')}<a class="permalink" href="#vcs-git-options"> ΒΆ</a></h3>
117 </div>
117 </div>
118 <div class="panel-body">
118 <div class="panel-body">
119 <div class="checkbox">
119 <div class="checkbox">
120 ${h.checkbox('vcs_git_lfs_enabled' + suffix, 'True', **kwargs)}
120 ${h.checkbox('vcs_git_lfs_enabled' + suffix, 'True', **kwargs)}
121 <label for="vcs_git_lfs_enabled${suffix}">${_('Enable lfs extension')}</label>
121 <label for="vcs_git_lfs_enabled${suffix}">${_('Enable lfs extension')}</label>
122 </div>
122 </div>
123 <div class="label">
123 <div class="label">
124 % if display_globals:
124 % if display_globals:
125 <span class="help-block">${_('Enable lfs extensions for all repositories.')}</span>
125 <span class="help-block">${_('Enable lfs extensions for all repositories.')}</span>
126 % else:
126 % else:
127 <span class="help-block">${_('Enable lfs extensions for this repository.')}</span>
127 <span class="help-block">${_('Enable lfs extensions for this repository.')}</span>
128 % endif
128 % endif
129 </div>
129 </div>
130
130
131 % if display_globals:
131 % if display_globals:
132 <div class="field">
132 <div class="field">
133 <div class="input">
133 <div class="input">
134 ${h.text('vcs_git_lfs_store_location' + suffix, size=59)}
134 ${h.text('vcs_git_lfs_store_location' + suffix, size=59)}
135 </div>
135 </div>
136 </div>
136 </div>
137 <div class="label">
137 <div class="label">
138 <span class="help-block">${_('Filesystem location where Git lfs objects should be stored.')}</span>
138 <span class="help-block">${_('Filesystem location where Git lfs objects should be stored.')}</span>
139 </div>
139 </div>
140 % endif
140 % endif
141 </div>
141 </div>
142 </div>
142 </div>
143 % endif
143 % endif
144
144
145 % if display_globals or repo_type in ['svn']:
145 % if display_globals or repo_type in ['svn']:
146 <div class="panel panel-default">
146 <div class="panel panel-default">
147 <div class="panel-heading" id="vcs-svn-options">
147 <div class="panel-heading" id="vcs-svn-options">
148 <h3 class="panel-title">${_('Subversion Settings')}<a class="permalink" href="#vcs-svn-options"> ΒΆ</a></h3>
148 <h3 class="panel-title">${_('Subversion Settings')}<a class="permalink" href="#vcs-svn-options"> ΒΆ</a></h3>
149 </div>
149 </div>
150 <div class="panel-body">
150 <div class="panel-body">
151 % if display_globals:
151 <div class="field">
152 <div class="field">
152 <div class="content" >
153 <div class="content" >
153 <label>${_('mod_dav config')}</label><br/>
154 <label>${_('mod_dav config')}</label><br/>
154 <code>path: ${c.svn_config_path}</code>
155 <code>path: ${c.svn_config_path}</code>
155 </div>
156 </div>
156 <br/>
157 <br/>
157
158
158 <div>
159 <div>
159
160
160 % if c.svn_generate_config:
161 % if c.svn_generate_config:
161 <span class="buttons">
162 <span class="buttons">
162 <button class="btn btn-primary" id="vcs_svn_generate_cfg">${_('Re-generate Apache Config')}</button>
163 <button class="btn btn-primary" id="vcs_svn_generate_cfg">${_('Re-generate Apache Config')}</button>
163 </span>
164 </span>
164 % endif
165 % endif
165 </div>
166 </div>
166 </div>
167 </div>
168 % endif
167
169
168 <div class="field">
170 <div class="field">
169 <div class="content" >
171 <div class="content" >
170 <label>${_('Repository patterns')}</label><br/>
172 <label>${_('Repository patterns')}</label><br/>
171 </div>
173 </div>
172 </div>
174 </div>
173 <div class="label">
175 <div class="label">
174 <span class="help-block">${_('Patterns for identifying SVN branches and tags. For recursive search, use "*". Eg.: "/branches/*"')}</span>
176 <span class="help-block">${_('Patterns for identifying SVN branches and tags. For recursive search, use "*". Eg.: "/branches/*"')}</span>
175 </div>
177 </div>
176
178
177 <div class="field branch_patterns">
179 <div class="field branch_patterns">
178 <div class="input" >
180 <div class="input" >
179 <label>${_('Branches')}:</label><br/>
181 <label>${_('Branches')}:</label><br/>
180 </div>
182 </div>
181 % if svn_branch_patterns:
183 % if svn_branch_patterns:
182 % for branch in svn_branch_patterns:
184 % for branch in svn_branch_patterns:
183 <div class="input adjacent" id="${'id%s' % branch.ui_id}">
185 <div class="input adjacent" id="${'id%s' % branch.ui_id}">
184 ${h.hidden('branch_ui_key' + suffix, branch.ui_key)}
186 ${h.hidden('branch_ui_key' + suffix, branch.ui_key)}
185 ${h.text('branch_value_%d' % branch.ui_id + suffix, branch.ui_value, size=59, readonly="readonly", class_='disabled')}
187 ${h.text('branch_value_%d' % branch.ui_id + suffix, branch.ui_value, size=59, readonly="readonly", class_='disabled')}
186 % if kwargs.get('disabled') != 'disabled':
188 % if kwargs.get('disabled') != 'disabled':
187 <span class="btn btn-x" onclick="ajaxDeletePattern(${branch.ui_id},'${'id%s' % branch.ui_id}')">
189 <span class="btn btn-x" onclick="ajaxDeletePattern(${branch.ui_id},'${'id%s' % branch.ui_id}')">
188 ${_('Delete')}
190 ${_('Delete')}
189 </span>
191 </span>
190 % endif
192 % endif
191 </div>
193 </div>
192 % endfor
194 % endfor
193 %endif
195 %endif
194 </div>
196 </div>
195 % if kwargs.get('disabled') != 'disabled':
197 % if kwargs.get('disabled') != 'disabled':
196 <div class="field branch_patterns">
198 <div class="field branch_patterns">
197 <div class="input" >
199 <div class="input" >
198 ${h.text('new_svn_branch',size=59,placeholder='New branch pattern')}
200 ${h.text('new_svn_branch',size=59,placeholder='New branch pattern')}
199 </div>
201 </div>
200 </div>
202 </div>
201 % endif
203 % endif
202 <div class="field tag_patterns">
204 <div class="field tag_patterns">
203 <div class="input" >
205 <div class="input" >
204 <label>${_('Tags')}:</label><br/>
206 <label>${_('Tags')}:</label><br/>
205 </div>
207 </div>
206 % if svn_tag_patterns:
208 % if svn_tag_patterns:
207 % for tag in svn_tag_patterns:
209 % for tag in svn_tag_patterns:
208 <div class="input" id="${'id%s' % tag.ui_id + suffix}">
210 <div class="input" id="${'id%s' % tag.ui_id + suffix}">
209 ${h.hidden('tag_ui_key' + suffix, tag.ui_key)}
211 ${h.hidden('tag_ui_key' + suffix, tag.ui_key)}
210 ${h.text('tag_ui_value_new_%d' % tag.ui_id + suffix, tag.ui_value, size=59, readonly="readonly", class_='disabled tag_input')}
212 ${h.text('tag_ui_value_new_%d' % tag.ui_id + suffix, tag.ui_value, size=59, readonly="readonly", class_='disabled tag_input')}
211 % if kwargs.get('disabled') != 'disabled':
213 % if kwargs.get('disabled') != 'disabled':
212 <span class="btn btn-x" onclick="ajaxDeletePattern(${tag.ui_id},'${'id%s' % tag.ui_id}')">
214 <span class="btn btn-x" onclick="ajaxDeletePattern(${tag.ui_id},'${'id%s' % tag.ui_id}')">
213 ${_('Delete')}
215 ${_('Delete')}
214 </span>
216 </span>
215 %endif
217 %endif
216 </div>
218 </div>
217 % endfor
219 % endfor
218 % endif
220 % endif
219 </div>
221 </div>
220 % if kwargs.get('disabled') != 'disabled':
222 % if kwargs.get('disabled') != 'disabled':
221 <div class="field tag_patterns">
223 <div class="field tag_patterns">
222 <div class="input" >
224 <div class="input" >
223 ${h.text('new_svn_tag' + suffix, size=59, placeholder='New tag pattern')}
225 ${h.text('new_svn_tag' + suffix, size=59, placeholder='New tag pattern')}
224 </div>
226 </div>
225 </div>
227 </div>
226 %endif
228 %endif
227 </div>
229 </div>
228 </div>
230 </div>
229 % else:
231 % else:
230 ${h.hidden('new_svn_branch' + suffix, '')}
232 ${h.hidden('new_svn_branch' + suffix, '')}
231 ${h.hidden('new_svn_tag' + suffix, '')}
233 ${h.hidden('new_svn_tag' + suffix, '')}
232 % endif
234 % endif
233
235
234
236
235 % if display_globals or repo_type in ['hg', 'git']:
237 % if display_globals or repo_type in ['hg', 'git']:
236 <div class="panel panel-default">
238 <div class="panel panel-default">
237 <div class="panel-heading" id="vcs-pull-requests-options">
239 <div class="panel-heading" id="vcs-pull-requests-options">
238 <h3 class="panel-title">${_('Pull Request Settings')}<a class="permalink" href="#vcs-pull-requests-options"> ΒΆ</a></h3>
240 <h3 class="panel-title">${_('Pull Request Settings')}<a class="permalink" href="#vcs-pull-requests-options"> ΒΆ</a></h3>
239 </div>
241 </div>
240 <div class="panel-body">
242 <div class="panel-body">
241 <div class="checkbox">
243 <div class="checkbox">
242 ${h.checkbox('rhodecode_pr_merge_enabled' + suffix, 'True', **kwargs)}
244 ${h.checkbox('rhodecode_pr_merge_enabled' + suffix, 'True', **kwargs)}
243 <label for="rhodecode_pr_merge_enabled${suffix}">${_('Enable server-side merge for pull requests')}</label>
245 <label for="rhodecode_pr_merge_enabled${suffix}">${_('Enable server-side merge for pull requests')}</label>
244 </div>
246 </div>
245 <div class="label">
247 <div class="label">
246 <span class="help-block">${_('Note: when this feature is enabled, it only runs hooks defined in the rcextension package. Custom hooks added on the Admin -> Settings -> Hooks page will not be run when pull requests are automatically merged from the web interface.')}</span>
248 <span class="help-block">${_('Note: when this feature is enabled, it only runs hooks defined in the rcextension package. Custom hooks added on the Admin -> Settings -> Hooks page will not be run when pull requests are automatically merged from the web interface.')}</span>
247 </div>
249 </div>
248 <div class="checkbox">
250 <div class="checkbox">
249 ${h.checkbox('rhodecode_use_outdated_comments' + suffix, 'True', **kwargs)}
251 ${h.checkbox('rhodecode_use_outdated_comments' + suffix, 'True', **kwargs)}
250 <label for="rhodecode_use_outdated_comments${suffix}">${_('Invalidate and relocate inline comments during update')}</label>
252 <label for="rhodecode_use_outdated_comments${suffix}">${_('Invalidate and relocate inline comments during update')}</label>
251 </div>
253 </div>
252 <div class="label">
254 <div class="label">
253 <span class="help-block">${_('During the update of a pull request, the position of inline comments will be updated and outdated inline comments will be hidden.')}</span>
255 <span class="help-block">${_('During the update of a pull request, the position of inline comments will be updated and outdated inline comments will be hidden.')}</span>
254 </div>
256 </div>
255 </div>
257 </div>
256 </div>
258 </div>
257 % endif
259 % endif
258
260
259 % if display_globals or repo_type in ['hg', 'git', 'svn']:
261 % if display_globals or repo_type in ['hg', 'git', 'svn']:
260 <div class="panel panel-default">
262 <div class="panel panel-default">
261 <div class="panel-heading" id="vcs-pull-requests-options">
263 <div class="panel-heading" id="vcs-pull-requests-options">
262 <h3 class="panel-title">${_('Diff cache')}<a class="permalink" href="#vcs-pull-requests-options"> ΒΆ</a></h3>
264 <h3 class="panel-title">${_('Diff cache')}<a class="permalink" href="#vcs-pull-requests-options"> ΒΆ</a></h3>
263 </div>
265 </div>
264 <div class="panel-body">
266 <div class="panel-body">
265 <div class="checkbox">
267 <div class="checkbox">
266 ${h.checkbox('rhodecode_diff_cache' + suffix, 'True', **kwargs)}
268 ${h.checkbox('rhodecode_diff_cache' + suffix, 'True', **kwargs)}
267 <label for="rhodecode_diff_cache${suffix}">${_('Enable caching diffs for pull requests cache and commits')}</label>
269 <label for="rhodecode_diff_cache${suffix}">${_('Enable caching diffs for pull requests cache and commits')}</label>
268 </div>
270 </div>
269 </div>
271 </div>
270 </div>
272 </div>
271 % endif
273 % endif
272
274
273 % if display_globals or repo_type in ['hg',]:
275 % if display_globals or repo_type in ['hg',]:
274 <div class="panel panel-default">
276 <div class="panel panel-default">
275 <div class="panel-heading" id="vcs-pull-requests-options">
277 <div class="panel-heading" id="vcs-pull-requests-options">
276 <h3 class="panel-title">${_('Mercurial Pull Request Settings')}<a class="permalink" href="#vcs-hg-pull-requests-options"> ΒΆ</a></h3>
278 <h3 class="panel-title">${_('Mercurial Pull Request Settings')}<a class="permalink" href="#vcs-hg-pull-requests-options"> ΒΆ</a></h3>
277 </div>
279 </div>
278 <div class="panel-body">
280 <div class="panel-body">
279 ## Specific HG settings
281 ## Specific HG settings
280 <div class="checkbox">
282 <div class="checkbox">
281 ${h.checkbox('rhodecode_hg_use_rebase_for_merging' + suffix, 'True', **kwargs)}
283 ${h.checkbox('rhodecode_hg_use_rebase_for_merging' + suffix, 'True', **kwargs)}
282 <label for="rhodecode_hg_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
284 <label for="rhodecode_hg_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
283 </div>
285 </div>
284 <div class="label">
286 <div class="label">
285 <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
287 <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
286 </div>
288 </div>
287
289
288 <div class="checkbox">
290 <div class="checkbox">
289 ${h.checkbox('rhodecode_hg_close_branch_before_merging' + suffix, 'True', **kwargs)}
291 ${h.checkbox('rhodecode_hg_close_branch_before_merging' + suffix, 'True', **kwargs)}
290 <label for="rhodecode_hg_close_branch_before_merging{suffix}">${_('Close branch before merging it')}</label>
292 <label for="rhodecode_hg_close_branch_before_merging{suffix}">${_('Close branch before merging it')}</label>
291 </div>
293 </div>
292 <div class="label">
294 <div class="label">
293 <span class="help-block">${_('Close branch before merging it into destination branch. No effect when rebase strategy is use.')}</span>
295 <span class="help-block">${_('Close branch before merging it into destination branch. No effect when rebase strategy is use.')}</span>
294 </div>
296 </div>
295
297
296
298
297 </div>
299 </div>
298 </div>
300 </div>
299 % endif
301 % endif
300
302
301 ## DISABLED FOR GIT FOR NOW as the rebase/close is not supported yet
303 ## DISABLED FOR GIT FOR NOW as the rebase/close is not supported yet
302 ## % if display_globals or repo_type in ['git']:
304 ## % if display_globals or repo_type in ['git']:
303 ## <div class="panel panel-default">
305 ## <div class="panel panel-default">
304 ## <div class="panel-heading" id="vcs-pull-requests-options">
306 ## <div class="panel-heading" id="vcs-pull-requests-options">
305 ## <h3 class="panel-title">${_('Git Pull Request Settings')}<a class="permalink" href="#vcs-git-pull-requests-options"> ΒΆ</a></h3>
307 ## <h3 class="panel-title">${_('Git Pull Request Settings')}<a class="permalink" href="#vcs-git-pull-requests-options"> ΒΆ</a></h3>
306 ## </div>
308 ## </div>
307 ## <div class="panel-body">
309 ## <div class="panel-body">
308 ## <div class="checkbox">
310 ## <div class="checkbox">
309 ## ${h.checkbox('rhodecode_git_use_rebase_for_merging' + suffix, 'True', **kwargs)}
311 ## ${h.checkbox('rhodecode_git_use_rebase_for_merging' + suffix, 'True', **kwargs)}
310 ## <label for="rhodecode_git_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
312 ## <label for="rhodecode_git_use_rebase_for_merging${suffix}">${_('Use rebase as merge strategy')}</label>
311 ## </div>
313 ## </div>
312 ## <div class="label">
314 ## <div class="label">
313 ## <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
315 ## <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span>
314 ## </div>
316 ## </div>
315 ##
317 ##
316 ## <div class="checkbox">
318 ## <div class="checkbox">
317 ## ${h.checkbox('rhodecode_git_close_branch_before_merging' + suffix, 'True', **kwargs)}
319 ## ${h.checkbox('rhodecode_git_close_branch_before_merging' + suffix, 'True', **kwargs)}
318 ## <label for="rhodecode_git_close_branch_before_merging{suffix}">${_('Delete branch after merging it')}</label>
320 ## <label for="rhodecode_git_close_branch_before_merging{suffix}">${_('Delete branch after merging it')}</label>
319 ## </div>
321 ## </div>
320 ## <div class="label">
322 ## <div class="label">
321 ## <span class="help-block">${_('Delete branch after merging it into destination branch. No effect when rebase strategy is use.')}</span>
323 ## <span class="help-block">${_('Delete branch after merging it into destination branch. No effect when rebase strategy is use.')}</span>
322 ## </div>
324 ## </div>
323 ## </div>
325 ## </div>
324 ## </div>
326 ## </div>
325 ## % endif
327 ## % endif
326
328
329 <script type="text/javascript">
327
330
331 $(document).ready(function() {
332 /* On click handler for the `Generate Apache Config` button. It sends a
333 POST request to trigger the (re)generation of the mod_dav_svn config. */
334 $('#vcs_svn_generate_cfg').on('click', function(event) {
335 event.preventDefault();
336 alert('i cliked it !!')
337 var url = "${h.route_path('admin_settings_vcs_svn_generate_cfg')}";
338 var jqxhr = $.post(url, {'csrf_token': CSRF_TOKEN});
339 jqxhr.done(function(data) {
340 $.Topic('/notifications').publish(data);
341 });
342 });
343 });
344
345 </script>
328 </%def>
346 </%def>
347
General Comments 0
You need to be logged in to leave comments. Login now