##// END OF EJS Templates
admin: ported settings controller to pyramid....
marcink -
r2333:c9f5d931 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (754 lines changed) Show them Hide them
@@ -0,0 +1,754 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23 import collections
24
25 import datetime
26 import formencode
27 import formencode.htmlfill
28
29 import rhodecode
30 from pyramid.view import view_config
31 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
32 from pyramid.renderers import render
33 from pyramid.response import Response
34
35 from rhodecode.apps._base import BaseAppView
36 from rhodecode.apps.admin.navigation import navigation_list
37 from rhodecode.apps.svn_support.config_keys import generate_config
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import (
40 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
41 from rhodecode.lib.celerylib import tasks, run_task
42 from rhodecode.lib.utils import repo2db_mapper
43 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
44 from rhodecode.lib.index import searcher_from_config
45
46 from rhodecode.model.db import RhodeCodeUi, Repository
47 from rhodecode.model.forms import (ApplicationSettingsForm,
48 ApplicationUiSettingsForm, ApplicationVisualisationForm,
49 LabsSettingsForm, IssueTrackerPatternsForm)
50 from rhodecode.model.repo_group import RepoGroupModel
51
52 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.notification import EmailNotificationModel
54 from rhodecode.model.meta import Session
55 from rhodecode.model.settings import (
56 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
57 SettingsModel)
58
59
60 log = logging.getLogger(__name__)
61
62
63 class AdminSettingsView(BaseAppView):
64
65 def load_default_context(self):
66 c = self._get_local_tmpl_context()
67 c.labs_active = str2bool(
68 rhodecode.CONFIG.get('labs_settings_active', 'true'))
69 c.navlist = navigation_list(self.request)
70 self._register_global_c(c)
71 return c
72
73 @classmethod
74 def _get_ui_settings(cls):
75 ret = RhodeCodeUi.query().all()
76
77 if not ret:
78 raise Exception('Could not get application ui settings !')
79 settings = {}
80 for each in ret:
81 k = each.ui_key
82 v = each.ui_value
83 if k == '/':
84 k = 'root_path'
85
86 if k in ['push_ssl', 'publish', 'enabled']:
87 v = str2bool(v)
88
89 if k.find('.') != -1:
90 k = k.replace('.', '_')
91
92 if each.ui_section in ['hooks', 'extensions']:
93 v = each.ui_active
94
95 settings[each.ui_section + '_' + k] = v
96 return settings
97
98 @classmethod
99 def _form_defaults(cls):
100 defaults = SettingsModel().get_all_settings()
101 defaults.update(cls._get_ui_settings())
102
103 defaults.update({
104 'new_svn_branch': '',
105 'new_svn_tag': '',
106 })
107 return defaults
108
109 @LoginRequired()
110 @HasPermissionAllDecorator('hg.admin')
111 @view_config(
112 route_name='admin_settings_vcs', request_method='GET',
113 renderer='rhodecode:templates/admin/settings/settings.mako')
114 def settings_vcs(self):
115 c = self.load_default_context()
116 c.active = 'vcs'
117 model = VcsSettingsModel()
118 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
119 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
120
121 settings = self.request.registry.settings
122 c.svn_proxy_generate_config = settings[generate_config]
123
124 defaults = self._form_defaults()
125
126 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
127
128 data = render('rhodecode:templates/admin/settings/settings.mako',
129 self._get_template_context(c), self.request)
130 html = formencode.htmlfill.render(
131 data,
132 defaults=defaults,
133 encoding="UTF-8",
134 force_defaults=False
135 )
136 return Response(html)
137
138 @LoginRequired()
139 @HasPermissionAllDecorator('hg.admin')
140 @CSRFRequired()
141 @view_config(
142 route_name='admin_settings_vcs_update', request_method='POST',
143 renderer='rhodecode:templates/admin/settings/settings.mako')
144 def settings_vcs_update(self):
145 _ = self.request.translate
146 c = self.load_default_context()
147 c.active = 'vcs'
148
149 model = VcsSettingsModel()
150 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
151 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
152
153 settings = self.request.registry.settings
154 c.svn_proxy_generate_config = settings[generate_config]
155
156 application_form = ApplicationUiSettingsForm()()
157
158 try:
159 form_result = application_form.to_python(dict(self.request.POST))
160 except formencode.Invalid as errors:
161 h.flash(
162 _("Some form inputs contain invalid data."),
163 category='error')
164 data = render('rhodecode:templates/admin/settings/settings.mako',
165 self._get_template_context(c), self.request)
166 html = formencode.htmlfill.render(
167 data,
168 defaults=errors.value,
169 errors=errors.error_dict or {},
170 prefix_error=False,
171 encoding="UTF-8",
172 force_defaults=False
173 )
174 return Response(html)
175
176 try:
177 if c.visual.allow_repo_location_change:
178 model.update_global_path_setting(
179 form_result['paths_root_path'])
180
181 model.update_global_ssl_setting(form_result['web_push_ssl'])
182 model.update_global_hook_settings(form_result)
183
184 model.create_or_update_global_svn_settings(form_result)
185 model.create_or_update_global_hg_settings(form_result)
186 model.create_or_update_global_git_settings(form_result)
187 model.create_or_update_global_pr_settings(form_result)
188 except Exception:
189 log.exception("Exception while updating settings")
190 h.flash(_('Error occurred during updating '
191 'application settings'), category='error')
192 else:
193 Session().commit()
194 h.flash(_('Updated VCS settings'), category='success')
195 raise HTTPFound(h.route_path('admin_settings_vcs'))
196
197 data = render('rhodecode:templates/admin/settings/settings.mako',
198 self._get_template_context(c), self.request)
199 html = formencode.htmlfill.render(
200 data,
201 defaults=self._form_defaults(),
202 encoding="UTF-8",
203 force_defaults=False
204 )
205 return Response(html)
206
207 @LoginRequired()
208 @HasPermissionAllDecorator('hg.admin')
209 @CSRFRequired()
210 @view_config(
211 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
212 renderer='json_ext', xhr=True)
213 def settings_vcs_delete_svn_pattern(self):
214 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
215 model = VcsSettingsModel()
216 try:
217 model.delete_global_svn_pattern(delete_pattern_id)
218 except SettingNotFound:
219 log.exception(
220 'Failed to delete svn_pattern with id %s', delete_pattern_id)
221 raise HTTPNotFound()
222
223 Session().commit()
224 return True
225
226 @LoginRequired()
227 @HasPermissionAllDecorator('hg.admin')
228 @view_config(
229 route_name='admin_settings_mapping', request_method='GET',
230 renderer='rhodecode:templates/admin/settings/settings.mako')
231 def settings_mapping(self):
232 c = self.load_default_context()
233 c.active = 'mapping'
234
235 data = render('rhodecode:templates/admin/settings/settings.mako',
236 self._get_template_context(c), self.request)
237 html = formencode.htmlfill.render(
238 data,
239 defaults=self._form_defaults(),
240 encoding="UTF-8",
241 force_defaults=False
242 )
243 return Response(html)
244
245 @LoginRequired()
246 @HasPermissionAllDecorator('hg.admin')
247 @CSRFRequired()
248 @view_config(
249 route_name='admin_settings_mapping_update', request_method='POST',
250 renderer='rhodecode:templates/admin/settings/settings.mako')
251 def settings_mapping_update(self):
252 _ = self.request.translate
253 c = self.load_default_context()
254 c.active = 'mapping'
255 rm_obsolete = self.request.POST.get('destroy', False)
256 invalidate_cache = self.request.POST.get('invalidate', False)
257 log.debug(
258 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
259
260 if invalidate_cache:
261 log.debug('invalidating all repositories cache')
262 for repo in Repository.get_all():
263 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
264
265 filesystem_repos = ScmModel().repo_scan()
266 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
267 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
268 h.flash(_('Repositories successfully '
269 'rescanned added: %s ; removed: %s') %
270 (_repr(added), _repr(removed)),
271 category='success')
272 raise HTTPFound(h.route_path('admin_settings_mapping'))
273
274 @LoginRequired()
275 @HasPermissionAllDecorator('hg.admin')
276 @view_config(
277 route_name='admin_settings', request_method='GET',
278 renderer='rhodecode:templates/admin/settings/settings.mako')
279 @view_config(
280 route_name='admin_settings_global', request_method='GET',
281 renderer='rhodecode:templates/admin/settings/settings.mako')
282 def settings_global(self):
283 c = self.load_default_context()
284 c.active = 'global'
285 c.personal_repo_group_default_pattern = RepoGroupModel()\
286 .get_personal_group_name_pattern()
287
288 data = render('rhodecode:templates/admin/settings/settings.mako',
289 self._get_template_context(c), self.request)
290 html = formencode.htmlfill.render(
291 data,
292 defaults=self._form_defaults(),
293 encoding="UTF-8",
294 force_defaults=False
295 )
296 return Response(html)
297
298 @LoginRequired()
299 @HasPermissionAllDecorator('hg.admin')
300 @CSRFRequired()
301 @view_config(
302 route_name='admin_settings_update', request_method='POST',
303 renderer='rhodecode:templates/admin/settings/settings.mako')
304 @view_config(
305 route_name='admin_settings_global_update', request_method='POST',
306 renderer='rhodecode:templates/admin/settings/settings.mako')
307 def settings_global_update(self):
308 _ = self.request.translate
309 c = self.load_default_context()
310 c.active = 'global'
311 c.personal_repo_group_default_pattern = RepoGroupModel()\
312 .get_personal_group_name_pattern()
313 application_form = ApplicationSettingsForm()()
314 try:
315 form_result = application_form.to_python(dict(self.request.POST))
316 except formencode.Invalid as errors:
317 data = render('rhodecode:templates/admin/settings/settings.mako',
318 self._get_template_context(c), self.request)
319 html = formencode.htmlfill.render(
320 data,
321 defaults=errors.value,
322 errors=errors.error_dict or {},
323 prefix_error=False,
324 encoding="UTF-8",
325 force_defaults=False
326 )
327 return Response(html)
328
329 settings = [
330 ('title', 'rhodecode_title', 'unicode'),
331 ('realm', 'rhodecode_realm', 'unicode'),
332 ('pre_code', 'rhodecode_pre_code', 'unicode'),
333 ('post_code', 'rhodecode_post_code', 'unicode'),
334 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
335 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
336 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
337 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
338 ]
339 try:
340 for setting, form_key, type_ in settings:
341 sett = SettingsModel().create_or_update_setting(
342 setting, form_result[form_key], type_)
343 Session().add(sett)
344
345 Session().commit()
346 SettingsModel().invalidate_settings_cache()
347 h.flash(_('Updated application settings'), category='success')
348 except Exception:
349 log.exception("Exception while updating application settings")
350 h.flash(
351 _('Error occurred during updating application settings'),
352 category='error')
353
354 raise HTTPFound(h.route_path('admin_settings_global'))
355
356 @LoginRequired()
357 @HasPermissionAllDecorator('hg.admin')
358 @view_config(
359 route_name='admin_settings_visual', request_method='GET',
360 renderer='rhodecode:templates/admin/settings/settings.mako')
361 def settings_visual(self):
362 c = self.load_default_context()
363 c.active = 'visual'
364
365 data = render('rhodecode:templates/admin/settings/settings.mako',
366 self._get_template_context(c), self.request)
367 html = formencode.htmlfill.render(
368 data,
369 defaults=self._form_defaults(),
370 encoding="UTF-8",
371 force_defaults=False
372 )
373 return Response(html)
374
375 @LoginRequired()
376 @HasPermissionAllDecorator('hg.admin')
377 @CSRFRequired()
378 @view_config(
379 route_name='admin_settings_visual_update', request_method='POST',
380 renderer='rhodecode:templates/admin/settings/settings.mako')
381 def settings_visual_update(self):
382 _ = self.request.translate
383 c = self.load_default_context()
384 c.active = 'visual'
385 application_form = ApplicationVisualisationForm()()
386 try:
387 form_result = application_form.to_python(dict(self.request.POST))
388 except formencode.Invalid as errors:
389 data = render('rhodecode:templates/admin/settings/settings.mako',
390 self._get_template_context(c), self.request)
391 html = formencode.htmlfill.render(
392 data,
393 defaults=errors.value,
394 errors=errors.error_dict or {},
395 prefix_error=False,
396 encoding="UTF-8",
397 force_defaults=False
398 )
399 return Response(html)
400
401 try:
402 settings = [
403 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
404 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
405 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
406 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
407 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
408 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
409 ('show_version', 'rhodecode_show_version', 'bool'),
410 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
411 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
412 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
413 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
414 ('support_url', 'rhodecode_support_url', 'unicode'),
415 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
416 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
417 ]
418 for setting, form_key, type_ in settings:
419 sett = SettingsModel().create_or_update_setting(
420 setting, form_result[form_key], type_)
421 Session().add(sett)
422
423 Session().commit()
424 SettingsModel().invalidate_settings_cache()
425 h.flash(_('Updated visualisation settings'), category='success')
426 except Exception:
427 log.exception("Exception updating visualization settings")
428 h.flash(_('Error occurred during updating '
429 'visualisation settings'),
430 category='error')
431
432 raise HTTPFound(h.route_path('admin_settings_visual'))
433
434 @LoginRequired()
435 @HasPermissionAllDecorator('hg.admin')
436 @view_config(
437 route_name='admin_settings_issuetracker', request_method='GET',
438 renderer='rhodecode:templates/admin/settings/settings.mako')
439 def settings_issuetracker(self):
440 c = self.load_default_context()
441 c.active = 'issuetracker'
442 defaults = SettingsModel().get_all_settings()
443
444 entry_key = 'rhodecode_issuetracker_pat_'
445
446 c.issuetracker_entries = {}
447 for k, v in defaults.items():
448 if k.startswith(entry_key):
449 uid = k[len(entry_key):]
450 c.issuetracker_entries[uid] = None
451
452 for uid in c.issuetracker_entries:
453 c.issuetracker_entries[uid] = AttributeDict({
454 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
455 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
456 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
457 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
458 })
459
460 return self._get_template_context(c)
461
462 @LoginRequired()
463 @HasPermissionAllDecorator('hg.admin')
464 @CSRFRequired()
465 @view_config(
466 route_name='admin_settings_issuetracker_test', request_method='POST',
467 renderer='string', xhr=True)
468 def settings_issuetracker_test(self):
469 return h.urlify_commit_message(
470 self.request.POST.get('test_text', ''),
471 'repo_group/test_repo1')
472
473 @LoginRequired()
474 @HasPermissionAllDecorator('hg.admin')
475 @CSRFRequired()
476 @view_config(
477 route_name='admin_settings_issuetracker_update', request_method='POST',
478 renderer='rhodecode:templates/admin/settings/settings.mako')
479 def settings_issuetracker_update(self):
480 _ = self.request.translate
481 self.load_default_context()
482 settings_model = IssueTrackerSettingsModel()
483
484 form = IssueTrackerPatternsForm()().to_python(self.request.POST)
485 if form:
486 for uid in form.get('delete_patterns', []):
487 settings_model.delete_entries(uid)
488
489 for pattern in form.get('patterns', []):
490 for setting, value, type_ in pattern:
491 sett = settings_model.create_or_update_setting(
492 setting, value, type_)
493 Session().add(sett)
494
495 Session().commit()
496
497 SettingsModel().invalidate_settings_cache()
498 h.flash(_('Updated issue tracker entries'), category='success')
499 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
500
501 @LoginRequired()
502 @HasPermissionAllDecorator('hg.admin')
503 @CSRFRequired()
504 @view_config(
505 route_name='admin_settings_issuetracker_delete', request_method='POST',
506 renderer='rhodecode:templates/admin/settings/settings.mako')
507 def settings_issuetracker_delete(self):
508 _ = self.request.translate
509 self.load_default_context()
510 uid = self.request.POST.get('uid')
511 try:
512 IssueTrackerSettingsModel().delete_entries(uid)
513 except Exception:
514 log.exception('Failed to delete issue tracker setting %s', uid)
515 raise HTTPNotFound()
516 h.flash(_('Removed issue tracker entry'), category='success')
517 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
518
519 @LoginRequired()
520 @HasPermissionAllDecorator('hg.admin')
521 @view_config(
522 route_name='admin_settings_email', request_method='GET',
523 renderer='rhodecode:templates/admin/settings/settings.mako')
524 def settings_email(self):
525 c = self.load_default_context()
526 c.active = 'email'
527 c.rhodecode_ini = rhodecode.CONFIG
528
529 data = render('rhodecode:templates/admin/settings/settings.mako',
530 self._get_template_context(c), self.request)
531 html = formencode.htmlfill.render(
532 data,
533 defaults=self._form_defaults(),
534 encoding="UTF-8",
535 force_defaults=False
536 )
537 return Response(html)
538
539 @LoginRequired()
540 @HasPermissionAllDecorator('hg.admin')
541 @CSRFRequired()
542 @view_config(
543 route_name='admin_settings_email_update', request_method='POST',
544 renderer='rhodecode:templates/admin/settings/settings.mako')
545 def settings_email_update(self):
546 _ = self.request.translate
547 c = self.load_default_context()
548 c.active = 'email'
549
550 test_email = self.request.POST.get('test_email')
551
552 if not test_email:
553 h.flash(_('Please enter email address'), category='error')
554 raise HTTPFound(h.route_path('admin_settings_email'))
555
556 email_kwargs = {
557 'date': datetime.datetime.now(),
558 'user': c.rhodecode_user,
559 'rhodecode_version': c.rhodecode_version
560 }
561
562 (subject, headers, email_body,
563 email_body_plaintext) = EmailNotificationModel().render_email(
564 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
565
566 recipients = [test_email] if test_email else None
567
568 run_task(tasks.send_email, recipients, subject,
569 email_body_plaintext, email_body)
570
571 h.flash(_('Send email task created'), category='success')
572 raise HTTPFound(h.route_path('admin_settings_email'))
573
574 @LoginRequired()
575 @HasPermissionAllDecorator('hg.admin')
576 @view_config(
577 route_name='admin_settings_hooks', request_method='GET',
578 renderer='rhodecode:templates/admin/settings/settings.mako')
579 def settings_hooks(self):
580 c = self.load_default_context()
581 c.active = 'hooks'
582
583 model = SettingsModel()
584 c.hooks = model.get_builtin_hooks()
585 c.custom_hooks = model.get_custom_hooks()
586
587 data = render('rhodecode:templates/admin/settings/settings.mako',
588 self._get_template_context(c), self.request)
589 html = formencode.htmlfill.render(
590 data,
591 defaults=self._form_defaults(),
592 encoding="UTF-8",
593 force_defaults=False
594 )
595 return Response(html)
596
597 @LoginRequired()
598 @HasPermissionAllDecorator('hg.admin')
599 @CSRFRequired()
600 @view_config(
601 route_name='admin_settings_hooks_update', request_method='POST',
602 renderer='rhodecode:templates/admin/settings/settings.mako')
603 @view_config(
604 route_name='admin_settings_hooks_delete', request_method='POST',
605 renderer='rhodecode:templates/admin/settings/settings.mako')
606 def settings_hooks_update(self):
607 _ = self.request.translate
608 c = self.load_default_context()
609 c.active = 'hooks'
610 if c.visual.allow_custom_hooks_settings:
611 ui_key = self.request.POST.get('new_hook_ui_key')
612 ui_value = self.request.POST.get('new_hook_ui_value')
613
614 hook_id = self.request.POST.get('hook_id')
615 new_hook = False
616
617 model = SettingsModel()
618 try:
619 if ui_value and ui_key:
620 model.create_or_update_hook(ui_key, ui_value)
621 h.flash(_('Added new hook'), category='success')
622 new_hook = True
623 elif hook_id:
624 RhodeCodeUi.delete(hook_id)
625 Session().commit()
626
627 # check for edits
628 update = False
629 _d = self.request.POST.dict_of_lists()
630 for k, v in zip(_d.get('hook_ui_key', []),
631 _d.get('hook_ui_value_new', [])):
632 model.create_or_update_hook(k, v)
633 update = True
634
635 if update and not new_hook:
636 h.flash(_('Updated hooks'), category='success')
637 Session().commit()
638 except Exception:
639 log.exception("Exception during hook creation")
640 h.flash(_('Error occurred during hook creation'),
641 category='error')
642
643 raise HTTPFound(h.route_path('admin_settings_hooks'))
644
645 @LoginRequired()
646 @HasPermissionAllDecorator('hg.admin')
647 @view_config(
648 route_name='admin_settings_search', request_method='GET',
649 renderer='rhodecode:templates/admin/settings/settings.mako')
650 def settings_search(self):
651 c = self.load_default_context()
652 c.active = 'search'
653
654 searcher = searcher_from_config(self.request.registry.settings)
655 c.statistics = searcher.statistics()
656
657 return self._get_template_context(c)
658
659 @LoginRequired()
660 @HasPermissionAllDecorator('hg.admin')
661 @view_config(
662 route_name='admin_settings_labs', request_method='GET',
663 renderer='rhodecode:templates/admin/settings/settings.mako')
664 def settings_labs(self):
665 c = self.load_default_context()
666 if not c.labs_active:
667 raise HTTPFound(h.route_path('admin_settings'))
668
669 c.active = 'labs'
670 c.lab_settings = _LAB_SETTINGS
671
672 data = render('rhodecode:templates/admin/settings/settings.mako',
673 self._get_template_context(c), self.request)
674 html = formencode.htmlfill.render(
675 data,
676 defaults=self._form_defaults(),
677 encoding="UTF-8",
678 force_defaults=False
679 )
680 return Response(html)
681
682 @LoginRequired()
683 @HasPermissionAllDecorator('hg.admin')
684 @CSRFRequired()
685 @view_config(
686 route_name='admin_settings_labs_update', request_method='POST',
687 renderer='rhodecode:templates/admin/settings/settings.mako')
688 def settings_labs_update(self):
689 _ = self.request.translate
690 c = self.load_default_context()
691 c.active = 'labs'
692
693 application_form = LabsSettingsForm()()
694 try:
695 form_result = application_form.to_python(dict(self.request.POST))
696 except formencode.Invalid as errors:
697 h.flash(
698 _('Some form inputs contain invalid data.'),
699 category='error')
700 data = render('rhodecode:templates/admin/settings/settings.mako',
701 self._get_template_context(c), self.request)
702 html = formencode.htmlfill.render(
703 data,
704 defaults=errors.value,
705 errors=errors.error_dict or {},
706 prefix_error=False,
707 encoding="UTF-8",
708 force_defaults=False
709 )
710 return Response(html)
711
712 try:
713 session = Session()
714 for setting in _LAB_SETTINGS:
715 setting_name = setting.key[len('rhodecode_'):]
716 sett = SettingsModel().create_or_update_setting(
717 setting_name, form_result[setting.key], setting.type)
718 session.add(sett)
719
720 except Exception:
721 log.exception('Exception while updating lab settings')
722 h.flash(_('Error occurred during updating labs settings'),
723 category='error')
724 else:
725 Session().commit()
726 SettingsModel().invalidate_settings_cache()
727 h.flash(_('Updated Labs settings'), category='success')
728 raise HTTPFound(h.route_path('admin_settings_labs'))
729
730 data = render('rhodecode:templates/admin/settings/settings.mako',
731 self._get_template_context(c), self.request)
732 html = formencode.htmlfill.render(
733 data,
734 defaults=self._form_defaults(),
735 encoding="UTF-8",
736 force_defaults=False
737 )
738 return Response(html)
739
740
741 # :param key: name of the setting including the 'rhodecode_' prefix
742 # :param type: the RhodeCodeSetting type to use.
743 # :param group: the i18ned group in which we should dispaly this setting
744 # :param label: the i18ned label we should display for this setting
745 # :param help: the i18ned help we should dispaly for this setting
746 LabSetting = collections.namedtuple(
747 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
748
749
750 # This list has to be kept in sync with the form
751 # rhodecode.model.forms.LabsSettingsForm.
752 _LAB_SETTINGS = [
753
754 ]
@@ -20,7 +20,6 b''
20
20
21
21
22 from rhodecode.apps._base import ADMIN_PREFIX
22 from rhodecode.apps._base import ADMIN_PREFIX
23 from rhodecode.lib.utils2 import str2bool
24
23
25
24
26 def admin_routes(config):
25 def admin_routes(config):
@@ -82,6 +81,88 b' def admin_routes(config):'
82 name='admin_defaults_repositories_update',
81 name='admin_defaults_repositories_update',
83 pattern='/defaults/repositories/update')
82 pattern='/defaults/repositories/update')
84
83
84 # admin settings
85
86 config.add_route(
87 name='admin_settings',
88 pattern='/settings')
89 config.add_route(
90 name='admin_settings_update',
91 pattern='/settings/update')
92
93 config.add_route(
94 name='admin_settings_global',
95 pattern='/settings/global')
96 config.add_route(
97 name='admin_settings_global_update',
98 pattern='/settings/global/update')
99
100 config.add_route(
101 name='admin_settings_vcs',
102 pattern='/settings/vcs')
103 config.add_route(
104 name='admin_settings_vcs_update',
105 pattern='/settings/vcs/update')
106 config.add_route(
107 name='admin_settings_vcs_svn_pattern_delete',
108 pattern='/settings/vcs/svn_pattern_delete')
109
110 config.add_route(
111 name='admin_settings_mapping',
112 pattern='/settings/mapping')
113 config.add_route(
114 name='admin_settings_mapping_update',
115 pattern='/settings/mapping/update')
116
117 config.add_route(
118 name='admin_settings_visual',
119 pattern='/settings/visual')
120 config.add_route(
121 name='admin_settings_visual_update',
122 pattern='/settings/visual/update')
123
124
125 config.add_route(
126 name='admin_settings_issuetracker',
127 pattern='/settings/issue-tracker')
128 config.add_route(
129 name='admin_settings_issuetracker_update',
130 pattern='/settings/issue-tracker/update')
131 config.add_route(
132 name='admin_settings_issuetracker_test',
133 pattern='/settings/issue-tracker/test')
134 config.add_route(
135 name='admin_settings_issuetracker_delete',
136 pattern='/settings/issue-tracker/delete')
137
138 config.add_route(
139 name='admin_settings_email',
140 pattern='/settings/email')
141 config.add_route(
142 name='admin_settings_email_update',
143 pattern='/settings/email/update')
144
145 config.add_route(
146 name='admin_settings_hooks',
147 pattern='/settings/hooks')
148 config.add_route(
149 name='admin_settings_hooks_update',
150 pattern='/settings/hooks/update')
151 config.add_route(
152 name='admin_settings_hooks_delete',
153 pattern='/settings/hooks/delete')
154
155 config.add_route(
156 name='admin_settings_search',
157 pattern='/settings/search')
158
159 config.add_route(
160 name='admin_settings_labs',
161 pattern='/settings/labs')
162 config.add_route(
163 name='admin_settings_labs_update',
164 pattern='/settings/labs/update')
165
85 # global permissions
166 # global permissions
86
167
87 config.add_route(
168 config.add_route(
@@ -236,7 +317,7 b' def admin_routes(config):'
236 config.add_route(
317 config.add_route(
237 name='edit_user_ips_delete',
318 name='edit_user_ips_delete',
238 pattern='/users/{user_id:\d+}/edit/ips/delete',
319 pattern='/users/{user_id:\d+}/edit/ips/delete',
239 user_route_with_default=True) # enabled for default user too
320 user_route_with_default=True) # enabled for default user too
240
321
241 # user perms
322 # user perms
242 config.add_route(
323 config.add_route(
@@ -46,65 +46,53 b' class NavEntry(object):'
46 be removed as soon as we are fully migrated to pyramid.
46 be removed as soon as we are fully migrated to pyramid.
47 """
47 """
48
48
49 def __init__(self, key, name, view_name, pyramid=False):
49 def __init__(self, key, name, view_name):
50 self.key = key
50 self.key = key
51 self.name = name
51 self.name = name
52 self.view_name = view_name
52 self.view_name = view_name
53 self.pyramid = pyramid
54
53
55 def generate_url(self, request):
54 def generate_url(self, request):
56 if self.pyramid:
55 return request.route_path(self.view_name)
57 if hasattr(request, 'route_path'):
58 return request.route_path(self.view_name)
59 else:
60 # TODO: johbo: Remove this after migrating to pyramid.
61 # We need the pyramid request here to generate URLs to pyramid
62 # views from within pylons views.
63 from pyramid.threadlocal import get_current_request
64 pyramid_request = get_current_request()
65 return pyramid_request.route_path(self.view_name)
66 else:
67 from pylons import url
68 return url(self.view_name)
69
56
70 def get_localized_name(self, request):
57 def get_localized_name(self, request):
71 if hasattr(request, 'translate'):
58 return request.translate(self.name)
72 return request.translate(self.name)
73 else:
74 # TODO(marcink): Remove this after migrating to pyramid
75 from pyramid.threadlocal import get_current_request
76 pyramid_request = get_current_request()
77 return pyramid_request.translate(self.name)
78
59
79
60
80 @implementer(IAdminNavigationRegistry)
61 @implementer(IAdminNavigationRegistry)
81 class NavigationRegistry(object):
62 class NavigationRegistry(object):
82
63
83 _base_entries = [
64 _base_entries = [
84 NavEntry('global', _('Global'), 'admin_settings_global'),
65 NavEntry('global', _('Global'),
85 NavEntry('vcs', _('VCS'), 'admin_settings_vcs'),
66 'admin_settings_global'),
86 NavEntry('visual', _('Visual'), 'admin_settings_visual'),
67 NavEntry('vcs', _('VCS'),
87 NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'),
68 'admin_settings_vcs'),
69 NavEntry('visual', _('Visual'),
70 'admin_settings_visual'),
71 NavEntry('mapping', _('Remap and Rescan'),
72 'admin_settings_mapping'),
88 NavEntry('issuetracker', _('Issue Tracker'),
73 NavEntry('issuetracker', _('Issue Tracker'),
89 'admin_settings_issuetracker'),
74 'admin_settings_issuetracker'),
90 NavEntry('email', _('Email'), 'admin_settings_email'),
75 NavEntry('email', _('Email'),
91 NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
76 'admin_settings_email'),
92 NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
77 NavEntry('hooks', _('Hooks'),
93
78 'admin_settings_hooks'),
79 NavEntry('search', _('Full Text Search'),
80 'admin_settings_search'),
94 NavEntry('integrations', _('Integrations'),
81 NavEntry('integrations', _('Integrations'),
95 'global_integrations_home', pyramid=True),
82 'global_integrations_home'),
96 NavEntry('system', _('System Info'),
83 NavEntry('system', _('System Info'),
97 'admin_settings_system', pyramid=True),
84 'admin_settings_system'),
98 NavEntry('process_management', _('Processes'),
85 NavEntry('process_management', _('Processes'),
99 'admin_settings_process_management', pyramid=True),
86 'admin_settings_process_management'),
100 NavEntry('sessions', _('User Sessions'),
87 NavEntry('sessions', _('User Sessions'),
101 'admin_settings_sessions', pyramid=True),
88 'admin_settings_sessions'),
102 NavEntry('open_source', _('Open Source Licenses'),
89 NavEntry('open_source', _('Open Source Licenses'),
103 'admin_settings_open_source', pyramid=True),
90 'admin_settings_open_source'),
104
91
105 ]
92 ]
106
93
107 _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs')
94 _labs_entry = NavEntry('labs', _('Labs'),
95 'admin_settings_labs')
108
96
109 def __init__(self, labs_active=False):
97 def __init__(self, labs_active=False):
110 self._registered_entries = collections.OrderedDict()
98 self._registered_entries = collections.OrderedDict()
@@ -27,7 +27,7 b' from rhodecode.lib.utils2 import md5'
27 from rhodecode.model.db import RhodeCodeUi
27 from rhodecode.model.db import RhodeCodeUi
28 from rhodecode.model.meta import Session
28 from rhodecode.model.meta import Session
29 from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel
29 from rhodecode.model.settings import SettingsModel, IssueTrackerSettingsModel
30 from rhodecode.tests import url, assert_session_flash
30 from rhodecode.tests import assert_session_flash
31 from rhodecode.tests.utils import AssertResponse
31 from rhodecode.tests.utils import AssertResponse
32
32
33
33
@@ -35,6 +35,78 b' UPDATE_DATA_QUALNAME = ('
35 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
35 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
36
36
37
37
38 def route_path(name, params=None, **kwargs):
39 import urllib
40 from rhodecode.apps._base import ADMIN_PREFIX
41
42 base_url = {
43
44 'admin_settings':
45 ADMIN_PREFIX +'/settings',
46 'admin_settings_update':
47 ADMIN_PREFIX + '/settings/update',
48 'admin_settings_global':
49 ADMIN_PREFIX + '/settings/global',
50 'admin_settings_global_update':
51 ADMIN_PREFIX + '/settings/global/update',
52 'admin_settings_vcs':
53 ADMIN_PREFIX + '/settings/vcs',
54 'admin_settings_vcs_update':
55 ADMIN_PREFIX + '/settings/vcs/update',
56 'admin_settings_vcs_svn_pattern_delete':
57 ADMIN_PREFIX + '/settings/vcs/svn_pattern_delete',
58 'admin_settings_mapping':
59 ADMIN_PREFIX + '/settings/mapping',
60 'admin_settings_mapping_update':
61 ADMIN_PREFIX + '/settings/mapping/update',
62 'admin_settings_visual':
63 ADMIN_PREFIX + '/settings/visual',
64 'admin_settings_visual_update':
65 ADMIN_PREFIX + '/settings/visual/update',
66 'admin_settings_issuetracker':
67 ADMIN_PREFIX + '/settings/issue-tracker',
68 'admin_settings_issuetracker_update':
69 ADMIN_PREFIX + '/settings/issue-tracker/update',
70 'admin_settings_issuetracker_test':
71 ADMIN_PREFIX + '/settings/issue-tracker/test',
72 'admin_settings_issuetracker_delete':
73 ADMIN_PREFIX + '/settings/issue-tracker/delete',
74 'admin_settings_email':
75 ADMIN_PREFIX + '/settings/email',
76 'admin_settings_email_update':
77 ADMIN_PREFIX + '/settings/email/update',
78 'admin_settings_hooks':
79 ADMIN_PREFIX + '/settings/hooks',
80 'admin_settings_hooks_update':
81 ADMIN_PREFIX + '/settings/hooks/update',
82 'admin_settings_hooks_delete':
83 ADMIN_PREFIX + '/settings/hooks/delete',
84 'admin_settings_search':
85 ADMIN_PREFIX + '/settings/search',
86 'admin_settings_labs':
87 ADMIN_PREFIX + '/settings/labs',
88 'admin_settings_labs_update':
89 ADMIN_PREFIX + '/settings/labs/update',
90
91 'admin_settings_sessions':
92 ADMIN_PREFIX + '/settings/sessions',
93 'admin_settings_sessions_cleanup':
94 ADMIN_PREFIX + '/settings/sessions/cleanup',
95 'admin_settings_system':
96 ADMIN_PREFIX + '/settings/system',
97 'admin_settings_system_update':
98 ADMIN_PREFIX + '/settings/system/updates',
99 'admin_settings_open_source':
100 ADMIN_PREFIX + '/settings/open_source',
101
102
103 }[name].format(**kwargs)
104
105 if params:
106 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
107 return base_url
108
109
38 @pytest.mark.usefixtures('autologin_user', 'app')
110 @pytest.mark.usefixtures('autologin_user', 'app')
39 class TestAdminSettingsController(object):
111 class TestAdminSettingsController(object):
40
112
@@ -47,12 +119,12 b' class TestAdminSettingsController(object'
47 'admin_settings_hooks',
119 'admin_settings_hooks',
48 'admin_settings_search',
120 'admin_settings_search',
49 ])
121 ])
50 def test_simple_get(self, urlname, app):
122 def test_simple_get(self, urlname):
51 app.get(url(urlname))
123 self.app.get(route_path(urlname))
52
124
53 def test_create_custom_hook(self, csrf_token):
125 def test_create_custom_hook(self, csrf_token):
54 response = self.app.post(
126 response = self.app.post(
55 url('admin_settings_hooks'),
127 route_path('admin_settings_hooks_update'),
56 params={
128 params={
57 'new_hook_ui_key': 'test_hooks_1',
129 'new_hook_ui_key': 'test_hooks_1',
58 'new_hook_ui_value': 'cd /tmp',
130 'new_hook_ui_value': 'cd /tmp',
@@ -64,7 +136,7 b' class TestAdminSettingsController(object'
64
136
65 def test_create_custom_hook_delete(self, csrf_token):
137 def test_create_custom_hook_delete(self, csrf_token):
66 response = self.app.post(
138 response = self.app.post(
67 url('admin_settings_hooks'),
139 route_path('admin_settings_hooks_update'),
68 params={
140 params={
69 'new_hook_ui_key': 'test_hooks_2',
141 'new_hook_ui_key': 'test_hooks_2',
70 'new_hook_ui_value': 'cd /tmp2',
142 'new_hook_ui_value': 'cd /tmp2',
@@ -78,9 +150,9 b' class TestAdminSettingsController(object'
78
150
79 # delete
151 # delete
80 self.app.post(
152 self.app.post(
81 url('admin_settings_hooks'),
153 route_path('admin_settings_hooks_delete'),
82 params={'hook_id': hook_id, 'csrf_token': csrf_token})
154 params={'hook_id': hook_id, 'csrf_token': csrf_token})
83 response = self.app.get(url('admin_settings_hooks'))
155 response = self.app.get(route_path('admin_settings_hooks'))
84 response.mustcontain(no=['test_hooks_2'])
156 response.mustcontain(no=['test_hooks_2'])
85 response.mustcontain(no=['cd /tmp2'])
157 response.mustcontain(no=['cd /tmp2'])
86
158
@@ -135,7 +207,6 b' class TestAdminSettingsGlobal(object):'
135
207
136 def test_title_change(self, csrf_token):
208 def test_title_change(self, csrf_token):
137 old_title = 'RhodeCode'
209 old_title = 'RhodeCode'
138 new_title = old_title + '_changed'
139
210
140 for new_title in ['Changed', 'Żółwik', old_title]:
211 for new_title in ['Changed', 'Żółwik', old_title]:
141 response = self.post_and_verify_settings({
212 response = self.post_and_verify_settings({
@@ -161,7 +232,8 b' class TestAdminSettingsGlobal(object):'
161 'rhodecode_personal_repo_group_pattern': '${username}',
232 'rhodecode_personal_repo_group_pattern': '${username}',
162 }
233 }
163 params.update(settings)
234 params.update(settings)
164 response = self.app.post(url('admin_settings_global'), params=params)
235 response = self.app.post(
236 route_path('admin_settings_global_update'), params=params)
165
237
166 assert_session_flash(response, 'Updated application settings')
238 assert_session_flash(response, 'Updated application settings')
167 app_settings = SettingsModel().get_all_settings()
239 app_settings = SettingsModel().get_all_settings()
@@ -175,8 +247,8 b' class TestAdminSettingsGlobal(object):'
175 @pytest.mark.usefixtures('autologin_user', 'app')
247 @pytest.mark.usefixtures('autologin_user', 'app')
176 class TestAdminSettingsVcs(object):
248 class TestAdminSettingsVcs(object):
177
249
178 def test_contains_svn_default_patterns(self, app):
250 def test_contains_svn_default_patterns(self):
179 response = app.get(url('admin_settings_vcs'))
251 response = self.app.get(route_path('admin_settings_vcs'))
180 expected_patterns = [
252 expected_patterns = [
181 '/trunk',
253 '/trunk',
182 '/branches/*',
254 '/branches/*',
@@ -186,7 +258,7 b' class TestAdminSettingsVcs(object):'
186 response.mustcontain(pattern)
258 response.mustcontain(pattern)
187
259
188 def test_add_new_svn_branch_and_tag_pattern(
260 def test_add_new_svn_branch_and_tag_pattern(
189 self, app, backend_svn, form_defaults, disable_sql_cache,
261 self, backend_svn, form_defaults, disable_sql_cache,
190 csrf_token):
262 csrf_token):
191 form_defaults.update({
263 form_defaults.update({
192 'new_svn_branch': '/exp/branches/*',
264 'new_svn_branch': '/exp/branches/*',
@@ -194,8 +266,9 b' class TestAdminSettingsVcs(object):'
194 'csrf_token': csrf_token,
266 'csrf_token': csrf_token,
195 })
267 })
196
268
197 response = app.post(
269 response = self.app.post(
198 url('admin_settings_vcs'), params=form_defaults, status=302)
270 route_path('admin_settings_vcs_update'),
271 params=form_defaults, status=302)
199 response = response.follow()
272 response = response.follow()
200
273
201 # Expect to find the new values on the page
274 # Expect to find the new values on the page
@@ -208,12 +281,12 b' class TestAdminSettingsVcs(object):'
208 assert 'important_tags/v0.5' in repo.tags
281 assert 'important_tags/v0.5' in repo.tags
209
282
210 def test_add_same_svn_value_twice_shows_an_error_message(
283 def test_add_same_svn_value_twice_shows_an_error_message(
211 self, app, form_defaults, csrf_token, settings_util):
284 self, form_defaults, csrf_token, settings_util):
212 settings_util.create_rhodecode_ui('vcs_svn_branch', '/test')
285 settings_util.create_rhodecode_ui('vcs_svn_branch', '/test')
213 settings_util.create_rhodecode_ui('vcs_svn_tag', '/test')
286 settings_util.create_rhodecode_ui('vcs_svn_tag', '/test')
214
287
215 response = app.post(
288 response = self.app.post(
216 url('admin_settings_vcs'),
289 route_path('admin_settings_vcs_update'),
217 params={
290 params={
218 'paths_root_path': form_defaults['paths_root_path'],
291 'paths_root_path': form_defaults['paths_root_path'],
219 'new_svn_branch': '/test',
292 'new_svn_branch': '/test',
@@ -230,14 +303,13 b' class TestAdminSettingsVcs(object):'
230 'vcs_svn_tag',
303 'vcs_svn_tag',
231 ])
304 ])
232 def test_delete_svn_patterns(
305 def test_delete_svn_patterns(
233 self, section, app, csrf_token, settings_util):
306 self, section, csrf_token, settings_util):
234 setting = settings_util.create_rhodecode_ui(
307 setting = settings_util.create_rhodecode_ui(
235 section, '/test_delete', cleanup=False)
308 section, '/test_delete', cleanup=False)
236
309
237 app.post(
310 self.app.post(
238 url('admin_settings_vcs'),
311 route_path('admin_settings_vcs_svn_pattern_delete'),
239 params={
312 params={
240 '_method': 'delete',
241 'delete_svn_pattern': setting.ui_id,
313 'delete_svn_pattern': setting.ui_id,
242 'csrf_token': csrf_token},
314 'csrf_token': csrf_token},
243 headers={'X-REQUESTED-WITH': 'XMLHttpRequest'})
315 headers={'X-REQUESTED-WITH': 'XMLHttpRequest'})
@@ -246,25 +318,24 b' class TestAdminSettingsVcs(object):'
246 'vcs_svn_branch',
318 'vcs_svn_branch',
247 'vcs_svn_tag',
319 'vcs_svn_tag',
248 ])
320 ])
249 def test_delete_svn_patterns_raises_400_when_no_xhr(
321 def test_delete_svn_patterns_raises_404_when_no_xhr(
250 self, section, app, csrf_token, settings_util):
322 self, section, csrf_token, settings_util):
251 setting = settings_util.create_rhodecode_ui(section, '/test_delete')
323 setting = settings_util.create_rhodecode_ui(section, '/test_delete')
252
324
253 app.post(
325 self.app.post(
254 url('admin_settings_vcs'),
326 route_path('admin_settings_vcs_svn_pattern_delete'),
255 params={
327 params={
256 '_method': 'delete',
257 'delete_svn_pattern': setting.ui_id,
328 'delete_svn_pattern': setting.ui_id,
258 'csrf_token': csrf_token},
329 'csrf_token': csrf_token},
259 status=400)
330 status=404)
260
331
261 def test_extensions_hgsubversion(self, app, form_defaults, csrf_token):
332 def test_extensions_hgsubversion(self, form_defaults, csrf_token):
262 form_defaults.update({
333 form_defaults.update({
263 'csrf_token': csrf_token,
334 'csrf_token': csrf_token,
264 'extensions_hgsubversion': 'True',
335 'extensions_hgsubversion': 'True',
265 })
336 })
266 response = app.post(
337 response = self.app.post(
267 url('admin_settings_vcs'),
338 route_path('admin_settings_vcs_update'),
268 params=form_defaults,
339 params=form_defaults,
269 status=302)
340 status=302)
270
341
@@ -275,13 +346,13 b' class TestAdminSettingsVcs(object):'
275 'value="True" checked="checked" />')
346 'value="True" checked="checked" />')
276 response.mustcontain(extensions_input)
347 response.mustcontain(extensions_input)
277
348
278 def test_extensions_hgevolve(self, app, form_defaults, csrf_token):
349 def test_extensions_hgevolve(self, form_defaults, csrf_token):
279 form_defaults.update({
350 form_defaults.update({
280 'csrf_token': csrf_token,
351 'csrf_token': csrf_token,
281 'extensions_evolve': 'True',
352 'extensions_evolve': 'True',
282 })
353 })
283 response = app.post(
354 response = self.app.post(
284 url('admin_settings_vcs'),
355 route_path('admin_settings_vcs_update'),
285 params=form_defaults,
356 params=form_defaults,
286 status=302)
357 status=302)
287
358
@@ -292,20 +363,19 b' class TestAdminSettingsVcs(object):'
292 'value="True" checked="checked" />')
363 'value="True" checked="checked" />')
293 response.mustcontain(extensions_input)
364 response.mustcontain(extensions_input)
294
365
295 def test_has_a_section_for_pull_request_settings(self, app):
366 def test_has_a_section_for_pull_request_settings(self):
296 response = app.get(url('admin_settings_vcs'))
367 response = self.app.get(route_path('admin_settings_vcs'))
297 response.mustcontain('Pull Request Settings')
368 response.mustcontain('Pull Request Settings')
298
369
299 def test_has_an_input_for_invalidation_of_inline_comments(
370 def test_has_an_input_for_invalidation_of_inline_comments(self):
300 self, app):
371 response = self.app.get(route_path('admin_settings_vcs'))
301 response = app.get(url('admin_settings_vcs'))
302 assert_response = AssertResponse(response)
372 assert_response = AssertResponse(response)
303 assert_response.one_element_exists(
373 assert_response.one_element_exists(
304 '[name=rhodecode_use_outdated_comments]')
374 '[name=rhodecode_use_outdated_comments]')
305
375
306 @pytest.mark.parametrize('new_value', [True, False])
376 @pytest.mark.parametrize('new_value', [True, False])
307 def test_allows_to_change_invalidation_of_inline_comments(
377 def test_allows_to_change_invalidation_of_inline_comments(
308 self, app, form_defaults, csrf_token, new_value):
378 self, form_defaults, csrf_token, new_value):
309 setting_key = 'use_outdated_comments'
379 setting_key = 'use_outdated_comments'
310 setting = SettingsModel().create_or_update_setting(
380 setting = SettingsModel().create_or_update_setting(
311 setting_key, not new_value, 'bool')
381 setting_key, not new_value, 'bool')
@@ -316,8 +386,8 b' class TestAdminSettingsVcs(object):'
316 'csrf_token': csrf_token,
386 'csrf_token': csrf_token,
317 'rhodecode_use_outdated_comments': str(new_value),
387 'rhodecode_use_outdated_comments': str(new_value),
318 })
388 })
319 response = app.post(
389 response = self.app.post(
320 url('admin_settings_vcs'),
390 route_path('admin_settings_vcs_update'),
321 params=form_defaults,
391 params=form_defaults,
322 status=302)
392 status=302)
323 response = response.follow()
393 response = response.follow()
@@ -326,7 +396,7 b' class TestAdminSettingsVcs(object):'
326
396
327 @pytest.mark.parametrize('new_value', [True, False])
397 @pytest.mark.parametrize('new_value', [True, False])
328 def test_allows_to_change_hg_rebase_merge_strategy(
398 def test_allows_to_change_hg_rebase_merge_strategy(
329 self, app, form_defaults, csrf_token, new_value):
399 self, form_defaults, csrf_token, new_value):
330 setting_key = 'hg_use_rebase_for_merging'
400 setting_key = 'hg_use_rebase_for_merging'
331
401
332 form_defaults.update({
402 form_defaults.update({
@@ -336,8 +406,8 b' class TestAdminSettingsVcs(object):'
336
406
337 with mock.patch.dict(
407 with mock.patch.dict(
338 rhodecode.CONFIG, {'labs_settings_active': 'true'}):
408 rhodecode.CONFIG, {'labs_settings_active': 'true'}):
339 app.post(
409 self.app.post(
340 url('admin_settings_vcs'),
410 route_path('admin_settings_vcs_update'),
341 params=form_defaults,
411 params=form_defaults,
342 status=302)
412 status=302)
343
413
@@ -353,9 +423,8 b' class TestAdminSettingsVcs(object):'
353
423
354 @pytest.fixture
424 @pytest.fixture
355 def form_defaults(self):
425 def form_defaults(self):
356 from rhodecode.controllers.admin.settings import SettingsController
426 from rhodecode.apps.admin.views.settings import AdminSettingsView
357 controller = SettingsController()
427 return AdminSettingsView._form_defaults()
358 return controller._form_defaults()
359
428
360 # TODO: johbo: What we really want is to checkpoint before a test run and
429 # TODO: johbo: What we really want is to checkpoint before a test run and
361 # reset the session afterwards.
430 # reset the session afterwards.
@@ -374,14 +443,16 b' class TestAdminSettingsVcs(object):'
374 @pytest.mark.usefixtures('autologin_user', 'app')
443 @pytest.mark.usefixtures('autologin_user', 'app')
375 class TestLabsSettings(object):
444 class TestLabsSettings(object):
376 def test_get_settings_page_disabled(self):
445 def test_get_settings_page_disabled(self):
377 with mock.patch.dict(rhodecode.CONFIG,
446 with mock.patch.dict(
378 {'labs_settings_active': 'false'}):
447 rhodecode.CONFIG, {'labs_settings_active': 'false'}):
379 response = self.app.get(url('admin_settings_labs'), status=302)
380
448
381 assert response.location.endswith(url('admin_settings'))
449 response = self.app.get(
450 route_path('admin_settings_labs'), status=302)
451
452 assert response.location.endswith(route_path('admin_settings'))
382
453
383 def test_get_settings_page_enabled(self):
454 def test_get_settings_page_enabled(self):
384 from rhodecode.controllers.admin import settings
455 from rhodecode.apps.admin.views import settings
385 lab_settings = [
456 lab_settings = [
386 settings.LabSetting(
457 settings.LabSetting(
387 key='rhodecode_bool',
458 key='rhodecode_bool',
@@ -401,7 +472,7 b' class TestLabsSettings(object):'
401 with mock.patch.dict(rhodecode.CONFIG,
472 with mock.patch.dict(rhodecode.CONFIG,
402 {'labs_settings_active': 'true'}):
473 {'labs_settings_active': 'true'}):
403 with mock.patch.object(settings, '_LAB_SETTINGS', lab_settings):
474 with mock.patch.object(settings, '_LAB_SETTINGS', lab_settings):
404 response = self.app.get(url('admin_settings_labs'))
475 response = self.app.get(route_path('admin_settings_labs'))
405
476
406 assert '<label>bool group:</label>' in response
477 assert '<label>bool group:</label>' in response
407 assert '<label for="rhodecode_bool">bool label</label>' in response
478 assert '<label for="rhodecode_bool">bool label</label>' in response
@@ -417,9 +488,6 b' class TestLabsSettings(object):'
417 @pytest.mark.usefixtures('app')
488 @pytest.mark.usefixtures('app')
418 class TestOpenSourceLicenses(object):
489 class TestOpenSourceLicenses(object):
419
490
420 def _get_url(self):
421 return ADMIN_PREFIX + '/settings/open_source'
422
423 def test_records_are_displayed(self, autologin_user):
491 def test_records_are_displayed(self, autologin_user):
424 sample_licenses = {
492 sample_licenses = {
425 "python2.7-pytest-2.7.1": {
493 "python2.7-pytest-2.7.1": {
@@ -433,7 +501,8 b' class TestOpenSourceLicenses(object):'
433 'rhodecode.apps.admin.views.open_source_licenses.read_opensource_licenses',
501 'rhodecode.apps.admin.views.open_source_licenses.read_opensource_licenses',
434 return_value=sample_licenses)
502 return_value=sample_licenses)
435 with read_licenses_patch:
503 with read_licenses_patch:
436 response = self.app.get(self._get_url(), status=200)
504 response = self.app.get(
505 route_path('admin_settings_open_source'), status=200)
437
506
438 assert_response = AssertResponse(response)
507 assert_response = AssertResponse(response)
439 assert_response.element_contains(
508 assert_response.element_contains(
@@ -444,29 +513,25 b' class TestOpenSourceLicenses(object):'
444 assert_response.element_contains('.panel-body', license)
513 assert_response.element_contains('.panel-body', license)
445
514
446 def test_records_can_be_read(self, autologin_user):
515 def test_records_can_be_read(self, autologin_user):
447 response = self.app.get(self._get_url(), status=200)
516 response = self.app.get(
517 route_path('admin_settings_open_source'), status=200)
448 assert_response = AssertResponse(response)
518 assert_response = AssertResponse(response)
449 assert_response.element_contains(
519 assert_response.element_contains(
450 '.panel-heading', 'Licenses of Third Party Packages')
520 '.panel-heading', 'Licenses of Third Party Packages')
451
521
452 def test_forbidden_when_normal_user(self, autologin_regular_user):
522 def test_forbidden_when_normal_user(self, autologin_regular_user):
453 self.app.get(self._get_url(), status=404)
523 self.app.get(
524 route_path('admin_settings_open_source'), status=404)
454
525
455
526
456 @pytest.mark.usefixtures('app')
527 @pytest.mark.usefixtures('app')
457 class TestUserSessions(object):
528 class TestUserSessions(object):
458
529
459 def _get_url(self, name='admin_settings_sessions'):
460 return {
461 'admin_settings_sessions': ADMIN_PREFIX + '/settings/sessions',
462 'admin_settings_sessions_cleanup': ADMIN_PREFIX + '/settings/sessions/cleanup'
463 }[name]
464
465 def test_forbidden_when_normal_user(self, autologin_regular_user):
530 def test_forbidden_when_normal_user(self, autologin_regular_user):
466 self.app.get(self._get_url(), status=404)
531 self.app.get(route_path('admin_settings_sessions'), status=404)
467
532
468 def test_show_sessions_page(self, autologin_user):
533 def test_show_sessions_page(self, autologin_user):
469 response = self.app.get(self._get_url(), status=200)
534 response = self.app.get(route_path('admin_settings_sessions'), status=200)
470 response.mustcontain('file')
535 response.mustcontain('file')
471
536
472 def test_cleanup_old_sessions(self, autologin_user, csrf_token):
537 def test_cleanup_old_sessions(self, autologin_user, csrf_token):
@@ -476,24 +541,19 b' class TestUserSessions(object):'
476 'expire_days': '60'
541 'expire_days': '60'
477 }
542 }
478 response = self.app.post(
543 response = self.app.post(
479 self._get_url('admin_settings_sessions_cleanup'), params=post_data,
544 route_path('admin_settings_sessions_cleanup'), params=post_data,
480 status=302)
545 status=302)
481 assert_session_flash(response, 'Cleaned up old sessions')
546 assert_session_flash(response, 'Cleaned up old sessions')
482
547
483
548
484 @pytest.mark.usefixtures('app')
549 @pytest.mark.usefixtures('app')
485 class TestAdminSystemInfo(object):
550 class TestAdminSystemInfo(object):
486 def _get_url(self, name='admin_settings_system'):
487 return {
488 'admin_settings_system': ADMIN_PREFIX + '/settings/system',
489 'admin_settings_system_update': ADMIN_PREFIX + '/settings/system/updates',
490 }[name]
491
551
492 def test_forbidden_when_normal_user(self, autologin_regular_user):
552 def test_forbidden_when_normal_user(self, autologin_regular_user):
493 self.app.get(self._get_url(), status=404)
553 self.app.get(route_path('admin_settings_system'), status=404)
494
554
495 def test_system_info_page(self, autologin_user):
555 def test_system_info_page(self, autologin_user):
496 response = self.app.get(self._get_url())
556 response = self.app.get(route_path('admin_settings_system'))
497 response.mustcontain('RhodeCode Community Edition, version {}'.format(
557 response.mustcontain('RhodeCode Community Edition, version {}'.format(
498 rhodecode.__version__))
558 rhodecode.__version__))
499
559
@@ -511,7 +571,7 b' class TestAdminSystemInfo(object):'
511 ]
571 ]
512 }
572 }
513 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
573 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
514 response = self.app.get(self._get_url('admin_settings_system_update'))
574 response = self.app.get(route_path('admin_settings_system_update'))
515 response.mustcontain('A <b>new version</b> is available')
575 response.mustcontain('A <b>new version</b> is available')
516
576
517 def test_system_update_nothing_new(self, autologin_user):
577 def test_system_update_nothing_new(self, autologin_user):
@@ -524,13 +584,13 b' class TestAdminSystemInfo(object):'
524 ]
584 ]
525 }
585 }
526 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
586 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
527 response = self.app.get(self._get_url('admin_settings_system_update'))
587 response = self.app.get(route_path('admin_settings_system_update'))
528 response.mustcontain(
588 response.mustcontain(
529 'You already have the <b>latest</b> stable version.')
589 'You already have the <b>latest</b> stable version.')
530
590
531 def test_system_update_bad_response(self, autologin_user):
591 def test_system_update_bad_response(self, autologin_user):
532 with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
592 with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
533 response = self.app.get(self._get_url('admin_settings_system_update'))
593 response = self.app.get(route_path('admin_settings_system_update'))
534 response.mustcontain(
594 response.mustcontain(
535 'Bad data sent from update server')
595 'Bad data sent from update server')
536
596
@@ -542,12 +602,12 b' class TestAdminSettingsIssueTracker(obje'
542 PATTERN_KEY = RC_PREFIX + SHORT_PATTERN_KEY
602 PATTERN_KEY = RC_PREFIX + SHORT_PATTERN_KEY
543
603
544 def test_issuetracker_index(self, autologin_user):
604 def test_issuetracker_index(self, autologin_user):
545 response = self.app.get(url('admin_settings_issuetracker'))
605 response = self.app.get(route_path('admin_settings_issuetracker'))
546 assert response.status_code == 200
606 assert response.status_code == 200
547
607
548 def test_add_empty_issuetracker_pattern(
608 def test_add_empty_issuetracker_pattern(
549 self, request, autologin_user, csrf_token):
609 self, request, autologin_user, csrf_token):
550 post_url = url('admin_settings_issuetracker_save')
610 post_url = route_path('admin_settings_issuetracker_update')
551 post_data = {
611 post_data = {
552 'csrf_token': csrf_token
612 'csrf_token': csrf_token
553 }
613 }
@@ -557,7 +617,7 b' class TestAdminSettingsIssueTracker(obje'
557 self, request, autologin_user, csrf_token):
617 self, request, autologin_user, csrf_token):
558 pattern = 'issuetracker_pat'
618 pattern = 'issuetracker_pat'
559 another_pattern = pattern+'1'
619 another_pattern = pattern+'1'
560 post_url = url('admin_settings_issuetracker_save')
620 post_url = route_path('admin_settings_issuetracker_update')
561 post_data = {
621 post_data = {
562 'new_pattern_pattern_0': pattern,
622 'new_pattern_pattern_0': pattern,
563 'new_pattern_url_0': 'url',
623 'new_pattern_url_0': 'url',
@@ -600,7 +660,7 b' class TestAdminSettingsIssueTracker(obje'
600 SettingsModel().create_or_update_setting(
660 SettingsModel().create_or_update_setting(
601 self.SHORT_PATTERN_KEY+old_uid, old_pattern, 'unicode')
661 self.SHORT_PATTERN_KEY+old_uid, old_pattern, 'unicode')
602
662
603 post_url = url('admin_settings_issuetracker_save')
663 post_url = route_path('admin_settings_issuetracker_update')
604 post_data = {
664 post_data = {
605 'new_pattern_pattern_0': pattern,
665 'new_pattern_pattern_0': pattern,
606 'new_pattern_url_0': 'url',
666 'new_pattern_url_0': 'url',
@@ -634,7 +694,7 b' class TestAdminSettingsIssueTracker(obje'
634 settings_util.create_rhodecode_setting(
694 settings_util.create_rhodecode_setting(
635 desc_key, 'old description', 'unicode', cleanup=False)
695 desc_key, 'old description', 'unicode', cleanup=False)
636
696
637 post_url = url('admin_settings_issuetracker_save')
697 post_url = route_path('admin_settings_issuetracker_update')
638 post_data = {
698 post_data = {
639 'new_pattern_pattern_0': pattern,
699 'new_pattern_pattern_0': pattern,
640 'new_pattern_url_0': 'url',
700 'new_pattern_url_0': 'url',
@@ -659,7 +719,7 b' class TestAdminSettingsIssueTracker(obje'
659 settings_util.create_rhodecode_setting(
719 settings_util.create_rhodecode_setting(
660 self.SHORT_PATTERN_KEY+uid, pattern, 'unicode', cleanup=False)
720 self.SHORT_PATTERN_KEY+uid, pattern, 'unicode', cleanup=False)
661
721
662 post_url = url('admin_issuetracker_delete')
722 post_url = route_path('admin_settings_issuetracker_delete')
663 post_data = {
723 post_data = {
664 '_method': 'delete',
724 '_method': 'delete',
665 'uid': uid,
725 'uid': uid,
@@ -172,81 +172,6 b' def make_map(config):'
172 # CUSTOM ROUTES HERE
172 # CUSTOM ROUTES HERE
173 #==========================================================================
173 #==========================================================================
174
174
175 # ADMIN SETTINGS ROUTES
176 with rmap.submapper(path_prefix=ADMIN_PREFIX,
177 controller='admin/settings') as m:
178
179 # default
180 m.connect('admin_settings', '/settings',
181 action='settings_global_update',
182 conditions={'method': ['POST']})
183 m.connect('admin_settings', '/settings',
184 action='settings_global', conditions={'method': ['GET']})
185
186 m.connect('admin_settings_vcs', '/settings/vcs',
187 action='settings_vcs_update',
188 conditions={'method': ['POST']})
189 m.connect('admin_settings_vcs', '/settings/vcs',
190 action='settings_vcs',
191 conditions={'method': ['GET']})
192 m.connect('admin_settings_vcs', '/settings/vcs',
193 action='delete_svn_pattern',
194 conditions={'method': ['DELETE']})
195
196 m.connect('admin_settings_mapping', '/settings/mapping',
197 action='settings_mapping_update',
198 conditions={'method': ['POST']})
199 m.connect('admin_settings_mapping', '/settings/mapping',
200 action='settings_mapping', conditions={'method': ['GET']})
201
202 m.connect('admin_settings_global', '/settings/global',
203 action='settings_global_update',
204 conditions={'method': ['POST']})
205 m.connect('admin_settings_global', '/settings/global',
206 action='settings_global', conditions={'method': ['GET']})
207
208 m.connect('admin_settings_visual', '/settings/visual',
209 action='settings_visual_update',
210 conditions={'method': ['POST']})
211 m.connect('admin_settings_visual', '/settings/visual',
212 action='settings_visual', conditions={'method': ['GET']})
213
214 m.connect('admin_settings_issuetracker',
215 '/settings/issue-tracker', action='settings_issuetracker',
216 conditions={'method': ['GET']})
217 m.connect('admin_settings_issuetracker_save',
218 '/settings/issue-tracker/save',
219 action='settings_issuetracker_save',
220 conditions={'method': ['POST']})
221 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
222 action='settings_issuetracker_test',
223 conditions={'method': ['POST']})
224 m.connect('admin_issuetracker_delete',
225 '/settings/issue-tracker/delete',
226 action='settings_issuetracker_delete',
227 conditions={'method': ['DELETE']})
228
229 m.connect('admin_settings_email', '/settings/email',
230 action='settings_email_update',
231 conditions={'method': ['POST']})
232 m.connect('admin_settings_email', '/settings/email',
233 action='settings_email', conditions={'method': ['GET']})
234
235 m.connect('admin_settings_hooks', '/settings/hooks',
236 action='settings_hooks_update',
237 conditions={'method': ['POST', 'DELETE']})
238 m.connect('admin_settings_hooks', '/settings/hooks',
239 action='settings_hooks', conditions={'method': ['GET']})
240
241 m.connect('admin_settings_search', '/settings/search',
242 action='settings_search', conditions={'method': ['GET']})
243
244 m.connect('admin_settings_labs', '/settings/labs',
245 action='settings_labs_update',
246 conditions={'method': ['POST']})
247 m.connect('admin_settings_labs', '/settings/labs',
248 action='settings_labs', conditions={'method': ['GET']})
249
250 # ADMIN MY ACCOUNT
175 # ADMIN MY ACCOUNT
251 with rmap.submapper(path_prefix=ADMIN_PREFIX,
176 with rmap.submapper(path_prefix=ADMIN_PREFIX,
252 controller='admin/my_account') as m:
177 controller='admin/my_account') as m:
@@ -51,6 +51,29 b' function registerRCRoutes() {'
51 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
51 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
52 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
52 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
53 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
53 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
54 pyroutes.register('admin_settings', '/_admin/settings', []);
55 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
56 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
57 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
58 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
59 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
60 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
61 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
62 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
63 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
64 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
65 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
66 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
67 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
68 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
69 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
70 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
71 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
72 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
73 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
74 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
75 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
76 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
54 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
77 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
55 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
78 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
56 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
79 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
@@ -27,7 +27,7 b''
27 %else:
27 %else:
28 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
28 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
29 &raquo;
29 &raquo;
30 ${h.link_to(_('Settings'),h.url('admin_settings'))}
30 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
31 &raquo;
31 &raquo;
32 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
32 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
33 &raquo;
33 &raquo;
@@ -13,7 +13,7 b''
13 %else:
13 %else:
14 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
14 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
15 &raquo;
15 &raquo;
16 ${h.link_to(_('Settings'),h.url('admin_settings'))}
16 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
17 %endif
17 %endif
18 %if c.current_IntegrationType:
18 %if c.current_IntegrationType:
19 &raquo;
19 &raquo;
@@ -18,7 +18,7 b''
18 %else:
18 %else:
19 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
19 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
20 &raquo;
20 &raquo;
21 ${h.link_to(_('Settings'),h.url('admin_settings'))}
21 ${h.link_to(_('Settings'),h.route_path('admin_settings'))}
22 &raquo;
22 &raquo;
23 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
23 ${h.link_to(_('Integrations'),request.route_url(route_name='global_integrations_home'))}
24 %endif
24 %endif
@@ -33,7 +33,7 b''
33 add authentication information to the URL: https://username:password@server.company.com/repo-name.
33 add authentication information to the URL: https://username:password@server.company.com/repo-name.
34 - The Git LFS/Mercurial Largefiles objects will not be imported.
34 - The Git LFS/Mercurial Largefiles objects will not be imported.
35 - For very large repositories, it's recommended to manually copy them into the
35 - For very large repositories, it's recommended to manually copy them into the
36 RhodeCode <a href="${h.url('admin_settings_vcs', anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.url('admin_settings_mapping')}">Remap and Rescan</a>.
36 RhodeCode <a href="${h.route_path('admin_settings_vcs', _anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.route_path('admin_settings_mapping')}">Remap and Rescan</a>.
37 </pre>
37 </pre>
38 </span>
38 </span>
39 </div>
39 </div>
@@ -34,7 +34,7 b''
34 <h3 class="panel-title">${_('Test Email')}</h3>
34 <h3 class="panel-title">${_('Test Email')}</h3>
35 </div>
35 </div>
36 <div class="panel-body">
36 <div class="panel-body">
37 ${h.secure_form(h.url('admin_settings_email'), request=request)}
37 ${h.secure_form(h.route_path('admin_settings_email_update'), request=request)}
38
38
39 <div class="field input">
39 <div class="field input">
40 ${h.text('test_email', size=60, placeholder=_('enter valid email'))}
40 ${h.text('test_email', size=60, placeholder=_('enter valid email'))}
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_global'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_global_update'), request=request)}
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-heading" id="branding-options">
4 <div class="panel-heading" id="branding-options">
@@ -28,7 +28,7 b''
28 </div>
28 </div>
29 <div class="panel-body">
29 <div class="panel-body">
30 % if c.visual.allow_custom_hooks_settings:
30 % if c.visual.allow_custom_hooks_settings:
31 ${h.secure_form(h.url('admin_settings_hooks'), request=request)}
31 ${h.secure_form(h.route_path('admin_settings_hooks_update'), request=request)}
32 <div class="form">
32 <div class="form">
33 <div class="fields">
33 <div class="fields">
34
34
@@ -74,13 +74,12 b''
74
74
75 <script type="text/javascript">
75 <script type="text/javascript">
76 function ajaxActionHook(hook_id,field_id) {
76 function ajaxActionHook(hook_id,field_id) {
77 var sUrl = "${h.url('admin_settings_hooks')}";
77 var sUrl = "${h.route_path('admin_settings_hooks_delete')}";
78 var callback = function (o) {
78 var callback = function (o) {
79 var elem = $("#"+field_id);
79 var elem = $("#"+field_id);
80 elem.remove();
80 elem.remove();
81 };
81 };
82 var postData = {
82 var postData = {
83 '_method': 'delete',
84 'hook_id': hook_id,
83 'hook_id': hook_id,
85 'csrf_token': CSRF_TOKEN
84 'csrf_token': CSRF_TOKEN
86 };
85 };
@@ -89,5 +88,5 b' function ajaxActionHook(hook_id,field_id'
89 .fail(function (data, textStatus, errorThrown) {
88 .fail(function (data, textStatus, errorThrown) {
90 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
89 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
91 });
90 });
92 };
91 }
93 </script>
92 </script>
@@ -5,11 +5,11 b''
5 <h3 class="panel-title">${_('Issue Tracker / Wiki Patterns')}</h3>
5 <h3 class="panel-title">${_('Issue Tracker / Wiki Patterns')}</h3>
6 </div>
6 </div>
7 <div class="panel-body">
7 <div class="panel-body">
8 ${h.secure_form(h.url('admin_settings_issuetracker_save'), request=request)}
8 ${h.secure_form(h.route_path('admin_settings_issuetracker_update'), request=request)}
9 ${its.issue_tracker_settings_table(
9 ${its.issue_tracker_settings_table(
10 patterns=c.issuetracker_entries.items(),
10 patterns=c.issuetracker_entries.items(),
11 form_url=h.url('admin_settings_issuetracker'),
11 form_url=h.route_path('admin_settings_issuetracker'),
12 delete_url=h.url('admin_issuetracker_delete')
12 delete_url=h.route_path('admin_settings_issuetracker_delete')
13 )}
13 )}
14 <div class="buttons">
14 <div class="buttons">
15 <button type="submit" class="btn btn-primary" id="save">${_('Save')}</button>
15 <button type="submit" class="btn btn-primary" id="save">${_('Save')}</button>
@@ -25,7 +25,7 b''
25 </div>
25 </div>
26 <div class="panel-body">
26 <div class="panel-body">
27 ${its.issue_tracker_new_row()}
27 ${its.issue_tracker_new_row()}
28 ${its.issue_tracker_settings_test(test_url=h.url('admin_issuetracker_test'))}
28 ${its.issue_tracker_settings_test(test_url=h.route_path('admin_settings_issuetracker_test'))}
29 </div>
29 </div>
30 </div>
30 </div>
31
31
@@ -3,7 +3,7 b''
3 <h3 class="panel-title">${_('Labs Settings')}</h3>
3 <h3 class="panel-title">${_('Labs Settings')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 ${h.secure_form(h.url('admin_settings_labs'), request=request)}
6 ${h.secure_form(h.route_path('admin_settings_labs_update'), request=request)}
7 <div class="form">
7 <div class="form">
8 <div class="fields">
8 <div class="fields">
9 % if not c.lab_settings:
9 % if not c.lab_settings:
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_mapping'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_mapping_update'), request=request)}
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-heading">
4 <div class="panel-heading">
@@ -1,6 +1,6 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.url('admin_settings_vcs'), 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='',
@@ -19,13 +19,12 b''
19 <script type="text/javascript">
19 <script type="text/javascript">
20
20
21 function ajaxDeletePattern(pattern_id, field_id) {
21 function ajaxDeletePattern(pattern_id, field_id) {
22 var sUrl = "${h.url('admin_settings_vcs')}";
22 var sUrl = "${h.route_path('admin_settings_vcs_svn_pattern_delete')}";
23 var callback = function (o) {
23 var callback = function (o) {
24 var elem = $("#"+field_id);
24 var elem = $("#"+field_id);
25 elem.remove();
25 elem.remove();
26 };
26 };
27 var postData = {
27 var postData = {
28 '_method': 'delete',
29 'delete_svn_pattern': pattern_id,
28 'delete_svn_pattern': pattern_id,
30 'csrf_token': CSRF_TOKEN
29 'csrf_token': CSRF_TOKEN
31 };
30 };
@@ -1,4 +1,4 b''
1 ${h.secure_form(h.url('admin_settings_visual'), request=request)}
1 ${h.secure_form(h.route_path('admin_settings_visual_update'), request=request)}
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-heading" id="general">
4 <div class="panel-heading" id="general">
@@ -81,7 +81,7 b''
81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
82 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
82 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
83 <li><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
83 <li><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
84 <li class="last"><a href="${h.url('admin_settings')}">${_('Settings')}</a></li>
84 <li class="last"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
85 </ul>
85 </ul>
86 </%def>
86 </%def>
87
87
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (631 lines changed) Show them Hide them
General Comments 0
You need to be logged in to leave comments. Login now