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