##// END OF EJS Templates
system-info: improve formatting of snapshot info page.
marcink -
r1114:4074d5a1 default
parent child Browse files
Show More
@@ -1,837 +1,838 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 """
22 """
23 settings controller for rhodecode admin
23 settings controller for rhodecode admin
24 """
24 """
25
25
26 import collections
26 import collections
27 import logging
27 import logging
28 import urllib2
28 import urllib2
29
29
30 import datetime
30 import datetime
31 import formencode
31 import formencode
32 from formencode import htmlfill
32 from formencode import htmlfill
33 import packaging.version
33 import packaging.version
34 from pylons import request, tmpl_context as c, url, config
34 from pylons import request, tmpl_context as c, url, config
35 from pylons.controllers.util import redirect
35 from pylons.controllers.util import redirect
36 from pylons.i18n.translation import _, lazy_ugettext
36 from pylons.i18n.translation import _, lazy_ugettext
37 from pyramid.threadlocal import get_current_registry
37 from pyramid.threadlocal import get_current_registry
38 from webob.exc import HTTPBadRequest
38 from webob.exc import HTTPBadRequest
39
39
40 import rhodecode
40 import rhodecode
41 from rhodecode.admin.navigation import navigation_list
41 from rhodecode.admin.navigation import navigation_list
42 from rhodecode.lib import auth
42 from rhodecode.lib import auth
43 from rhodecode.lib import helpers as h
43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
44 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
45 from rhodecode.lib.base import BaseController, render
45 from rhodecode.lib.base import BaseController, render
46 from rhodecode.lib.celerylib import tasks, run_task
46 from rhodecode.lib.celerylib import tasks, run_task
47 from rhodecode.lib.utils import repo2db_mapper
47 from rhodecode.lib.utils import repo2db_mapper
48 from rhodecode.lib.utils2 import (
48 from rhodecode.lib.utils2 import (
49 str2bool, safe_unicode, AttributeDict, safe_int)
49 str2bool, safe_unicode, AttributeDict, safe_int)
50 from rhodecode.lib.compat import OrderedDict
50 from rhodecode.lib.compat import OrderedDict
51 from rhodecode.lib.ext_json import json
51 from rhodecode.lib.ext_json import json
52 from rhodecode.lib.utils import jsonify
52 from rhodecode.lib.utils import jsonify
53
53
54 from rhodecode.model.db import RhodeCodeUi, Repository
54 from rhodecode.model.db import RhodeCodeUi, Repository
55 from rhodecode.model.forms import ApplicationSettingsForm, \
55 from rhodecode.model.forms import ApplicationSettingsForm, \
56 ApplicationUiSettingsForm, ApplicationVisualisationForm, \
56 ApplicationUiSettingsForm, ApplicationVisualisationForm, \
57 LabsSettingsForm, IssueTrackerPatternsForm
57 LabsSettingsForm, IssueTrackerPatternsForm
58 from rhodecode.model.repo_group import RepoGroupModel
58 from rhodecode.model.repo_group import RepoGroupModel
59
59
60 from rhodecode.model.scm import ScmModel
60 from rhodecode.model.scm import ScmModel
61 from rhodecode.model.notification import EmailNotificationModel
61 from rhodecode.model.notification import EmailNotificationModel
62 from rhodecode.model.meta import Session
62 from rhodecode.model.meta import Session
63 from rhodecode.model.settings import (
63 from rhodecode.model.settings import (
64 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
64 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
65 SettingsModel)
65 SettingsModel)
66
66
67 from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER
67 from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER
68 from rhodecode.svn_support.config_keys import generate_config
68 from rhodecode.svn_support.config_keys import generate_config
69
69
70
70
71 log = logging.getLogger(__name__)
71 log = logging.getLogger(__name__)
72
72
73
73
74 class SettingsController(BaseController):
74 class SettingsController(BaseController):
75 """REST Controller styled on the Atom Publishing Protocol"""
75 """REST Controller styled on the Atom Publishing Protocol"""
76 # To properly map this controller, ensure your config/routing.py
76 # To properly map this controller, ensure your config/routing.py
77 # file has a resource setup:
77 # file has a resource setup:
78 # map.resource('setting', 'settings', controller='admin/settings',
78 # map.resource('setting', 'settings', controller='admin/settings',
79 # path_prefix='/admin', name_prefix='admin_')
79 # path_prefix='/admin', name_prefix='admin_')
80
80
81 @LoginRequired()
81 @LoginRequired()
82 def __before__(self):
82 def __before__(self):
83 super(SettingsController, self).__before__()
83 super(SettingsController, self).__before__()
84 c.labs_active = str2bool(
84 c.labs_active = str2bool(
85 rhodecode.CONFIG.get('labs_settings_active', 'true'))
85 rhodecode.CONFIG.get('labs_settings_active', 'true'))
86 c.navlist = navigation_list(request)
86 c.navlist = navigation_list(request)
87
87
88 def _get_hg_ui_settings(self):
88 def _get_hg_ui_settings(self):
89 ret = RhodeCodeUi.query().all()
89 ret = RhodeCodeUi.query().all()
90
90
91 if not ret:
91 if not ret:
92 raise Exception('Could not get application ui settings !')
92 raise Exception('Could not get application ui settings !')
93 settings = {}
93 settings = {}
94 for each in ret:
94 for each in ret:
95 k = each.ui_key
95 k = each.ui_key
96 v = each.ui_value
96 v = each.ui_value
97 if k == '/':
97 if k == '/':
98 k = 'root_path'
98 k = 'root_path'
99
99
100 if k in ['push_ssl', 'publish']:
100 if k in ['push_ssl', 'publish']:
101 v = str2bool(v)
101 v = str2bool(v)
102
102
103 if k.find('.') != -1:
103 if k.find('.') != -1:
104 k = k.replace('.', '_')
104 k = k.replace('.', '_')
105
105
106 if each.ui_section in ['hooks', 'extensions']:
106 if each.ui_section in ['hooks', 'extensions']:
107 v = each.ui_active
107 v = each.ui_active
108
108
109 settings[each.ui_section + '_' + k] = v
109 settings[each.ui_section + '_' + k] = v
110 return settings
110 return settings
111
111
112 @HasPermissionAllDecorator('hg.admin')
112 @HasPermissionAllDecorator('hg.admin')
113 @auth.CSRFRequired()
113 @auth.CSRFRequired()
114 @jsonify
114 @jsonify
115 def delete_svn_pattern(self):
115 def delete_svn_pattern(self):
116 if not request.is_xhr:
116 if not request.is_xhr:
117 raise HTTPBadRequest()
117 raise HTTPBadRequest()
118
118
119 delete_pattern_id = request.POST.get('delete_svn_pattern')
119 delete_pattern_id = request.POST.get('delete_svn_pattern')
120 model = VcsSettingsModel()
120 model = VcsSettingsModel()
121 try:
121 try:
122 model.delete_global_svn_pattern(delete_pattern_id)
122 model.delete_global_svn_pattern(delete_pattern_id)
123 except SettingNotFound:
123 except SettingNotFound:
124 raise HTTPBadRequest()
124 raise HTTPBadRequest()
125
125
126 Session().commit()
126 Session().commit()
127 return True
127 return True
128
128
129 @HasPermissionAllDecorator('hg.admin')
129 @HasPermissionAllDecorator('hg.admin')
130 @auth.CSRFRequired()
130 @auth.CSRFRequired()
131 def settings_vcs_update(self):
131 def settings_vcs_update(self):
132 """POST /admin/settings: All items in the collection"""
132 """POST /admin/settings: All items in the collection"""
133 # url('admin_settings_vcs')
133 # url('admin_settings_vcs')
134 c.active = 'vcs'
134 c.active = 'vcs'
135
135
136 model = VcsSettingsModel()
136 model = VcsSettingsModel()
137 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
137 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
138 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
138 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
139
139
140 # TODO: Replace with request.registry after migrating to pyramid.
140 # TODO: Replace with request.registry after migrating to pyramid.
141 pyramid_settings = get_current_registry().settings
141 pyramid_settings = get_current_registry().settings
142 c.svn_proxy_generate_config = pyramid_settings[generate_config]
142 c.svn_proxy_generate_config = pyramid_settings[generate_config]
143
143
144 application_form = ApplicationUiSettingsForm()()
144 application_form = ApplicationUiSettingsForm()()
145
145
146 try:
146 try:
147 form_result = application_form.to_python(dict(request.POST))
147 form_result = application_form.to_python(dict(request.POST))
148 except formencode.Invalid as errors:
148 except formencode.Invalid as errors:
149 h.flash(
149 h.flash(
150 _("Some form inputs contain invalid data."),
150 _("Some form inputs contain invalid data."),
151 category='error')
151 category='error')
152 return htmlfill.render(
152 return htmlfill.render(
153 render('admin/settings/settings.html'),
153 render('admin/settings/settings.html'),
154 defaults=errors.value,
154 defaults=errors.value,
155 errors=errors.error_dict or {},
155 errors=errors.error_dict or {},
156 prefix_error=False,
156 prefix_error=False,
157 encoding="UTF-8",
157 encoding="UTF-8",
158 force_defaults=False
158 force_defaults=False
159 )
159 )
160
160
161 try:
161 try:
162 if c.visual.allow_repo_location_change:
162 if c.visual.allow_repo_location_change:
163 model.update_global_path_setting(
163 model.update_global_path_setting(
164 form_result['paths_root_path'])
164 form_result['paths_root_path'])
165
165
166 model.update_global_ssl_setting(form_result['web_push_ssl'])
166 model.update_global_ssl_setting(form_result['web_push_ssl'])
167 model.update_global_hook_settings(form_result)
167 model.update_global_hook_settings(form_result)
168
168
169 model.create_or_update_global_svn_settings(form_result)
169 model.create_or_update_global_svn_settings(form_result)
170 model.create_or_update_global_hg_settings(form_result)
170 model.create_or_update_global_hg_settings(form_result)
171 model.create_or_update_global_pr_settings(form_result)
171 model.create_or_update_global_pr_settings(form_result)
172 except Exception:
172 except Exception:
173 log.exception("Exception while updating settings")
173 log.exception("Exception while updating settings")
174 h.flash(_('Error occurred during updating '
174 h.flash(_('Error occurred during updating '
175 'application settings'), category='error')
175 'application settings'), category='error')
176 else:
176 else:
177 Session().commit()
177 Session().commit()
178 h.flash(_('Updated VCS settings'), category='success')
178 h.flash(_('Updated VCS settings'), category='success')
179 return redirect(url('admin_settings_vcs'))
179 return redirect(url('admin_settings_vcs'))
180
180
181 return htmlfill.render(
181 return htmlfill.render(
182 render('admin/settings/settings.html'),
182 render('admin/settings/settings.html'),
183 defaults=self._form_defaults(),
183 defaults=self._form_defaults(),
184 encoding="UTF-8",
184 encoding="UTF-8",
185 force_defaults=False)
185 force_defaults=False)
186
186
187 @HasPermissionAllDecorator('hg.admin')
187 @HasPermissionAllDecorator('hg.admin')
188 def settings_vcs(self):
188 def settings_vcs(self):
189 """GET /admin/settings: All items in the collection"""
189 """GET /admin/settings: All items in the collection"""
190 # url('admin_settings_vcs')
190 # url('admin_settings_vcs')
191 c.active = 'vcs'
191 c.active = 'vcs'
192 model = VcsSettingsModel()
192 model = VcsSettingsModel()
193 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
193 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
194 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
194 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
195
195
196 # TODO: Replace with request.registry after migrating to pyramid.
196 # TODO: Replace with request.registry after migrating to pyramid.
197 pyramid_settings = get_current_registry().settings
197 pyramid_settings = get_current_registry().settings
198 c.svn_proxy_generate_config = pyramid_settings[generate_config]
198 c.svn_proxy_generate_config = pyramid_settings[generate_config]
199
199
200 return htmlfill.render(
200 return htmlfill.render(
201 render('admin/settings/settings.html'),
201 render('admin/settings/settings.html'),
202 defaults=self._form_defaults(),
202 defaults=self._form_defaults(),
203 encoding="UTF-8",
203 encoding="UTF-8",
204 force_defaults=False)
204 force_defaults=False)
205
205
206 @HasPermissionAllDecorator('hg.admin')
206 @HasPermissionAllDecorator('hg.admin')
207 @auth.CSRFRequired()
207 @auth.CSRFRequired()
208 def settings_mapping_update(self):
208 def settings_mapping_update(self):
209 """POST /admin/settings/mapping: All items in the collection"""
209 """POST /admin/settings/mapping: All items in the collection"""
210 # url('admin_settings_mapping')
210 # url('admin_settings_mapping')
211 c.active = 'mapping'
211 c.active = 'mapping'
212 rm_obsolete = request.POST.get('destroy', False)
212 rm_obsolete = request.POST.get('destroy', False)
213 invalidate_cache = request.POST.get('invalidate', False)
213 invalidate_cache = request.POST.get('invalidate', False)
214 log.debug(
214 log.debug(
215 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
215 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
216
216
217 if invalidate_cache:
217 if invalidate_cache:
218 log.debug('invalidating all repositories cache')
218 log.debug('invalidating all repositories cache')
219 for repo in Repository.get_all():
219 for repo in Repository.get_all():
220 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
220 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
221
221
222 filesystem_repos = ScmModel().repo_scan()
222 filesystem_repos = ScmModel().repo_scan()
223 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
223 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
224 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
224 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
225 h.flash(_('Repositories successfully '
225 h.flash(_('Repositories successfully '
226 'rescanned added: %s ; removed: %s') %
226 'rescanned added: %s ; removed: %s') %
227 (_repr(added), _repr(removed)),
227 (_repr(added), _repr(removed)),
228 category='success')
228 category='success')
229 return redirect(url('admin_settings_mapping'))
229 return redirect(url('admin_settings_mapping'))
230
230
231 @HasPermissionAllDecorator('hg.admin')
231 @HasPermissionAllDecorator('hg.admin')
232 def settings_mapping(self):
232 def settings_mapping(self):
233 """GET /admin/settings/mapping: All items in the collection"""
233 """GET /admin/settings/mapping: All items in the collection"""
234 # url('admin_settings_mapping')
234 # url('admin_settings_mapping')
235 c.active = 'mapping'
235 c.active = 'mapping'
236
236
237 return htmlfill.render(
237 return htmlfill.render(
238 render('admin/settings/settings.html'),
238 render('admin/settings/settings.html'),
239 defaults=self._form_defaults(),
239 defaults=self._form_defaults(),
240 encoding="UTF-8",
240 encoding="UTF-8",
241 force_defaults=False)
241 force_defaults=False)
242
242
243 @HasPermissionAllDecorator('hg.admin')
243 @HasPermissionAllDecorator('hg.admin')
244 @auth.CSRFRequired()
244 @auth.CSRFRequired()
245 def settings_global_update(self):
245 def settings_global_update(self):
246 """POST /admin/settings/global: All items in the collection"""
246 """POST /admin/settings/global: All items in the collection"""
247 # url('admin_settings_global')
247 # url('admin_settings_global')
248 c.active = 'global'
248 c.active = 'global'
249 c.personal_repo_group_default_pattern = RepoGroupModel()\
249 c.personal_repo_group_default_pattern = RepoGroupModel()\
250 .get_personal_group_name_pattern()
250 .get_personal_group_name_pattern()
251 application_form = ApplicationSettingsForm()()
251 application_form = ApplicationSettingsForm()()
252 try:
252 try:
253 form_result = application_form.to_python(dict(request.POST))
253 form_result = application_form.to_python(dict(request.POST))
254 except formencode.Invalid as errors:
254 except formencode.Invalid as errors:
255 return htmlfill.render(
255 return htmlfill.render(
256 render('admin/settings/settings.html'),
256 render('admin/settings/settings.html'),
257 defaults=errors.value,
257 defaults=errors.value,
258 errors=errors.error_dict or {},
258 errors=errors.error_dict or {},
259 prefix_error=False,
259 prefix_error=False,
260 encoding="UTF-8",
260 encoding="UTF-8",
261 force_defaults=False)
261 force_defaults=False)
262
262
263 try:
263 try:
264 settings = [
264 settings = [
265 ('title', 'rhodecode_title', 'unicode'),
265 ('title', 'rhodecode_title', 'unicode'),
266 ('realm', 'rhodecode_realm', 'unicode'),
266 ('realm', 'rhodecode_realm', 'unicode'),
267 ('pre_code', 'rhodecode_pre_code', 'unicode'),
267 ('pre_code', 'rhodecode_pre_code', 'unicode'),
268 ('post_code', 'rhodecode_post_code', 'unicode'),
268 ('post_code', 'rhodecode_post_code', 'unicode'),
269 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
269 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
270 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
270 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
271 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
271 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
272 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
272 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
273 ]
273 ]
274 for setting, form_key, type_ in settings:
274 for setting, form_key, type_ in settings:
275 sett = SettingsModel().create_or_update_setting(
275 sett = SettingsModel().create_or_update_setting(
276 setting, form_result[form_key], type_)
276 setting, form_result[form_key], type_)
277 Session().add(sett)
277 Session().add(sett)
278
278
279 Session().commit()
279 Session().commit()
280 SettingsModel().invalidate_settings_cache()
280 SettingsModel().invalidate_settings_cache()
281 h.flash(_('Updated application settings'), category='success')
281 h.flash(_('Updated application settings'), category='success')
282 except Exception:
282 except Exception:
283 log.exception("Exception while updating application settings")
283 log.exception("Exception while updating application settings")
284 h.flash(
284 h.flash(
285 _('Error occurred during updating application settings'),
285 _('Error occurred during updating application settings'),
286 category='error')
286 category='error')
287
287
288 return redirect(url('admin_settings_global'))
288 return redirect(url('admin_settings_global'))
289
289
290 @HasPermissionAllDecorator('hg.admin')
290 @HasPermissionAllDecorator('hg.admin')
291 def settings_global(self):
291 def settings_global(self):
292 """GET /admin/settings/global: All items in the collection"""
292 """GET /admin/settings/global: All items in the collection"""
293 # url('admin_settings_global')
293 # url('admin_settings_global')
294 c.active = 'global'
294 c.active = 'global'
295 c.personal_repo_group_default_pattern = RepoGroupModel()\
295 c.personal_repo_group_default_pattern = RepoGroupModel()\
296 .get_personal_group_name_pattern()
296 .get_personal_group_name_pattern()
297
297
298 return htmlfill.render(
298 return htmlfill.render(
299 render('admin/settings/settings.html'),
299 render('admin/settings/settings.html'),
300 defaults=self._form_defaults(),
300 defaults=self._form_defaults(),
301 encoding="UTF-8",
301 encoding="UTF-8",
302 force_defaults=False)
302 force_defaults=False)
303
303
304 @HasPermissionAllDecorator('hg.admin')
304 @HasPermissionAllDecorator('hg.admin')
305 @auth.CSRFRequired()
305 @auth.CSRFRequired()
306 def settings_visual_update(self):
306 def settings_visual_update(self):
307 """POST /admin/settings/visual: All items in the collection"""
307 """POST /admin/settings/visual: All items in the collection"""
308 # url('admin_settings_visual')
308 # url('admin_settings_visual')
309 c.active = 'visual'
309 c.active = 'visual'
310 application_form = ApplicationVisualisationForm()()
310 application_form = ApplicationVisualisationForm()()
311 try:
311 try:
312 form_result = application_form.to_python(dict(request.POST))
312 form_result = application_form.to_python(dict(request.POST))
313 except formencode.Invalid as errors:
313 except formencode.Invalid as errors:
314 return htmlfill.render(
314 return htmlfill.render(
315 render('admin/settings/settings.html'),
315 render('admin/settings/settings.html'),
316 defaults=errors.value,
316 defaults=errors.value,
317 errors=errors.error_dict or {},
317 errors=errors.error_dict or {},
318 prefix_error=False,
318 prefix_error=False,
319 encoding="UTF-8",
319 encoding="UTF-8",
320 force_defaults=False
320 force_defaults=False
321 )
321 )
322
322
323 try:
323 try:
324 settings = [
324 settings = [
325 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
325 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
326 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
326 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
327 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
327 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
328 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
328 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
329 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
329 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
330 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
330 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
331 ('show_version', 'rhodecode_show_version', 'bool'),
331 ('show_version', 'rhodecode_show_version', 'bool'),
332 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
332 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
333 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
333 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
334 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
334 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
335 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
335 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
336 ('support_url', 'rhodecode_support_url', 'unicode'),
336 ('support_url', 'rhodecode_support_url', 'unicode'),
337 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
337 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
338 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
338 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
339 ]
339 ]
340 for setting, form_key, type_ in settings:
340 for setting, form_key, type_ in settings:
341 sett = SettingsModel().create_or_update_setting(
341 sett = SettingsModel().create_or_update_setting(
342 setting, form_result[form_key], type_)
342 setting, form_result[form_key], type_)
343 Session().add(sett)
343 Session().add(sett)
344
344
345 Session().commit()
345 Session().commit()
346 SettingsModel().invalidate_settings_cache()
346 SettingsModel().invalidate_settings_cache()
347 h.flash(_('Updated visualisation settings'), category='success')
347 h.flash(_('Updated visualisation settings'), category='success')
348 except Exception:
348 except Exception:
349 log.exception("Exception updating visualization settings")
349 log.exception("Exception updating visualization settings")
350 h.flash(_('Error occurred during updating '
350 h.flash(_('Error occurred during updating '
351 'visualisation settings'),
351 'visualisation settings'),
352 category='error')
352 category='error')
353
353
354 return redirect(url('admin_settings_visual'))
354 return redirect(url('admin_settings_visual'))
355
355
356 @HasPermissionAllDecorator('hg.admin')
356 @HasPermissionAllDecorator('hg.admin')
357 def settings_visual(self):
357 def settings_visual(self):
358 """GET /admin/settings/visual: All items in the collection"""
358 """GET /admin/settings/visual: All items in the collection"""
359 # url('admin_settings_visual')
359 # url('admin_settings_visual')
360 c.active = 'visual'
360 c.active = 'visual'
361
361
362 return htmlfill.render(
362 return htmlfill.render(
363 render('admin/settings/settings.html'),
363 render('admin/settings/settings.html'),
364 defaults=self._form_defaults(),
364 defaults=self._form_defaults(),
365 encoding="UTF-8",
365 encoding="UTF-8",
366 force_defaults=False)
366 force_defaults=False)
367
367
368 @HasPermissionAllDecorator('hg.admin')
368 @HasPermissionAllDecorator('hg.admin')
369 @auth.CSRFRequired()
369 @auth.CSRFRequired()
370 def settings_issuetracker_test(self):
370 def settings_issuetracker_test(self):
371 if request.is_xhr:
371 if request.is_xhr:
372 return h.urlify_commit_message(
372 return h.urlify_commit_message(
373 request.POST.get('test_text', ''),
373 request.POST.get('test_text', ''),
374 'repo_group/test_repo1')
374 'repo_group/test_repo1')
375 else:
375 else:
376 raise HTTPBadRequest()
376 raise HTTPBadRequest()
377
377
378 @HasPermissionAllDecorator('hg.admin')
378 @HasPermissionAllDecorator('hg.admin')
379 @auth.CSRFRequired()
379 @auth.CSRFRequired()
380 def settings_issuetracker_delete(self):
380 def settings_issuetracker_delete(self):
381 uid = request.POST.get('uid')
381 uid = request.POST.get('uid')
382 IssueTrackerSettingsModel().delete_entries(uid)
382 IssueTrackerSettingsModel().delete_entries(uid)
383 h.flash(_('Removed issue tracker entry'), category='success')
383 h.flash(_('Removed issue tracker entry'), category='success')
384 return redirect(url('admin_settings_issuetracker'))
384 return redirect(url('admin_settings_issuetracker'))
385
385
386 @HasPermissionAllDecorator('hg.admin')
386 @HasPermissionAllDecorator('hg.admin')
387 def settings_issuetracker(self):
387 def settings_issuetracker(self):
388 """GET /admin/settings/issue-tracker: All items in the collection"""
388 """GET /admin/settings/issue-tracker: All items in the collection"""
389 # url('admin_settings_issuetracker')
389 # url('admin_settings_issuetracker')
390 c.active = 'issuetracker'
390 c.active = 'issuetracker'
391 defaults = SettingsModel().get_all_settings()
391 defaults = SettingsModel().get_all_settings()
392
392
393 entry_key = 'rhodecode_issuetracker_pat_'
393 entry_key = 'rhodecode_issuetracker_pat_'
394
394
395 c.issuetracker_entries = {}
395 c.issuetracker_entries = {}
396 for k, v in defaults.items():
396 for k, v in defaults.items():
397 if k.startswith(entry_key):
397 if k.startswith(entry_key):
398 uid = k[len(entry_key):]
398 uid = k[len(entry_key):]
399 c.issuetracker_entries[uid] = None
399 c.issuetracker_entries[uid] = None
400
400
401 for uid in c.issuetracker_entries:
401 for uid in c.issuetracker_entries:
402 c.issuetracker_entries[uid] = AttributeDict({
402 c.issuetracker_entries[uid] = AttributeDict({
403 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
403 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
404 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
404 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
405 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
405 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
406 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
406 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
407 })
407 })
408
408
409 return render('admin/settings/settings.html')
409 return render('admin/settings/settings.html')
410
410
411 @HasPermissionAllDecorator('hg.admin')
411 @HasPermissionAllDecorator('hg.admin')
412 @auth.CSRFRequired()
412 @auth.CSRFRequired()
413 def settings_issuetracker_save(self):
413 def settings_issuetracker_save(self):
414 settings_model = IssueTrackerSettingsModel()
414 settings_model = IssueTrackerSettingsModel()
415
415
416 form = IssueTrackerPatternsForm()().to_python(request.POST)
416 form = IssueTrackerPatternsForm()().to_python(request.POST)
417 if form:
417 if form:
418 for uid in form.get('delete_patterns', []):
418 for uid in form.get('delete_patterns', []):
419 settings_model.delete_entries(uid)
419 settings_model.delete_entries(uid)
420
420
421 for pattern in form.get('patterns', []):
421 for pattern in form.get('patterns', []):
422 for setting, value, type_ in pattern:
422 for setting, value, type_ in pattern:
423 sett = settings_model.create_or_update_setting(
423 sett = settings_model.create_or_update_setting(
424 setting, value, type_)
424 setting, value, type_)
425 Session().add(sett)
425 Session().add(sett)
426
426
427 Session().commit()
427 Session().commit()
428
428
429 SettingsModel().invalidate_settings_cache()
429 SettingsModel().invalidate_settings_cache()
430 h.flash(_('Updated issue tracker entries'), category='success')
430 h.flash(_('Updated issue tracker entries'), category='success')
431 return redirect(url('admin_settings_issuetracker'))
431 return redirect(url('admin_settings_issuetracker'))
432
432
433 @HasPermissionAllDecorator('hg.admin')
433 @HasPermissionAllDecorator('hg.admin')
434 @auth.CSRFRequired()
434 @auth.CSRFRequired()
435 def settings_email_update(self):
435 def settings_email_update(self):
436 """POST /admin/settings/email: All items in the collection"""
436 """POST /admin/settings/email: All items in the collection"""
437 # url('admin_settings_email')
437 # url('admin_settings_email')
438 c.active = 'email'
438 c.active = 'email'
439
439
440 test_email = request.POST.get('test_email')
440 test_email = request.POST.get('test_email')
441
441
442 if not test_email:
442 if not test_email:
443 h.flash(_('Please enter email address'), category='error')
443 h.flash(_('Please enter email address'), category='error')
444 return redirect(url('admin_settings_email'))
444 return redirect(url('admin_settings_email'))
445
445
446 email_kwargs = {
446 email_kwargs = {
447 'date': datetime.datetime.now(),
447 'date': datetime.datetime.now(),
448 'user': c.rhodecode_user,
448 'user': c.rhodecode_user,
449 'rhodecode_version': c.rhodecode_version
449 'rhodecode_version': c.rhodecode_version
450 }
450 }
451
451
452 (subject, headers, email_body,
452 (subject, headers, email_body,
453 email_body_plaintext) = EmailNotificationModel().render_email(
453 email_body_plaintext) = EmailNotificationModel().render_email(
454 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
454 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
455
455
456 recipients = [test_email] if test_email else None
456 recipients = [test_email] if test_email else None
457
457
458 run_task(tasks.send_email, recipients, subject,
458 run_task(tasks.send_email, recipients, subject,
459 email_body_plaintext, email_body)
459 email_body_plaintext, email_body)
460
460
461 h.flash(_('Send email task created'), category='success')
461 h.flash(_('Send email task created'), category='success')
462 return redirect(url('admin_settings_email'))
462 return redirect(url('admin_settings_email'))
463
463
464 @HasPermissionAllDecorator('hg.admin')
464 @HasPermissionAllDecorator('hg.admin')
465 def settings_email(self):
465 def settings_email(self):
466 """GET /admin/settings/email: All items in the collection"""
466 """GET /admin/settings/email: All items in the collection"""
467 # url('admin_settings_email')
467 # url('admin_settings_email')
468 c.active = 'email'
468 c.active = 'email'
469 c.rhodecode_ini = rhodecode.CONFIG
469 c.rhodecode_ini = rhodecode.CONFIG
470
470
471 return htmlfill.render(
471 return htmlfill.render(
472 render('admin/settings/settings.html'),
472 render('admin/settings/settings.html'),
473 defaults=self._form_defaults(),
473 defaults=self._form_defaults(),
474 encoding="UTF-8",
474 encoding="UTF-8",
475 force_defaults=False)
475 force_defaults=False)
476
476
477 @HasPermissionAllDecorator('hg.admin')
477 @HasPermissionAllDecorator('hg.admin')
478 @auth.CSRFRequired()
478 @auth.CSRFRequired()
479 def settings_hooks_update(self):
479 def settings_hooks_update(self):
480 """POST or DELETE /admin/settings/hooks: All items in the collection"""
480 """POST or DELETE /admin/settings/hooks: All items in the collection"""
481 # url('admin_settings_hooks')
481 # url('admin_settings_hooks')
482 c.active = 'hooks'
482 c.active = 'hooks'
483 if c.visual.allow_custom_hooks_settings:
483 if c.visual.allow_custom_hooks_settings:
484 ui_key = request.POST.get('new_hook_ui_key')
484 ui_key = request.POST.get('new_hook_ui_key')
485 ui_value = request.POST.get('new_hook_ui_value')
485 ui_value = request.POST.get('new_hook_ui_value')
486
486
487 hook_id = request.POST.get('hook_id')
487 hook_id = request.POST.get('hook_id')
488 new_hook = False
488 new_hook = False
489
489
490 model = SettingsModel()
490 model = SettingsModel()
491 try:
491 try:
492 if ui_value and ui_key:
492 if ui_value and ui_key:
493 model.create_or_update_hook(ui_key, ui_value)
493 model.create_or_update_hook(ui_key, ui_value)
494 h.flash(_('Added new hook'), category='success')
494 h.flash(_('Added new hook'), category='success')
495 new_hook = True
495 new_hook = True
496 elif hook_id:
496 elif hook_id:
497 RhodeCodeUi.delete(hook_id)
497 RhodeCodeUi.delete(hook_id)
498 Session().commit()
498 Session().commit()
499
499
500 # check for edits
500 # check for edits
501 update = False
501 update = False
502 _d = request.POST.dict_of_lists()
502 _d = request.POST.dict_of_lists()
503 for k, v in zip(_d.get('hook_ui_key', []),
503 for k, v in zip(_d.get('hook_ui_key', []),
504 _d.get('hook_ui_value_new', [])):
504 _d.get('hook_ui_value_new', [])):
505 model.create_or_update_hook(k, v)
505 model.create_or_update_hook(k, v)
506 update = True
506 update = True
507
507
508 if update and not new_hook:
508 if update and not new_hook:
509 h.flash(_('Updated hooks'), category='success')
509 h.flash(_('Updated hooks'), category='success')
510 Session().commit()
510 Session().commit()
511 except Exception:
511 except Exception:
512 log.exception("Exception during hook creation")
512 log.exception("Exception during hook creation")
513 h.flash(_('Error occurred during hook creation'),
513 h.flash(_('Error occurred during hook creation'),
514 category='error')
514 category='error')
515
515
516 return redirect(url('admin_settings_hooks'))
516 return redirect(url('admin_settings_hooks'))
517
517
518 @HasPermissionAllDecorator('hg.admin')
518 @HasPermissionAllDecorator('hg.admin')
519 def settings_hooks(self):
519 def settings_hooks(self):
520 """GET /admin/settings/hooks: All items in the collection"""
520 """GET /admin/settings/hooks: All items in the collection"""
521 # url('admin_settings_hooks')
521 # url('admin_settings_hooks')
522 c.active = 'hooks'
522 c.active = 'hooks'
523
523
524 model = SettingsModel()
524 model = SettingsModel()
525 c.hooks = model.get_builtin_hooks()
525 c.hooks = model.get_builtin_hooks()
526 c.custom_hooks = model.get_custom_hooks()
526 c.custom_hooks = model.get_custom_hooks()
527
527
528 return htmlfill.render(
528 return htmlfill.render(
529 render('admin/settings/settings.html'),
529 render('admin/settings/settings.html'),
530 defaults=self._form_defaults(),
530 defaults=self._form_defaults(),
531 encoding="UTF-8",
531 encoding="UTF-8",
532 force_defaults=False)
532 force_defaults=False)
533
533
534 @HasPermissionAllDecorator('hg.admin')
534 @HasPermissionAllDecorator('hg.admin')
535 def settings_search(self):
535 def settings_search(self):
536 """GET /admin/settings/search: All items in the collection"""
536 """GET /admin/settings/search: All items in the collection"""
537 # url('admin_settings_search')
537 # url('admin_settings_search')
538 c.active = 'search'
538 c.active = 'search'
539
539
540 from rhodecode.lib.index import searcher_from_config
540 from rhodecode.lib.index import searcher_from_config
541 searcher = searcher_from_config(config)
541 searcher = searcher_from_config(config)
542 c.statistics = searcher.statistics()
542 c.statistics = searcher.statistics()
543
543
544 return render('admin/settings/settings.html')
544 return render('admin/settings/settings.html')
545
545
546 @HasPermissionAllDecorator('hg.admin')
546 @HasPermissionAllDecorator('hg.admin')
547 def settings_system(self):
547 def settings_system(self):
548 """GET /admin/settings/system: All items in the collection"""
548 """GET /admin/settings/system: All items in the collection"""
549 # url('admin_settings_system')
549 # url('admin_settings_system')
550 snapshot = str2bool(request.GET.get('snapshot'))
550 snapshot = str2bool(request.GET.get('snapshot'))
551 defaults = self._form_defaults()
551 defaults = self._form_defaults()
552
552
553 c.active = 'system'
553 c.active = 'system'
554 c.rhodecode_update_url = defaults.get('rhodecode_update_url')
554 c.rhodecode_update_url = defaults.get('rhodecode_update_url')
555 server_info = ScmModel().get_server_info(request.environ)
555 server_info = ScmModel().get_server_info(request.environ)
556
556
557 for key, val in server_info.iteritems():
557 for key, val in server_info.iteritems():
558 setattr(c, key, val)
558 setattr(c, key, val)
559
559
560 def val(name, subkey='human_value'):
560 def val(name, subkey='human_value'):
561 return server_info[name][subkey]
561 return server_info[name][subkey]
562
562
563 def state(name):
563 def state(name):
564 return server_info[name]['state']
564 return server_info[name]['state']
565
565
566 def val2(name):
566 def val2(name):
567 val = server_info[name]['human_value']
567 val = server_info[name]['human_value']
568 state = server_info[name]['state']
568 state = server_info[name]['state']
569 return val, state
569 return val, state
570
570
571 c.data_items = [
571 c.data_items = [
572 # update info
572 # update info
573 (_('Update info'), h.literal(
573 (_('Update info'), h.literal(
574 '<span class="link" id="check_for_update" >%s.</span>' % (
574 '<span class="link" id="check_for_update" >%s.</span>' % (
575 _('Check for updates')) +
575 _('Check for updates')) +
576 '<br/> <span >%s.</span>' % (_('Note: please make sure this server can access `%s` for the update link to work') % c.rhodecode_update_url)
576 '<br/> <span >%s.</span>' % (_('Note: please make sure this server can access `%s` for the update link to work') % c.rhodecode_update_url)
577 ), ''),
577 ), ''),
578
578
579 # RhodeCode specific
579 # RhodeCode specific
580 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
580 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
581 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
581 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
582 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
582 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
583 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
583 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
584 ('', '', ''), # spacer
584 ('', '', ''), # spacer
585
585
586 # Database
586 # Database
587 (_('Database'), val('database')['url'], state('database')),
587 (_('Database'), val('database')['url'], state('database')),
588 (_('Database version'), val('database')['version'], state('database')),
588 (_('Database version'), val('database')['version'], state('database')),
589 ('', '', ''), # spacer
589 ('', '', ''), # spacer
590
590
591 # Platform/Python
591 # Platform/Python
592 (_('Platform'), val('platform'), state('platform')),
592 (_('Platform'), val('platform'), state('platform')),
593 (_('Python version'), val('python')['version'], state('python')),
593 (_('Python version'), val('python')['version'], state('python')),
594 (_('Python path'), val('python')['executable'], state('python')),
594 (_('Python path'), val('python')['executable'], state('python')),
595 ('', '', ''), # spacer
595 ('', '', ''), # spacer
596
596
597 # Systems stats
597 # Systems stats
598 (_('CPU'), val('cpu'), state('cpu')),
598 (_('CPU'), val('cpu'), state('cpu')),
599 (_('Load'), val('load')['text'], state('load')),
599 (_('Load'), val('load')['text'], state('load')),
600 (_('Memory'), val('memory')['text'], state('memory')),
600 (_('Memory'), val('memory')['text'], state('memory')),
601 (_('Uptime'), val('uptime')['text'], state('uptime')),
601 (_('Uptime'), val('uptime')['text'], state('uptime')),
602 ('', '', ''), # spacer
602 ('', '', ''), # spacer
603
603
604 # Repo storage
604 # Repo storage
605 (_('Storage location'), val('storage')['path'], state('storage')),
605 (_('Storage location'), val('storage')['path'], state('storage')),
606 (_('Storage info'), val('storage')['text'], state('storage')),
606 (_('Storage info'), val('storage')['text'], state('storage')),
607 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
607 (_('Storage inodes'), val('storage_inodes')['text'], state('storage_inodes')),
608
608
609 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
609 (_('Gist storage location'), val('storage_gist')['path'], state('storage_gist')),
610 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
610 (_('Gist storage info'), val('storage_gist')['text'], state('storage_gist')),
611
611
612 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
612 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
613 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
613 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
614
614
615 (_('Search info'), val('search')['text'], state('search')),
615 (_('Search info'), val('search')['text'], state('search')),
616 (_('Search location'), val('search')['location'], state('search')),
616 (_('Search location'), val('search')['location'], state('search')),
617 ('', '', ''), # spacer
617 ('', '', ''), # spacer
618
618
619 # VCS specific
619 # VCS specific
620 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
620 (_('VCS Backends'), val('vcs_backends'), state('vcs_backends')),
621 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
621 (_('VCS Server'), val('vcs_server')['text'], state('vcs_server')),
622 (_('GIT'), val('git'), state('git')),
622 (_('GIT'), val('git'), state('git')),
623 (_('HG'), val('hg'), state('hg')),
623 (_('HG'), val('hg'), state('hg')),
624 (_('SVN'), val('svn'), state('svn')),
624 (_('SVN'), val('svn'), state('svn')),
625
625
626 ]
626 ]
627
627
628 # TODO: marcink, figure out how to allow only selected users to do this
628 # TODO: marcink, figure out how to allow only selected users to do this
629 c.allowed_to_snapshot = c.rhodecode_user.admin
629 c.allowed_to_snapshot = c.rhodecode_user.admin
630
630
631 if snapshot:
631 if snapshot:
632 if c.allowed_to_snapshot:
632 if c.allowed_to_snapshot:
633 c.data_items.pop(0) # remove server info
633 return render('admin/settings/settings_system_snapshot.html')
634 return render('admin/settings/settings_system_snapshot.html')
634 else:
635 else:
635 h.flash('You are not allowed to do this', category='warning')
636 h.flash('You are not allowed to do this', category='warning')
636
637
637 return htmlfill.render(
638 return htmlfill.render(
638 render('admin/settings/settings.html'),
639 render('admin/settings/settings.html'),
639 defaults=defaults,
640 defaults=defaults,
640 encoding="UTF-8",
641 encoding="UTF-8",
641 force_defaults=False)
642 force_defaults=False)
642
643
643 @staticmethod
644 @staticmethod
644 def get_update_data(update_url):
645 def get_update_data(update_url):
645 """Return the JSON update data."""
646 """Return the JSON update data."""
646 ver = rhodecode.__version__
647 ver = rhodecode.__version__
647 log.debug('Checking for upgrade on `%s` server', update_url)
648 log.debug('Checking for upgrade on `%s` server', update_url)
648 opener = urllib2.build_opener()
649 opener = urllib2.build_opener()
649 opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
650 opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
650 response = opener.open(update_url)
651 response = opener.open(update_url)
651 response_data = response.read()
652 response_data = response.read()
652 data = json.loads(response_data)
653 data = json.loads(response_data)
653
654
654 return data
655 return data
655
656
656 @HasPermissionAllDecorator('hg.admin')
657 @HasPermissionAllDecorator('hg.admin')
657 def settings_system_update(self):
658 def settings_system_update(self):
658 """GET /admin/settings/system/updates: All items in the collection"""
659 """GET /admin/settings/system/updates: All items in the collection"""
659 # url('admin_settings_system_update')
660 # url('admin_settings_system_update')
660 defaults = self._form_defaults()
661 defaults = self._form_defaults()
661 update_url = defaults.get('rhodecode_update_url', '')
662 update_url = defaults.get('rhodecode_update_url', '')
662
663
663 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">%s</div>' % (s)
664 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">%s</div>' % (s)
664 try:
665 try:
665 data = self.get_update_data(update_url)
666 data = self.get_update_data(update_url)
666 except urllib2.URLError as e:
667 except urllib2.URLError as e:
667 log.exception("Exception contacting upgrade server")
668 log.exception("Exception contacting upgrade server")
668 return _err('Failed to contact upgrade server: %r' % e)
669 return _err('Failed to contact upgrade server: %r' % e)
669 except ValueError as e:
670 except ValueError as e:
670 log.exception("Bad data sent from update server")
671 log.exception("Bad data sent from update server")
671 return _err('Bad data sent from update server')
672 return _err('Bad data sent from update server')
672
673
673 latest = data['versions'][0]
674 latest = data['versions'][0]
674
675
675 c.update_url = update_url
676 c.update_url = update_url
676 c.latest_data = latest
677 c.latest_data = latest
677 c.latest_ver = latest['version']
678 c.latest_ver = latest['version']
678 c.cur_ver = rhodecode.__version__
679 c.cur_ver = rhodecode.__version__
679 c.should_upgrade = False
680 c.should_upgrade = False
680
681
681 if (packaging.version.Version(c.latest_ver) >
682 if (packaging.version.Version(c.latest_ver) >
682 packaging.version.Version(c.cur_ver)):
683 packaging.version.Version(c.cur_ver)):
683 c.should_upgrade = True
684 c.should_upgrade = True
684 c.important_notices = latest['general']
685 c.important_notices = latest['general']
685
686
686 return render('admin/settings/settings_system_update.html')
687 return render('admin/settings/settings_system_update.html')
687
688
688 @HasPermissionAllDecorator('hg.admin')
689 @HasPermissionAllDecorator('hg.admin')
689 def settings_supervisor(self):
690 def settings_supervisor(self):
690 c.rhodecode_ini = rhodecode.CONFIG
691 c.rhodecode_ini = rhodecode.CONFIG
691 c.active = 'supervisor'
692 c.active = 'supervisor'
692
693
693 c.supervisor_procs = OrderedDict([
694 c.supervisor_procs = OrderedDict([
694 (SUPERVISOR_MASTER, {}),
695 (SUPERVISOR_MASTER, {}),
695 ])
696 ])
696
697
697 c.log_size = 10240
698 c.log_size = 10240
698 supervisor = SupervisorModel()
699 supervisor = SupervisorModel()
699
700
700 _connection = supervisor.get_connection(
701 _connection = supervisor.get_connection(
701 c.rhodecode_ini.get('supervisor.uri'))
702 c.rhodecode_ini.get('supervisor.uri'))
702 c.connection_error = None
703 c.connection_error = None
703 try:
704 try:
704 _connection.supervisor.getAllProcessInfo()
705 _connection.supervisor.getAllProcessInfo()
705 except Exception as e:
706 except Exception as e:
706 c.connection_error = str(e)
707 c.connection_error = str(e)
707 log.exception("Exception reading supervisor data")
708 log.exception("Exception reading supervisor data")
708 return render('admin/settings/settings.html')
709 return render('admin/settings/settings.html')
709
710
710 groupid = c.rhodecode_ini.get('supervisor.group_id')
711 groupid = c.rhodecode_ini.get('supervisor.group_id')
711
712
712 # feed our group processes to the main
713 # feed our group processes to the main
713 for proc in supervisor.get_group_processes(_connection, groupid):
714 for proc in supervisor.get_group_processes(_connection, groupid):
714 c.supervisor_procs[proc['name']] = {}
715 c.supervisor_procs[proc['name']] = {}
715
716
716 for k in c.supervisor_procs.keys():
717 for k in c.supervisor_procs.keys():
717 try:
718 try:
718 # master process info
719 # master process info
719 if k == SUPERVISOR_MASTER:
720 if k == SUPERVISOR_MASTER:
720 _data = supervisor.get_master_state(_connection)
721 _data = supervisor.get_master_state(_connection)
721 _data['name'] = 'supervisor master'
722 _data['name'] = 'supervisor master'
722 _data['description'] = 'pid %s, id: %s, ver: %s' % (
723 _data['description'] = 'pid %s, id: %s, ver: %s' % (
723 _data['pid'], _data['id'], _data['ver'])
724 _data['pid'], _data['id'], _data['ver'])
724 c.supervisor_procs[k] = _data
725 c.supervisor_procs[k] = _data
725 else:
726 else:
726 procid = groupid + ":" + k
727 procid = groupid + ":" + k
727 c.supervisor_procs[k] = supervisor.get_process_info(_connection, procid)
728 c.supervisor_procs[k] = supervisor.get_process_info(_connection, procid)
728 except Exception as e:
729 except Exception as e:
729 log.exception("Exception reading supervisor data")
730 log.exception("Exception reading supervisor data")
730 c.supervisor_procs[k] = {'_rhodecode_error': str(e)}
731 c.supervisor_procs[k] = {'_rhodecode_error': str(e)}
731
732
732 return render('admin/settings/settings.html')
733 return render('admin/settings/settings.html')
733
734
734 @HasPermissionAllDecorator('hg.admin')
735 @HasPermissionAllDecorator('hg.admin')
735 def settings_supervisor_log(self, procid):
736 def settings_supervisor_log(self, procid):
736 import rhodecode
737 import rhodecode
737 c.rhodecode_ini = rhodecode.CONFIG
738 c.rhodecode_ini = rhodecode.CONFIG
738 c.active = 'supervisor_tail'
739 c.active = 'supervisor_tail'
739
740
740 supervisor = SupervisorModel()
741 supervisor = SupervisorModel()
741 _connection = supervisor.get_connection(c.rhodecode_ini.get('supervisor.uri'))
742 _connection = supervisor.get_connection(c.rhodecode_ini.get('supervisor.uri'))
742 groupid = c.rhodecode_ini.get('supervisor.group_id')
743 groupid = c.rhodecode_ini.get('supervisor.group_id')
743 procid = groupid + ":" + procid if procid != SUPERVISOR_MASTER else procid
744 procid = groupid + ":" + procid if procid != SUPERVISOR_MASTER else procid
744
745
745 c.log_size = 10240
746 c.log_size = 10240
746 offset = abs(safe_int(request.GET.get('offset', c.log_size))) * -1
747 offset = abs(safe_int(request.GET.get('offset', c.log_size))) * -1
747 c.log = supervisor.read_process_log(_connection, procid, offset, 0)
748 c.log = supervisor.read_process_log(_connection, procid, offset, 0)
748
749
749 return render('admin/settings/settings.html')
750 return render('admin/settings/settings.html')
750
751
751 @HasPermissionAllDecorator('hg.admin')
752 @HasPermissionAllDecorator('hg.admin')
752 @auth.CSRFRequired()
753 @auth.CSRFRequired()
753 def settings_labs_update(self):
754 def settings_labs_update(self):
754 """POST /admin/settings/labs: All items in the collection"""
755 """POST /admin/settings/labs: All items in the collection"""
755 # url('admin_settings/labs', method={'POST'})
756 # url('admin_settings/labs', method={'POST'})
756 c.active = 'labs'
757 c.active = 'labs'
757
758
758 application_form = LabsSettingsForm()()
759 application_form = LabsSettingsForm()()
759 try:
760 try:
760 form_result = application_form.to_python(dict(request.POST))
761 form_result = application_form.to_python(dict(request.POST))
761 except formencode.Invalid as errors:
762 except formencode.Invalid as errors:
762 h.flash(
763 h.flash(
763 _('Some form inputs contain invalid data.'),
764 _('Some form inputs contain invalid data.'),
764 category='error')
765 category='error')
765 return htmlfill.render(
766 return htmlfill.render(
766 render('admin/settings/settings.html'),
767 render('admin/settings/settings.html'),
767 defaults=errors.value,
768 defaults=errors.value,
768 errors=errors.error_dict or {},
769 errors=errors.error_dict or {},
769 prefix_error=False,
770 prefix_error=False,
770 encoding='UTF-8',
771 encoding='UTF-8',
771 force_defaults=False
772 force_defaults=False
772 )
773 )
773
774
774 try:
775 try:
775 session = Session()
776 session = Session()
776 for setting in _LAB_SETTINGS:
777 for setting in _LAB_SETTINGS:
777 setting_name = setting.key[len('rhodecode_'):]
778 setting_name = setting.key[len('rhodecode_'):]
778 sett = SettingsModel().create_or_update_setting(
779 sett = SettingsModel().create_or_update_setting(
779 setting_name, form_result[setting.key], setting.type)
780 setting_name, form_result[setting.key], setting.type)
780 session.add(sett)
781 session.add(sett)
781
782
782 except Exception:
783 except Exception:
783 log.exception('Exception while updating lab settings')
784 log.exception('Exception while updating lab settings')
784 h.flash(_('Error occurred during updating labs settings'),
785 h.flash(_('Error occurred during updating labs settings'),
785 category='error')
786 category='error')
786 else:
787 else:
787 Session().commit()
788 Session().commit()
788 SettingsModel().invalidate_settings_cache()
789 SettingsModel().invalidate_settings_cache()
789 h.flash(_('Updated Labs settings'), category='success')
790 h.flash(_('Updated Labs settings'), category='success')
790 return redirect(url('admin_settings_labs'))
791 return redirect(url('admin_settings_labs'))
791
792
792 return htmlfill.render(
793 return htmlfill.render(
793 render('admin/settings/settings.html'),
794 render('admin/settings/settings.html'),
794 defaults=self._form_defaults(),
795 defaults=self._form_defaults(),
795 encoding='UTF-8',
796 encoding='UTF-8',
796 force_defaults=False)
797 force_defaults=False)
797
798
798 @HasPermissionAllDecorator('hg.admin')
799 @HasPermissionAllDecorator('hg.admin')
799 def settings_labs(self):
800 def settings_labs(self):
800 """GET /admin/settings/labs: All items in the collection"""
801 """GET /admin/settings/labs: All items in the collection"""
801 # url('admin_settings_labs')
802 # url('admin_settings_labs')
802 if not c.labs_active:
803 if not c.labs_active:
803 redirect(url('admin_settings'))
804 redirect(url('admin_settings'))
804
805
805 c.active = 'labs'
806 c.active = 'labs'
806 c.lab_settings = _LAB_SETTINGS
807 c.lab_settings = _LAB_SETTINGS
807
808
808 return htmlfill.render(
809 return htmlfill.render(
809 render('admin/settings/settings.html'),
810 render('admin/settings/settings.html'),
810 defaults=self._form_defaults(),
811 defaults=self._form_defaults(),
811 encoding='UTF-8',
812 encoding='UTF-8',
812 force_defaults=False)
813 force_defaults=False)
813
814
814 def _form_defaults(self):
815 def _form_defaults(self):
815 defaults = SettingsModel().get_all_settings()
816 defaults = SettingsModel().get_all_settings()
816 defaults.update(self._get_hg_ui_settings())
817 defaults.update(self._get_hg_ui_settings())
817 defaults.update({
818 defaults.update({
818 'new_svn_branch': '',
819 'new_svn_branch': '',
819 'new_svn_tag': '',
820 'new_svn_tag': '',
820 })
821 })
821 return defaults
822 return defaults
822
823
823
824
824 # :param key: name of the setting including the 'rhodecode_' prefix
825 # :param key: name of the setting including the 'rhodecode_' prefix
825 # :param type: the RhodeCodeSetting type to use.
826 # :param type: the RhodeCodeSetting type to use.
826 # :param group: the i18ned group in which we should dispaly this setting
827 # :param group: the i18ned group in which we should dispaly this setting
827 # :param label: the i18ned label we should display for this setting
828 # :param label: the i18ned label we should display for this setting
828 # :param help: the i18ned help we should dispaly for this setting
829 # :param help: the i18ned help we should dispaly for this setting
829 LabSetting = collections.namedtuple(
830 LabSetting = collections.namedtuple(
830 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
831 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
831
832
832
833
833 # This list has to be kept in sync with the form
834 # This list has to be kept in sync with the form
834 # rhodecode.model.forms.LabsSettingsForm.
835 # rhodecode.model.forms.LabsSettingsForm.
835 _LAB_SETTINGS = [
836 _LAB_SETTINGS = [
836
837
837 ]
838 ]
@@ -1,41 +1,40 b''
1
1
2 <pre>
2 <pre>
3 SYSTEM INFO
3 SYSTEM INFO
4 -----------
4 -----------
5
5
6 % for dt, dd, warn in c.data_items:
6 % for dt, dd, warn in c.data_items:
7 ${dt}${':' if dt else '---'}
7 ${dt.lower().replace(' ', '_')}${': '+dd if dt else '---'}
8 ${dd}
9 % if warn and warn['message']:
8 % if warn and warn['message']:
10 ALERT_${warn['type'].upper()} ${warn['message']}
9 ALERT_${warn['type'].upper()} ${warn['message']}
11 % endif
10 % endif
12 % endfor
11 % endfor
13
12
14 PYTHON PACKAGES
13 PYTHON PACKAGES
15 ---------------
14 ---------------
16
15
17 % for key, value in c.py_modules['human_value']:
16 % for key, value in c.py_modules['human_value']:
18 ${key}: ${value}
17 ${key}: ${value}
19 % endfor
18 % endfor
20
19
21 SYSTEM SETTINGS
20 SYSTEM SETTINGS
22 ---------------
21 ---------------
23
22
24 % for key, value in sorted(c.rhodecode_config['human_value'].items()):
23 % for key, value in sorted(c.rhodecode_config['human_value'].items()):
25 % if isinstance(value, dict):
24 % if isinstance(value, dict):
26
25
27 % for key2, value2 in value.items():
26 % for key2, value2 in value.items():
28 [${key}]${key2}: ${value2}
27 [${key}]${key2}: ${value2}
29 % endfor
28 % endfor
30
29
31 % else:
30 % else:
32 ${key}: ${value}
31 ${key}: ${value}
33 % endif
32 % endif
34 % endfor
33 % endfor
35
34
36 </pre>
35 </pre>
37
36
38
37
39
38
40
39
41
40
General Comments 0
You need to be logged in to leave comments. Login now