##// END OF EJS Templates
fix: settings, no longer create lfs dirs, and disable hgsubversion from old installations
super-admin -
r5602:78e16a73 default
parent child Browse files
Show More
@@ -1,715 +1,716 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 import config_keys
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 # legacy param that needs to be kept
79 # legacy param that needs to be kept
80 'web_push_ssl': False
80 'web_push_ssl': False,
81 'extensions_hgsubversion': False
81 }
82 }
82 for each in ret:
83 for each in ret:
83 k = each.ui_key
84 k = each.ui_key
84 v = each.ui_value
85 v = each.ui_value
86 section = each.ui_section
87
85 # skip some options if they are defined
88 # skip some options if they are defined
86 if k in ['push_ssl']:
89 if f"{section}_{k}" in ['web_push_ssl', 'extensions_hgsubversion']:
87 continue
90 continue
88
91
89 if k == '/':
92 if k == '/':
90 k = 'root_path'
93 k = 'root_path'
91
94
92 if k in ['publish', 'enabled']:
95 if k in ['publish', 'enabled']:
93 v = str2bool(v)
96 v = str2bool(v)
94
97
95 if k.find('.') != -1:
98 if k.find('.') != -1:
96 k = k.replace('.', '_')
99 k = k.replace('.', '_')
97
100
98 if each.ui_section in ['hooks', 'extensions']:
101 if each.ui_section in ['hooks', 'extensions']:
99 v = each.ui_active
102 v = each.ui_active
100
103
101 settings[each.ui_section + '_' + k] = v
104 settings[section + '_' + k] = v
102
105
103 return settings
106 return settings
104
107
105 @classmethod
108 @classmethod
106 def _form_defaults(cls):
109 def _form_defaults(cls):
107 defaults = SettingsModel().get_all_settings()
110 defaults = SettingsModel().get_all_settings()
108 defaults.update(cls._get_ui_settings())
111 defaults.update(cls._get_ui_settings())
109
112
110 defaults.update({
113 defaults.update({
111 'new_svn_branch': '',
114 'new_svn_branch': '',
112 'new_svn_tag': '',
115 'new_svn_tag': '',
113 })
116 })
114 return defaults
117 return defaults
115
118
116 @LoginRequired()
119 @LoginRequired()
117 @HasPermissionAllDecorator('hg.admin')
120 @HasPermissionAllDecorator('hg.admin')
118 def settings_vcs(self):
121 def settings_vcs(self):
119 c = self.load_default_context()
122 c = self.load_default_context()
120 c.active = 'vcs'
123 c.active = 'vcs'
121 model = VcsSettingsModel()
124 model = VcsSettingsModel()
122 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
125 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
123 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
126 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
124 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
127 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
125 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
128 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
126 defaults = self._form_defaults()
129 defaults = self._form_defaults()
127
130
128 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
129
130 data = render('rhodecode:templates/admin/settings/settings.mako',
131 data = render('rhodecode:templates/admin/settings/settings.mako',
131 self._get_template_context(c), self.request)
132 self._get_template_context(c), self.request)
132 html = formencode.htmlfill.render(
133 html = formencode.htmlfill.render(
133 data,
134 data,
134 defaults=defaults,
135 defaults=defaults,
135 encoding="UTF-8",
136 encoding="UTF-8",
136 force_defaults=False
137 force_defaults=False
137 )
138 )
138 return Response(html)
139 return Response(html)
139
140
140 @LoginRequired()
141 @LoginRequired()
141 @HasPermissionAllDecorator('hg.admin')
142 @HasPermissionAllDecorator('hg.admin')
142 @CSRFRequired()
143 @CSRFRequired()
143 def settings_vcs_update(self):
144 def settings_vcs_update(self):
144 _ = self.request.translate
145 _ = self.request.translate
145 c = self.load_default_context()
146 c = self.load_default_context()
146 c.active = 'vcs'
147 c.active = 'vcs'
147
148
148 model = VcsSettingsModel()
149 model = VcsSettingsModel()
149 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
150 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
150 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
151 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
151
152
152 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
153 c.svn_generate_config = rhodecode.ConfigGet().get_bool(config_keys.generate_config)
153 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
154 c.svn_config_path = rhodecode.ConfigGet().get_str(config_keys.config_file_path)
154 application_form = ApplicationUiSettingsForm(self.request.translate)()
155 application_form = ApplicationUiSettingsForm(self.request.translate)()
155
156
156 try:
157 try:
157 form_result = application_form.to_python(dict(self.request.POST))
158 form_result = application_form.to_python(dict(self.request.POST))
158 except formencode.Invalid as errors:
159 except formencode.Invalid as errors:
159 h.flash(
160 h.flash(
160 _("Some form inputs contain invalid data."),
161 _("Some form inputs contain invalid data."),
161 category='error')
162 category='error')
162 data = render('rhodecode:templates/admin/settings/settings.mako',
163 data = render('rhodecode:templates/admin/settings/settings.mako',
163 self._get_template_context(c), self.request)
164 self._get_template_context(c), self.request)
164 html = formencode.htmlfill.render(
165 html = formencode.htmlfill.render(
165 data,
166 data,
166 defaults=errors.value,
167 defaults=errors.value,
167 errors=errors.unpack_errors() or {},
168 errors=errors.unpack_errors() or {},
168 prefix_error=False,
169 prefix_error=False,
169 encoding="UTF-8",
170 encoding="UTF-8",
170 force_defaults=False
171 force_defaults=False
171 )
172 )
172 return Response(html)
173 return Response(html)
173
174
174 try:
175 try:
175 model.update_global_hook_settings(form_result)
176 model.update_global_hook_settings(form_result)
176
177
177 model.create_or_update_global_svn_settings(form_result)
178 model.create_or_update_global_svn_settings(form_result)
178 model.create_or_update_global_hg_settings(form_result)
179 model.create_or_update_global_hg_settings(form_result)
179 model.create_or_update_global_git_settings(form_result)
180 model.create_or_update_global_git_settings(form_result)
180 model.create_or_update_global_pr_settings(form_result)
181 model.create_or_update_global_pr_settings(form_result)
181 except Exception:
182 except Exception:
182 log.exception("Exception while updating settings")
183 log.exception("Exception while updating settings")
183 h.flash(_('Error occurred during updating '
184 h.flash(_('Error occurred during updating '
184 'application settings'), category='error')
185 'application settings'), category='error')
185 else:
186 else:
186 Session().commit()
187 Session().commit()
187 h.flash(_('Updated VCS settings'), category='success')
188 h.flash(_('Updated VCS settings'), category='success')
188 raise HTTPFound(h.route_path('admin_settings_vcs'))
189 raise HTTPFound(h.route_path('admin_settings_vcs'))
189
190
190 data = render('rhodecode:templates/admin/settings/settings.mako',
191 data = render('rhodecode:templates/admin/settings/settings.mako',
191 self._get_template_context(c), self.request)
192 self._get_template_context(c), self.request)
192 html = formencode.htmlfill.render(
193 html = formencode.htmlfill.render(
193 data,
194 data,
194 defaults=self._form_defaults(),
195 defaults=self._form_defaults(),
195 encoding="UTF-8",
196 encoding="UTF-8",
196 force_defaults=False
197 force_defaults=False
197 )
198 )
198 return Response(html)
199 return Response(html)
199
200
200 @LoginRequired()
201 @LoginRequired()
201 @HasPermissionAllDecorator('hg.admin')
202 @HasPermissionAllDecorator('hg.admin')
202 @CSRFRequired()
203 @CSRFRequired()
203 def settings_vcs_delete_svn_pattern(self):
204 def settings_vcs_delete_svn_pattern(self):
204 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
205 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
205 model = VcsSettingsModel()
206 model = VcsSettingsModel()
206 try:
207 try:
207 model.delete_global_svn_pattern(delete_pattern_id)
208 model.delete_global_svn_pattern(delete_pattern_id)
208 except SettingNotFound:
209 except SettingNotFound:
209 log.exception(
210 log.exception(
210 'Failed to delete svn_pattern with id %s', delete_pattern_id)
211 'Failed to delete svn_pattern with id %s', delete_pattern_id)
211 raise HTTPNotFound()
212 raise HTTPNotFound()
212
213
213 Session().commit()
214 Session().commit()
214 return True
215 return True
215
216
216 @LoginRequired()
217 @LoginRequired()
217 @HasPermissionAllDecorator('hg.admin')
218 @HasPermissionAllDecorator('hg.admin')
218 def settings_mapping(self):
219 def settings_mapping(self):
219 c = self.load_default_context()
220 c = self.load_default_context()
220 c.active = 'mapping'
221 c.active = 'mapping'
221 c.storage_path = get_rhodecode_repo_store_path()
222 c.storage_path = get_rhodecode_repo_store_path()
222 data = render('rhodecode:templates/admin/settings/settings.mako',
223 data = render('rhodecode:templates/admin/settings/settings.mako',
223 self._get_template_context(c), self.request)
224 self._get_template_context(c), self.request)
224 html = formencode.htmlfill.render(
225 html = formencode.htmlfill.render(
225 data,
226 data,
226 defaults=self._form_defaults(),
227 defaults=self._form_defaults(),
227 encoding="UTF-8",
228 encoding="UTF-8",
228 force_defaults=False
229 force_defaults=False
229 )
230 )
230 return Response(html)
231 return Response(html)
231
232
232 @LoginRequired()
233 @LoginRequired()
233 @HasPermissionAllDecorator('hg.admin')
234 @HasPermissionAllDecorator('hg.admin')
234 @CSRFRequired()
235 @CSRFRequired()
235 def settings_mapping_update(self):
236 def settings_mapping_update(self):
236 _ = self.request.translate
237 _ = self.request.translate
237 c = self.load_default_context()
238 c = self.load_default_context()
238 c.active = 'mapping'
239 c.active = 'mapping'
239 rm_obsolete = self.request.POST.get('destroy', False)
240 rm_obsolete = self.request.POST.get('destroy', False)
240 invalidate_cache = self.request.POST.get('invalidate', False)
241 invalidate_cache = self.request.POST.get('invalidate', False)
241 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
242 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
242
243
243 if invalidate_cache:
244 if invalidate_cache:
244 log.debug('invalidating all repositories cache')
245 log.debug('invalidating all repositories cache')
245 for repo in Repository.get_all():
246 for repo in Repository.get_all():
246 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
247 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
247
248
248 filesystem_repos = ScmModel().repo_scan()
249 filesystem_repos = ScmModel().repo_scan()
249 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, force_hooks_rebuild=True)
250 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete, force_hooks_rebuild=True)
250 PermissionModel().trigger_permission_flush()
251 PermissionModel().trigger_permission_flush()
251
252
252 def _repr(rm_repo):
253 def _repr(rm_repo):
253 return ', '.join(map(safe_str, rm_repo)) or '-'
254 return ', '.join(map(safe_str, rm_repo)) or '-'
254
255
255 h.flash(_('Repositories successfully '
256 h.flash(_('Repositories successfully '
256 'rescanned added: %s ; removed: %s') %
257 'rescanned added: %s ; removed: %s') %
257 (_repr(added), _repr(removed)),
258 (_repr(added), _repr(removed)),
258 category='success')
259 category='success')
259 raise HTTPFound(h.route_path('admin_settings_mapping'))
260 raise HTTPFound(h.route_path('admin_settings_mapping'))
260
261
261 @LoginRequired()
262 @LoginRequired()
262 @HasPermissionAllDecorator('hg.admin')
263 @HasPermissionAllDecorator('hg.admin')
263 def settings_global(self):
264 def settings_global(self):
264 c = self.load_default_context()
265 c = self.load_default_context()
265 c.active = 'global'
266 c.active = 'global'
266 c.personal_repo_group_default_pattern = RepoGroupModel()\
267 c.personal_repo_group_default_pattern = RepoGroupModel()\
267 .get_personal_group_name_pattern()
268 .get_personal_group_name_pattern()
268
269
269 data = render('rhodecode:templates/admin/settings/settings.mako',
270 data = render('rhodecode:templates/admin/settings/settings.mako',
270 self._get_template_context(c), self.request)
271 self._get_template_context(c), self.request)
271 html = formencode.htmlfill.render(
272 html = formencode.htmlfill.render(
272 data,
273 data,
273 defaults=self._form_defaults(),
274 defaults=self._form_defaults(),
274 encoding="UTF-8",
275 encoding="UTF-8",
275 force_defaults=False
276 force_defaults=False
276 )
277 )
277 return Response(html)
278 return Response(html)
278
279
279 @LoginRequired()
280 @LoginRequired()
280 @HasPermissionAllDecorator('hg.admin')
281 @HasPermissionAllDecorator('hg.admin')
281 @CSRFRequired()
282 @CSRFRequired()
282 def settings_global_update(self):
283 def settings_global_update(self):
283 _ = self.request.translate
284 _ = self.request.translate
284 c = self.load_default_context()
285 c = self.load_default_context()
285 c.active = 'global'
286 c.active = 'global'
286 c.personal_repo_group_default_pattern = RepoGroupModel()\
287 c.personal_repo_group_default_pattern = RepoGroupModel()\
287 .get_personal_group_name_pattern()
288 .get_personal_group_name_pattern()
288 application_form = ApplicationSettingsForm(self.request.translate)()
289 application_form = ApplicationSettingsForm(self.request.translate)()
289 try:
290 try:
290 form_result = application_form.to_python(dict(self.request.POST))
291 form_result = application_form.to_python(dict(self.request.POST))
291 except formencode.Invalid as errors:
292 except formencode.Invalid as errors:
292 h.flash(
293 h.flash(
293 _("Some form inputs contain invalid data."),
294 _("Some form inputs contain invalid data."),
294 category='error')
295 category='error')
295 data = render('rhodecode:templates/admin/settings/settings.mako',
296 data = render('rhodecode:templates/admin/settings/settings.mako',
296 self._get_template_context(c), self.request)
297 self._get_template_context(c), self.request)
297 html = formencode.htmlfill.render(
298 html = formencode.htmlfill.render(
298 data,
299 data,
299 defaults=errors.value,
300 defaults=errors.value,
300 errors=errors.unpack_errors() or {},
301 errors=errors.unpack_errors() or {},
301 prefix_error=False,
302 prefix_error=False,
302 encoding="UTF-8",
303 encoding="UTF-8",
303 force_defaults=False
304 force_defaults=False
304 )
305 )
305 return Response(html)
306 return Response(html)
306
307
307 settings = [
308 settings = [
308 ('title', 'rhodecode_title', 'unicode'),
309 ('title', 'rhodecode_title', 'unicode'),
309 ('realm', 'rhodecode_realm', 'unicode'),
310 ('realm', 'rhodecode_realm', 'unicode'),
310 ('pre_code', 'rhodecode_pre_code', 'unicode'),
311 ('pre_code', 'rhodecode_pre_code', 'unicode'),
311 ('post_code', 'rhodecode_post_code', 'unicode'),
312 ('post_code', 'rhodecode_post_code', 'unicode'),
312 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
313 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
313 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
314 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
314 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
315 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
315 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
316 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
316 ]
317 ]
317
318
318 try:
319 try:
319 for setting, form_key, type_ in settings:
320 for setting, form_key, type_ in settings:
320 sett = SettingsModel().create_or_update_setting(
321 sett = SettingsModel().create_or_update_setting(
321 setting, form_result[form_key], type_)
322 setting, form_result[form_key], type_)
322 Session().add(sett)
323 Session().add(sett)
323
324
324 Session().commit()
325 Session().commit()
325 SettingsModel().invalidate_settings_cache()
326 SettingsModel().invalidate_settings_cache()
326 h.flash(_('Updated application settings'), category='success')
327 h.flash(_('Updated application settings'), category='success')
327 except Exception:
328 except Exception:
328 log.exception("Exception while updating application settings")
329 log.exception("Exception while updating application settings")
329 h.flash(
330 h.flash(
330 _('Error occurred during updating application settings'),
331 _('Error occurred during updating application settings'),
331 category='error')
332 category='error')
332
333
333 raise HTTPFound(h.route_path('admin_settings_global'))
334 raise HTTPFound(h.route_path('admin_settings_global'))
334
335
335 @LoginRequired()
336 @LoginRequired()
336 @HasPermissionAllDecorator('hg.admin')
337 @HasPermissionAllDecorator('hg.admin')
337 def settings_visual(self):
338 def settings_visual(self):
338 c = self.load_default_context()
339 c = self.load_default_context()
339 c.active = 'visual'
340 c.active = 'visual'
340
341
341 data = render('rhodecode:templates/admin/settings/settings.mako',
342 data = render('rhodecode:templates/admin/settings/settings.mako',
342 self._get_template_context(c), self.request)
343 self._get_template_context(c), self.request)
343 html = formencode.htmlfill.render(
344 html = formencode.htmlfill.render(
344 data,
345 data,
345 defaults=self._form_defaults(),
346 defaults=self._form_defaults(),
346 encoding="UTF-8",
347 encoding="UTF-8",
347 force_defaults=False
348 force_defaults=False
348 )
349 )
349 return Response(html)
350 return Response(html)
350
351
351 @LoginRequired()
352 @LoginRequired()
352 @HasPermissionAllDecorator('hg.admin')
353 @HasPermissionAllDecorator('hg.admin')
353 @CSRFRequired()
354 @CSRFRequired()
354 def settings_visual_update(self):
355 def settings_visual_update(self):
355 _ = self.request.translate
356 _ = self.request.translate
356 c = self.load_default_context()
357 c = self.load_default_context()
357 c.active = 'visual'
358 c.active = 'visual'
358 application_form = ApplicationVisualisationForm(self.request.translate)()
359 application_form = ApplicationVisualisationForm(self.request.translate)()
359 try:
360 try:
360 form_result = application_form.to_python(dict(self.request.POST))
361 form_result = application_form.to_python(dict(self.request.POST))
361 except formencode.Invalid as errors:
362 except formencode.Invalid as errors:
362 h.flash(
363 h.flash(
363 _("Some form inputs contain invalid data."),
364 _("Some form inputs contain invalid data."),
364 category='error')
365 category='error')
365 data = render('rhodecode:templates/admin/settings/settings.mako',
366 data = render('rhodecode:templates/admin/settings/settings.mako',
366 self._get_template_context(c), self.request)
367 self._get_template_context(c), self.request)
367 html = formencode.htmlfill.render(
368 html = formencode.htmlfill.render(
368 data,
369 data,
369 defaults=errors.value,
370 defaults=errors.value,
370 errors=errors.unpack_errors() or {},
371 errors=errors.unpack_errors() or {},
371 prefix_error=False,
372 prefix_error=False,
372 encoding="UTF-8",
373 encoding="UTF-8",
373 force_defaults=False
374 force_defaults=False
374 )
375 )
375 return Response(html)
376 return Response(html)
376
377
377 try:
378 try:
378 settings = [
379 settings = [
379 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
380 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
380 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
381 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
381 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
382 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
382 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
383 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
383 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
384 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
384 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
385 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
385 ('show_version', 'rhodecode_show_version', 'bool'),
386 ('show_version', 'rhodecode_show_version', 'bool'),
386 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
387 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
387 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
388 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
388 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
389 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
389 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
390 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
390 ('clone_uri_id_tmpl', 'rhodecode_clone_uri_id_tmpl', 'unicode'),
391 ('clone_uri_id_tmpl', 'rhodecode_clone_uri_id_tmpl', 'unicode'),
391 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
392 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
392 ('support_url', 'rhodecode_support_url', 'unicode'),
393 ('support_url', 'rhodecode_support_url', 'unicode'),
393 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
394 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
394 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
395 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
395 ]
396 ]
396 for setting, form_key, type_ in settings:
397 for setting, form_key, type_ in settings:
397 sett = SettingsModel().create_or_update_setting(
398 sett = SettingsModel().create_or_update_setting(
398 setting, form_result[form_key], type_)
399 setting, form_result[form_key], type_)
399 Session().add(sett)
400 Session().add(sett)
400
401
401 Session().commit()
402 Session().commit()
402 SettingsModel().invalidate_settings_cache()
403 SettingsModel().invalidate_settings_cache()
403 h.flash(_('Updated visualisation settings'), category='success')
404 h.flash(_('Updated visualisation settings'), category='success')
404 except Exception:
405 except Exception:
405 log.exception("Exception updating visualization settings")
406 log.exception("Exception updating visualization settings")
406 h.flash(_('Error occurred during updating '
407 h.flash(_('Error occurred during updating '
407 'visualisation settings'),
408 'visualisation settings'),
408 category='error')
409 category='error')
409
410
410 raise HTTPFound(h.route_path('admin_settings_visual'))
411 raise HTTPFound(h.route_path('admin_settings_visual'))
411
412
412 @LoginRequired()
413 @LoginRequired()
413 @HasPermissionAllDecorator('hg.admin')
414 @HasPermissionAllDecorator('hg.admin')
414 def settings_issuetracker(self):
415 def settings_issuetracker(self):
415 c = self.load_default_context()
416 c = self.load_default_context()
416 c.active = 'issuetracker'
417 c.active = 'issuetracker'
417 defaults = c.rc_config
418 defaults = c.rc_config
418
419
419 entry_key = 'rhodecode_issuetracker_pat_'
420 entry_key = 'rhodecode_issuetracker_pat_'
420
421
421 c.issuetracker_entries = {}
422 c.issuetracker_entries = {}
422 for k, v in defaults.items():
423 for k, v in defaults.items():
423 if k.startswith(entry_key):
424 if k.startswith(entry_key):
424 uid = k[len(entry_key):]
425 uid = k[len(entry_key):]
425 c.issuetracker_entries[uid] = None
426 c.issuetracker_entries[uid] = None
426
427
427 for uid in c.issuetracker_entries:
428 for uid in c.issuetracker_entries:
428 c.issuetracker_entries[uid] = AttributeDict({
429 c.issuetracker_entries[uid] = AttributeDict({
429 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
430 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
430 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
431 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
431 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
432 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
432 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
433 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
433 })
434 })
434
435
435 return self._get_template_context(c)
436 return self._get_template_context(c)
436
437
437 @LoginRequired()
438 @LoginRequired()
438 @HasPermissionAllDecorator('hg.admin')
439 @HasPermissionAllDecorator('hg.admin')
439 @CSRFRequired()
440 @CSRFRequired()
440 def settings_issuetracker_test(self):
441 def settings_issuetracker_test(self):
441 error_container = []
442 error_container = []
442
443
443 urlified_commit = h.urlify_commit_message(
444 urlified_commit = h.urlify_commit_message(
444 self.request.POST.get('test_text', ''),
445 self.request.POST.get('test_text', ''),
445 'repo_group/test_repo1', error_container=error_container)
446 'repo_group/test_repo1', error_container=error_container)
446 if error_container:
447 if error_container:
447 def converter(inp):
448 def converter(inp):
448 return h.html_escape(inp)
449 return h.html_escape(inp)
449
450
450 return 'ERRORS: ' + '\n'.join(map(converter, error_container))
451 return 'ERRORS: ' + '\n'.join(map(converter, error_container))
451
452
452 return urlified_commit
453 return urlified_commit
453
454
454 @LoginRequired()
455 @LoginRequired()
455 @HasPermissionAllDecorator('hg.admin')
456 @HasPermissionAllDecorator('hg.admin')
456 @CSRFRequired()
457 @CSRFRequired()
457 def settings_issuetracker_update(self):
458 def settings_issuetracker_update(self):
458 _ = self.request.translate
459 _ = self.request.translate
459 self.load_default_context()
460 self.load_default_context()
460 settings_model = IssueTrackerSettingsModel()
461 settings_model = IssueTrackerSettingsModel()
461
462
462 try:
463 try:
463 form = IssueTrackerPatternsForm(self.request.translate)()
464 form = IssueTrackerPatternsForm(self.request.translate)()
464 data = form.to_python(self.request.POST)
465 data = form.to_python(self.request.POST)
465 except formencode.Invalid as errors:
466 except formencode.Invalid as errors:
466 log.exception('Failed to add new pattern')
467 log.exception('Failed to add new pattern')
467 error = errors
468 error = errors
468 h.flash(_(f'Invalid issue tracker pattern: {error}'),
469 h.flash(_(f'Invalid issue tracker pattern: {error}'),
469 category='error')
470 category='error')
470 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
471 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
471
472
472 if data:
473 if data:
473 for uid in data.get('delete_patterns', []):
474 for uid in data.get('delete_patterns', []):
474 settings_model.delete_entries(uid)
475 settings_model.delete_entries(uid)
475
476
476 for pattern in data.get('patterns', []):
477 for pattern in data.get('patterns', []):
477 for setting, value, type_ in pattern:
478 for setting, value, type_ in pattern:
478 sett = settings_model.create_or_update_setting(
479 sett = settings_model.create_or_update_setting(
479 setting, value, type_)
480 setting, value, type_)
480 Session().add(sett)
481 Session().add(sett)
481
482
482 Session().commit()
483 Session().commit()
483
484
484 SettingsModel().invalidate_settings_cache()
485 SettingsModel().invalidate_settings_cache()
485 h.flash(_('Updated issue tracker entries'), category='success')
486 h.flash(_('Updated issue tracker entries'), category='success')
486 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
487 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
487
488
488 @LoginRequired()
489 @LoginRequired()
489 @HasPermissionAllDecorator('hg.admin')
490 @HasPermissionAllDecorator('hg.admin')
490 @CSRFRequired()
491 @CSRFRequired()
491 def settings_issuetracker_delete(self):
492 def settings_issuetracker_delete(self):
492 _ = self.request.translate
493 _ = self.request.translate
493 self.load_default_context()
494 self.load_default_context()
494 uid = self.request.POST.get('uid')
495 uid = self.request.POST.get('uid')
495 try:
496 try:
496 IssueTrackerSettingsModel().delete_entries(uid)
497 IssueTrackerSettingsModel().delete_entries(uid)
497 except Exception:
498 except Exception:
498 log.exception('Failed to delete issue tracker setting %s', uid)
499 log.exception('Failed to delete issue tracker setting %s', uid)
499 raise HTTPNotFound()
500 raise HTTPNotFound()
500
501
501 SettingsModel().invalidate_settings_cache()
502 SettingsModel().invalidate_settings_cache()
502 h.flash(_('Removed issue tracker entry.'), category='success')
503 h.flash(_('Removed issue tracker entry.'), category='success')
503
504
504 return {'deleted': uid}
505 return {'deleted': uid}
505
506
506 @LoginRequired()
507 @LoginRequired()
507 @HasPermissionAllDecorator('hg.admin')
508 @HasPermissionAllDecorator('hg.admin')
508 def settings_email(self):
509 def settings_email(self):
509 c = self.load_default_context()
510 c = self.load_default_context()
510 c.active = 'email'
511 c.active = 'email'
511 c.rhodecode_ini = rhodecode.CONFIG
512 c.rhodecode_ini = rhodecode.CONFIG
512
513
513 data = render('rhodecode:templates/admin/settings/settings.mako',
514 data = render('rhodecode:templates/admin/settings/settings.mako',
514 self._get_template_context(c), self.request)
515 self._get_template_context(c), self.request)
515 html = formencode.htmlfill.render(
516 html = formencode.htmlfill.render(
516 data,
517 data,
517 defaults=self._form_defaults(),
518 defaults=self._form_defaults(),
518 encoding="UTF-8",
519 encoding="UTF-8",
519 force_defaults=False
520 force_defaults=False
520 )
521 )
521 return Response(html)
522 return Response(html)
522
523
523 @LoginRequired()
524 @LoginRequired()
524 @HasPermissionAllDecorator('hg.admin')
525 @HasPermissionAllDecorator('hg.admin')
525 @CSRFRequired()
526 @CSRFRequired()
526 def settings_email_update(self):
527 def settings_email_update(self):
527 _ = self.request.translate
528 _ = self.request.translate
528 c = self.load_default_context()
529 c = self.load_default_context()
529 c.active = 'email'
530 c.active = 'email'
530
531
531 test_email = self.request.POST.get('test_email')
532 test_email = self.request.POST.get('test_email')
532
533
533 if not test_email:
534 if not test_email:
534 h.flash(_('Please enter email address'), category='error')
535 h.flash(_('Please enter email address'), category='error')
535 raise HTTPFound(h.route_path('admin_settings_email'))
536 raise HTTPFound(h.route_path('admin_settings_email'))
536
537
537 email_kwargs = {
538 email_kwargs = {
538 'date': datetime.datetime.now(),
539 'date': datetime.datetime.now(),
539 'user': self._rhodecode_db_user
540 'user': self._rhodecode_db_user
540 }
541 }
541
542
542 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
543 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
543 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
544 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
544
545
545 recipients = [test_email] if test_email else None
546 recipients = [test_email] if test_email else None
546
547
547 run_task(tasks.send_email, recipients, subject,
548 run_task(tasks.send_email, recipients, subject,
548 email_body_plaintext, email_body)
549 email_body_plaintext, email_body)
549
550
550 h.flash(_('Send email task created'), category='success')
551 h.flash(_('Send email task created'), category='success')
551 raise HTTPFound(h.route_path('admin_settings_email'))
552 raise HTTPFound(h.route_path('admin_settings_email'))
552
553
553 @LoginRequired()
554 @LoginRequired()
554 @HasPermissionAllDecorator('hg.admin')
555 @HasPermissionAllDecorator('hg.admin')
555 def settings_hooks(self):
556 def settings_hooks(self):
556 c = self.load_default_context()
557 c = self.load_default_context()
557 c.active = 'hooks'
558 c.active = 'hooks'
558
559
559 model = SettingsModel()
560 model = SettingsModel()
560 c.hooks = model.get_builtin_hooks()
561 c.hooks = model.get_builtin_hooks()
561 c.custom_hooks = model.get_custom_hooks()
562 c.custom_hooks = model.get_custom_hooks()
562
563
563 data = render('rhodecode:templates/admin/settings/settings.mako',
564 data = render('rhodecode:templates/admin/settings/settings.mako',
564 self._get_template_context(c), self.request)
565 self._get_template_context(c), self.request)
565 html = formencode.htmlfill.render(
566 html = formencode.htmlfill.render(
566 data,
567 data,
567 defaults=self._form_defaults(),
568 defaults=self._form_defaults(),
568 encoding="UTF-8",
569 encoding="UTF-8",
569 force_defaults=False
570 force_defaults=False
570 )
571 )
571 return Response(html)
572 return Response(html)
572
573
573 @LoginRequired()
574 @LoginRequired()
574 @HasPermissionAllDecorator('hg.admin')
575 @HasPermissionAllDecorator('hg.admin')
575 @CSRFRequired()
576 @CSRFRequired()
576 def settings_hooks_update(self):
577 def settings_hooks_update(self):
577 _ = self.request.translate
578 _ = self.request.translate
578 c = self.load_default_context()
579 c = self.load_default_context()
579 c.active = 'hooks'
580 c.active = 'hooks'
580 if c.visual.allow_custom_hooks_settings:
581 if c.visual.allow_custom_hooks_settings:
581 ui_key = self.request.POST.get('new_hook_ui_key')
582 ui_key = self.request.POST.get('new_hook_ui_key')
582 ui_value = self.request.POST.get('new_hook_ui_value')
583 ui_value = self.request.POST.get('new_hook_ui_value')
583
584
584 hook_id = self.request.POST.get('hook_id')
585 hook_id = self.request.POST.get('hook_id')
585 new_hook = False
586 new_hook = False
586
587
587 model = SettingsModel()
588 model = SettingsModel()
588 try:
589 try:
589 if ui_value and ui_key:
590 if ui_value and ui_key:
590 model.create_or_update_hook(ui_key, ui_value)
591 model.create_or_update_hook(ui_key, ui_value)
591 h.flash(_('Added new hook'), category='success')
592 h.flash(_('Added new hook'), category='success')
592 new_hook = True
593 new_hook = True
593 elif hook_id:
594 elif hook_id:
594 RhodeCodeUi.delete(hook_id)
595 RhodeCodeUi.delete(hook_id)
595 Session().commit()
596 Session().commit()
596
597
597 # check for edits
598 # check for edits
598 update = False
599 update = False
599 _d = self.request.POST.dict_of_lists()
600 _d = self.request.POST.dict_of_lists()
600 for k, v in zip(_d.get('hook_ui_key', []),
601 for k, v in zip(_d.get('hook_ui_key', []),
601 _d.get('hook_ui_value_new', [])):
602 _d.get('hook_ui_value_new', [])):
602 model.create_or_update_hook(k, v)
603 model.create_or_update_hook(k, v)
603 update = True
604 update = True
604
605
605 if update and not new_hook:
606 if update and not new_hook:
606 h.flash(_('Updated hooks'), category='success')
607 h.flash(_('Updated hooks'), category='success')
607 Session().commit()
608 Session().commit()
608 except Exception:
609 except Exception:
609 log.exception("Exception during hook creation")
610 log.exception("Exception during hook creation")
610 h.flash(_('Error occurred during hook creation'),
611 h.flash(_('Error occurred during hook creation'),
611 category='error')
612 category='error')
612
613
613 raise HTTPFound(h.route_path('admin_settings_hooks'))
614 raise HTTPFound(h.route_path('admin_settings_hooks'))
614
615
615 @LoginRequired()
616 @LoginRequired()
616 @HasPermissionAllDecorator('hg.admin')
617 @HasPermissionAllDecorator('hg.admin')
617 def settings_search(self):
618 def settings_search(self):
618 c = self.load_default_context()
619 c = self.load_default_context()
619 c.active = 'search'
620 c.active = 'search'
620
621
621 c.searcher = searcher_from_config(self.request.registry.settings)
622 c.searcher = searcher_from_config(self.request.registry.settings)
622 c.statistics = c.searcher.statistics(self.request.translate)
623 c.statistics = c.searcher.statistics(self.request.translate)
623
624
624 return self._get_template_context(c)
625 return self._get_template_context(c)
625
626
626 @LoginRequired()
627 @LoginRequired()
627 @HasPermissionAllDecorator('hg.admin')
628 @HasPermissionAllDecorator('hg.admin')
628 def settings_labs(self):
629 def settings_labs(self):
629 c = self.load_default_context()
630 c = self.load_default_context()
630 if not c.labs_active:
631 if not c.labs_active:
631 raise HTTPFound(h.route_path('admin_settings'))
632 raise HTTPFound(h.route_path('admin_settings'))
632
633
633 c.active = 'labs'
634 c.active = 'labs'
634 c.lab_settings = _LAB_SETTINGS
635 c.lab_settings = _LAB_SETTINGS
635
636
636 data = render('rhodecode:templates/admin/settings/settings.mako',
637 data = render('rhodecode:templates/admin/settings/settings.mako',
637 self._get_template_context(c), self.request)
638 self._get_template_context(c), self.request)
638 html = formencode.htmlfill.render(
639 html = formencode.htmlfill.render(
639 data,
640 data,
640 defaults=self._form_defaults(),
641 defaults=self._form_defaults(),
641 encoding="UTF-8",
642 encoding="UTF-8",
642 force_defaults=False
643 force_defaults=False
643 )
644 )
644 return Response(html)
645 return Response(html)
645
646
646 @LoginRequired()
647 @LoginRequired()
647 @HasPermissionAllDecorator('hg.admin')
648 @HasPermissionAllDecorator('hg.admin')
648 @CSRFRequired()
649 @CSRFRequired()
649 def settings_labs_update(self):
650 def settings_labs_update(self):
650 _ = self.request.translate
651 _ = self.request.translate
651 c = self.load_default_context()
652 c = self.load_default_context()
652 c.active = 'labs'
653 c.active = 'labs'
653
654
654 application_form = LabsSettingsForm(self.request.translate)()
655 application_form = LabsSettingsForm(self.request.translate)()
655 try:
656 try:
656 form_result = application_form.to_python(dict(self.request.POST))
657 form_result = application_form.to_python(dict(self.request.POST))
657 except formencode.Invalid as errors:
658 except formencode.Invalid as errors:
658 h.flash(
659 h.flash(
659 _("Some form inputs contain invalid data."),
660 _("Some form inputs contain invalid data."),
660 category='error')
661 category='error')
661 data = render('rhodecode:templates/admin/settings/settings.mako',
662 data = render('rhodecode:templates/admin/settings/settings.mako',
662 self._get_template_context(c), self.request)
663 self._get_template_context(c), self.request)
663 html = formencode.htmlfill.render(
664 html = formencode.htmlfill.render(
664 data,
665 data,
665 defaults=errors.value,
666 defaults=errors.value,
666 errors=errors.unpack_errors() or {},
667 errors=errors.unpack_errors() or {},
667 prefix_error=False,
668 prefix_error=False,
668 encoding="UTF-8",
669 encoding="UTF-8",
669 force_defaults=False
670 force_defaults=False
670 )
671 )
671 return Response(html)
672 return Response(html)
672
673
673 try:
674 try:
674 session = Session()
675 session = Session()
675 for setting in _LAB_SETTINGS:
676 for setting in _LAB_SETTINGS:
676 setting_name = setting.key[len('rhodecode_'):]
677 setting_name = setting.key[len('rhodecode_'):]
677 sett = SettingsModel().create_or_update_setting(
678 sett = SettingsModel().create_or_update_setting(
678 setting_name, form_result[setting.key], setting.type)
679 setting_name, form_result[setting.key], setting.type)
679 session.add(sett)
680 session.add(sett)
680
681
681 except Exception:
682 except Exception:
682 log.exception('Exception while updating lab settings')
683 log.exception('Exception while updating lab settings')
683 h.flash(_('Error occurred during updating labs settings'),
684 h.flash(_('Error occurred during updating labs settings'),
684 category='error')
685 category='error')
685 else:
686 else:
686 Session().commit()
687 Session().commit()
687 SettingsModel().invalidate_settings_cache()
688 SettingsModel().invalidate_settings_cache()
688 h.flash(_('Updated Labs settings'), category='success')
689 h.flash(_('Updated Labs settings'), category='success')
689 raise HTTPFound(h.route_path('admin_settings_labs'))
690 raise HTTPFound(h.route_path('admin_settings_labs'))
690
691
691 data = render('rhodecode:templates/admin/settings/settings.mako',
692 data = render('rhodecode:templates/admin/settings/settings.mako',
692 self._get_template_context(c), self.request)
693 self._get_template_context(c), self.request)
693 html = formencode.htmlfill.render(
694 html = formencode.htmlfill.render(
694 data,
695 data,
695 defaults=self._form_defaults(),
696 defaults=self._form_defaults(),
696 encoding="UTF-8",
697 encoding="UTF-8",
697 force_defaults=False
698 force_defaults=False
698 )
699 )
699 return Response(html)
700 return Response(html)
700
701
701
702
702 # :param key: name of the setting including the 'rhodecode_' prefix
703 # :param key: name of the setting including the 'rhodecode_' prefix
703 # :param type: the RhodeCodeSetting type to use.
704 # :param type: the RhodeCodeSetting type to use.
704 # :param group: the i18ned group in which we should dispaly this setting
705 # :param group: the i18ned group in which we should dispaly this setting
705 # :param label: the i18ned label we should display for this setting
706 # :param label: the i18ned label we should display for this setting
706 # :param help: the i18ned help we should dispaly for this setting
707 # :param help: the i18ned help we should dispaly for this setting
707 LabSetting = collections.namedtuple(
708 LabSetting = collections.namedtuple(
708 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
709 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
709
710
710
711
711 # This list has to be kept in sync with the form
712 # This list has to be kept in sync with the form
712 # rhodecode.model.forms.LabsSettingsForm.
713 # rhodecode.model.forms.LabsSettingsForm.
713 _LAB_SETTINGS = [
714 _LAB_SETTINGS = [
714
715
715 ]
716 ]
General Comments 0
You need to be logged in to leave comments. Login now