##// END OF EJS Templates
vcs-settings: moved creation of largefiles default dirs into vcs settings view....
marcink -
r1682:9db59bee default
parent child Browse files
Show More
@@ -1,694 +1,697 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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
28
29 import datetime
29 import datetime
30 import formencode
30 import formencode
31 from formencode import htmlfill
31 from formencode import htmlfill
32 from pylons import request, tmpl_context as c, url, config
32 from pylons import request, tmpl_context as c, url, config
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35 from pyramid.threadlocal import get_current_registry
35 from pyramid.threadlocal import get_current_registry
36 from webob.exc import HTTPBadRequest
36 from webob.exc import HTTPBadRequest
37
37
38 import rhodecode
38 import rhodecode
39 from rhodecode.apps.admin.navigation import navigation_list
39 from rhodecode.apps.admin.navigation import navigation_list
40 from rhodecode.apps.svn_support.config_keys import generate_config
40 from rhodecode.apps.svn_support.config_keys import generate_config
41 from rhodecode.lib import auth
41 from rhodecode.lib import auth
42 from rhodecode.lib import helpers as h
42 from rhodecode.lib import helpers as h
43 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
43 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
44 from rhodecode.lib.base import BaseController, render
44 from rhodecode.lib.base import BaseController, render
45 from rhodecode.lib.celerylib import tasks, run_task
45 from rhodecode.lib.celerylib import tasks, run_task
46 from rhodecode.lib.utils import repo2db_mapper
46 from rhodecode.lib.utils import repo2db_mapper
47 from rhodecode.lib.utils2 import (
47 from rhodecode.lib.utils2 import (
48 str2bool, safe_unicode, AttributeDict, safe_int)
48 str2bool, safe_unicode, AttributeDict, safe_int)
49 from rhodecode.lib.compat import OrderedDict
49 from rhodecode.lib.compat import OrderedDict
50 from rhodecode.lib.utils import jsonify
50 from rhodecode.lib.utils import jsonify
51
51
52 from rhodecode.model.db import RhodeCodeUi, Repository
52 from rhodecode.model.db import RhodeCodeUi, Repository
53 from rhodecode.model.forms import ApplicationSettingsForm, \
53 from rhodecode.model.forms import ApplicationSettingsForm, \
54 ApplicationUiSettingsForm, ApplicationVisualisationForm, \
54 ApplicationUiSettingsForm, ApplicationVisualisationForm, \
55 LabsSettingsForm, IssueTrackerPatternsForm
55 LabsSettingsForm, IssueTrackerPatternsForm
56 from rhodecode.model.repo_group import RepoGroupModel
56 from rhodecode.model.repo_group import RepoGroupModel
57
57
58 from rhodecode.model.scm import ScmModel
58 from rhodecode.model.scm import ScmModel
59 from rhodecode.model.notification import EmailNotificationModel
59 from rhodecode.model.notification import EmailNotificationModel
60 from rhodecode.model.meta import Session
60 from rhodecode.model.meta import Session
61 from rhodecode.model.settings import (
61 from rhodecode.model.settings import (
62 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
62 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
63 SettingsModel)
63 SettingsModel)
64
64
65 from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER
65 from rhodecode.model.supervisor import SupervisorModel, SUPERVISOR_MASTER
66
66
67
67
68 log = logging.getLogger(__name__)
68 log = logging.getLogger(__name__)
69
69
70
70
71 class SettingsController(BaseController):
71 class SettingsController(BaseController):
72 """REST Controller styled on the Atom Publishing Protocol"""
72 """REST Controller styled on the Atom Publishing Protocol"""
73 # To properly map this controller, ensure your config/routing.py
73 # To properly map this controller, ensure your config/routing.py
74 # file has a resource setup:
74 # file has a resource setup:
75 # map.resource('setting', 'settings', controller='admin/settings',
75 # map.resource('setting', 'settings', controller='admin/settings',
76 # path_prefix='/admin', name_prefix='admin_')
76 # path_prefix='/admin', name_prefix='admin_')
77
77
78 @LoginRequired()
78 @LoginRequired()
79 def __before__(self):
79 def __before__(self):
80 super(SettingsController, self).__before__()
80 super(SettingsController, self).__before__()
81 c.labs_active = str2bool(
81 c.labs_active = str2bool(
82 rhodecode.CONFIG.get('labs_settings_active', 'true'))
82 rhodecode.CONFIG.get('labs_settings_active', 'true'))
83 c.navlist = navigation_list(request)
83 c.navlist = navigation_list(request)
84
84
85 def _get_ui_settings(self):
85 def _get_ui_settings(self):
86 ret = RhodeCodeUi.query().all()
86 ret = RhodeCodeUi.query().all()
87
87
88 if not ret:
88 if not ret:
89 raise Exception('Could not get application ui settings !')
89 raise Exception('Could not get application ui settings !')
90 settings = {}
90 settings = {}
91 for each in ret:
91 for each in ret:
92 k = each.ui_key
92 k = each.ui_key
93 v = each.ui_value
93 v = each.ui_value
94 if k == '/':
94 if k == '/':
95 k = 'root_path'
95 k = 'root_path'
96
96
97 if k in ['push_ssl', 'publish', 'enabled']:
97 if k in ['push_ssl', 'publish', 'enabled']:
98 v = str2bool(v)
98 v = str2bool(v)
99
99
100 if k.find('.') != -1:
100 if k.find('.') != -1:
101 k = k.replace('.', '_')
101 k = k.replace('.', '_')
102
102
103 if each.ui_section in ['hooks', 'extensions']:
103 if each.ui_section in ['hooks', 'extensions']:
104 v = each.ui_active
104 v = each.ui_active
105
105
106 settings[each.ui_section + '_' + k] = v
106 settings[each.ui_section + '_' + k] = v
107 return settings
107 return settings
108
108
109 @HasPermissionAllDecorator('hg.admin')
109 @HasPermissionAllDecorator('hg.admin')
110 @auth.CSRFRequired()
110 @auth.CSRFRequired()
111 @jsonify
111 @jsonify
112 def delete_svn_pattern(self):
112 def delete_svn_pattern(self):
113 if not request.is_xhr:
113 if not request.is_xhr:
114 raise HTTPBadRequest()
114 raise HTTPBadRequest()
115
115
116 delete_pattern_id = request.POST.get('delete_svn_pattern')
116 delete_pattern_id = request.POST.get('delete_svn_pattern')
117 model = VcsSettingsModel()
117 model = VcsSettingsModel()
118 try:
118 try:
119 model.delete_global_svn_pattern(delete_pattern_id)
119 model.delete_global_svn_pattern(delete_pattern_id)
120 except SettingNotFound:
120 except SettingNotFound:
121 raise HTTPBadRequest()
121 raise HTTPBadRequest()
122
122
123 Session().commit()
123 Session().commit()
124 return True
124 return True
125
125
126 @HasPermissionAllDecorator('hg.admin')
126 @HasPermissionAllDecorator('hg.admin')
127 @auth.CSRFRequired()
127 @auth.CSRFRequired()
128 def settings_vcs_update(self):
128 def settings_vcs_update(self):
129 """POST /admin/settings: All items in the collection"""
129 """POST /admin/settings: All items in the collection"""
130 # url('admin_settings_vcs')
130 # url('admin_settings_vcs')
131 c.active = 'vcs'
131 c.active = 'vcs'
132
132
133 model = VcsSettingsModel()
133 model = VcsSettingsModel()
134 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
134 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
135 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
135 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
136
136
137 # TODO: Replace with request.registry after migrating to pyramid.
137 # TODO: Replace with request.registry after migrating to pyramid.
138 pyramid_settings = get_current_registry().settings
138 pyramid_settings = get_current_registry().settings
139 c.svn_proxy_generate_config = pyramid_settings[generate_config]
139 c.svn_proxy_generate_config = pyramid_settings[generate_config]
140
140
141 application_form = ApplicationUiSettingsForm()()
141 application_form = ApplicationUiSettingsForm()()
142
142
143 try:
143 try:
144 form_result = application_form.to_python(dict(request.POST))
144 form_result = application_form.to_python(dict(request.POST))
145 except formencode.Invalid as errors:
145 except formencode.Invalid as errors:
146 h.flash(
146 h.flash(
147 _("Some form inputs contain invalid data."),
147 _("Some form inputs contain invalid data."),
148 category='error')
148 category='error')
149 return htmlfill.render(
149 return htmlfill.render(
150 render('admin/settings/settings.mako'),
150 render('admin/settings/settings.mako'),
151 defaults=errors.value,
151 defaults=errors.value,
152 errors=errors.error_dict or {},
152 errors=errors.error_dict or {},
153 prefix_error=False,
153 prefix_error=False,
154 encoding="UTF-8",
154 encoding="UTF-8",
155 force_defaults=False
155 force_defaults=False
156 )
156 )
157
157
158 try:
158 try:
159 if c.visual.allow_repo_location_change:
159 if c.visual.allow_repo_location_change:
160 model.update_global_path_setting(
160 model.update_global_path_setting(
161 form_result['paths_root_path'])
161 form_result['paths_root_path'])
162
162
163 model.update_global_ssl_setting(form_result['web_push_ssl'])
163 model.update_global_ssl_setting(form_result['web_push_ssl'])
164 model.update_global_hook_settings(form_result)
164 model.update_global_hook_settings(form_result)
165
165
166 model.create_or_update_global_svn_settings(form_result)
166 model.create_or_update_global_svn_settings(form_result)
167 model.create_or_update_global_hg_settings(form_result)
167 model.create_or_update_global_hg_settings(form_result)
168 model.create_or_update_global_git_settings(form_result)
168 model.create_or_update_global_git_settings(form_result)
169 model.create_or_update_global_pr_settings(form_result)
169 model.create_or_update_global_pr_settings(form_result)
170 except Exception:
170 except Exception:
171 log.exception("Exception while updating settings")
171 log.exception("Exception while updating settings")
172 h.flash(_('Error occurred during updating '
172 h.flash(_('Error occurred during updating '
173 'application settings'), category='error')
173 'application settings'), category='error')
174 else:
174 else:
175 Session().commit()
175 Session().commit()
176 h.flash(_('Updated VCS settings'), category='success')
176 h.flash(_('Updated VCS settings'), category='success')
177 return redirect(url('admin_settings_vcs'))
177 return redirect(url('admin_settings_vcs'))
178
178
179 return htmlfill.render(
179 return htmlfill.render(
180 render('admin/settings/settings.mako'),
180 render('admin/settings/settings.mako'),
181 defaults=self._form_defaults(),
181 defaults=self._form_defaults(),
182 encoding="UTF-8",
182 encoding="UTF-8",
183 force_defaults=False)
183 force_defaults=False)
184
184
185 @HasPermissionAllDecorator('hg.admin')
185 @HasPermissionAllDecorator('hg.admin')
186 def settings_vcs(self):
186 def settings_vcs(self):
187 """GET /admin/settings: All items in the collection"""
187 """GET /admin/settings: All items in the collection"""
188 # url('admin_settings_vcs')
188 # url('admin_settings_vcs')
189 c.active = 'vcs'
189 c.active = 'vcs'
190 model = VcsSettingsModel()
190 model = VcsSettingsModel()
191 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
191 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
192 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
192 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
193
193
194 # TODO: Replace with request.registry after migrating to pyramid.
194 # TODO: Replace with request.registry after migrating to pyramid.
195 pyramid_settings = get_current_registry().settings
195 pyramid_settings = get_current_registry().settings
196 c.svn_proxy_generate_config = pyramid_settings[generate_config]
196 c.svn_proxy_generate_config = pyramid_settings[generate_config]
197
197
198 defaults = self._form_defaults()
199
200 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
198 return htmlfill.render(
201 return htmlfill.render(
199 render('admin/settings/settings.mako'),
202 render('admin/settings/settings.mako'),
200 defaults=self._form_defaults(),
203 defaults=defaults,
201 encoding="UTF-8",
204 encoding="UTF-8",
202 force_defaults=False)
205 force_defaults=False)
203
206
204 @HasPermissionAllDecorator('hg.admin')
207 @HasPermissionAllDecorator('hg.admin')
205 @auth.CSRFRequired()
208 @auth.CSRFRequired()
206 def settings_mapping_update(self):
209 def settings_mapping_update(self):
207 """POST /admin/settings/mapping: All items in the collection"""
210 """POST /admin/settings/mapping: All items in the collection"""
208 # url('admin_settings_mapping')
211 # url('admin_settings_mapping')
209 c.active = 'mapping'
212 c.active = 'mapping'
210 rm_obsolete = request.POST.get('destroy', False)
213 rm_obsolete = request.POST.get('destroy', False)
211 invalidate_cache = request.POST.get('invalidate', False)
214 invalidate_cache = request.POST.get('invalidate', False)
212 log.debug(
215 log.debug(
213 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
216 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
214
217
215 if invalidate_cache:
218 if invalidate_cache:
216 log.debug('invalidating all repositories cache')
219 log.debug('invalidating all repositories cache')
217 for repo in Repository.get_all():
220 for repo in Repository.get_all():
218 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
221 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
219
222
220 filesystem_repos = ScmModel().repo_scan()
223 filesystem_repos = ScmModel().repo_scan()
221 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
224 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
222 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
225 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
223 h.flash(_('Repositories successfully '
226 h.flash(_('Repositories successfully '
224 'rescanned added: %s ; removed: %s') %
227 'rescanned added: %s ; removed: %s') %
225 (_repr(added), _repr(removed)),
228 (_repr(added), _repr(removed)),
226 category='success')
229 category='success')
227 return redirect(url('admin_settings_mapping'))
230 return redirect(url('admin_settings_mapping'))
228
231
229 @HasPermissionAllDecorator('hg.admin')
232 @HasPermissionAllDecorator('hg.admin')
230 def settings_mapping(self):
233 def settings_mapping(self):
231 """GET /admin/settings/mapping: All items in the collection"""
234 """GET /admin/settings/mapping: All items in the collection"""
232 # url('admin_settings_mapping')
235 # url('admin_settings_mapping')
233 c.active = 'mapping'
236 c.active = 'mapping'
234
237
235 return htmlfill.render(
238 return htmlfill.render(
236 render('admin/settings/settings.mako'),
239 render('admin/settings/settings.mako'),
237 defaults=self._form_defaults(),
240 defaults=self._form_defaults(),
238 encoding="UTF-8",
241 encoding="UTF-8",
239 force_defaults=False)
242 force_defaults=False)
240
243
241 @HasPermissionAllDecorator('hg.admin')
244 @HasPermissionAllDecorator('hg.admin')
242 @auth.CSRFRequired()
245 @auth.CSRFRequired()
243 def settings_global_update(self):
246 def settings_global_update(self):
244 """POST /admin/settings/global: All items in the collection"""
247 """POST /admin/settings/global: All items in the collection"""
245 # url('admin_settings_global')
248 # url('admin_settings_global')
246 c.active = 'global'
249 c.active = 'global'
247 c.personal_repo_group_default_pattern = RepoGroupModel()\
250 c.personal_repo_group_default_pattern = RepoGroupModel()\
248 .get_personal_group_name_pattern()
251 .get_personal_group_name_pattern()
249 application_form = ApplicationSettingsForm()()
252 application_form = ApplicationSettingsForm()()
250 try:
253 try:
251 form_result = application_form.to_python(dict(request.POST))
254 form_result = application_form.to_python(dict(request.POST))
252 except formencode.Invalid as errors:
255 except formencode.Invalid as errors:
253 return htmlfill.render(
256 return htmlfill.render(
254 render('admin/settings/settings.mako'),
257 render('admin/settings/settings.mako'),
255 defaults=errors.value,
258 defaults=errors.value,
256 errors=errors.error_dict or {},
259 errors=errors.error_dict or {},
257 prefix_error=False,
260 prefix_error=False,
258 encoding="UTF-8",
261 encoding="UTF-8",
259 force_defaults=False)
262 force_defaults=False)
260
263
261 try:
264 try:
262 settings = [
265 settings = [
263 ('title', 'rhodecode_title', 'unicode'),
266 ('title', 'rhodecode_title', 'unicode'),
264 ('realm', 'rhodecode_realm', 'unicode'),
267 ('realm', 'rhodecode_realm', 'unicode'),
265 ('pre_code', 'rhodecode_pre_code', 'unicode'),
268 ('pre_code', 'rhodecode_pre_code', 'unicode'),
266 ('post_code', 'rhodecode_post_code', 'unicode'),
269 ('post_code', 'rhodecode_post_code', 'unicode'),
267 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
270 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
268 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
271 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
269 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
272 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
270 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
273 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
271 ]
274 ]
272 for setting, form_key, type_ in settings:
275 for setting, form_key, type_ in settings:
273 sett = SettingsModel().create_or_update_setting(
276 sett = SettingsModel().create_or_update_setting(
274 setting, form_result[form_key], type_)
277 setting, form_result[form_key], type_)
275 Session().add(sett)
278 Session().add(sett)
276
279
277 Session().commit()
280 Session().commit()
278 SettingsModel().invalidate_settings_cache()
281 SettingsModel().invalidate_settings_cache()
279 h.flash(_('Updated application settings'), category='success')
282 h.flash(_('Updated application settings'), category='success')
280 except Exception:
283 except Exception:
281 log.exception("Exception while updating application settings")
284 log.exception("Exception while updating application settings")
282 h.flash(
285 h.flash(
283 _('Error occurred during updating application settings'),
286 _('Error occurred during updating application settings'),
284 category='error')
287 category='error')
285
288
286 return redirect(url('admin_settings_global'))
289 return redirect(url('admin_settings_global'))
287
290
288 @HasPermissionAllDecorator('hg.admin')
291 @HasPermissionAllDecorator('hg.admin')
289 def settings_global(self):
292 def settings_global(self):
290 """GET /admin/settings/global: All items in the collection"""
293 """GET /admin/settings/global: All items in the collection"""
291 # url('admin_settings_global')
294 # url('admin_settings_global')
292 c.active = 'global'
295 c.active = 'global'
293 c.personal_repo_group_default_pattern = RepoGroupModel()\
296 c.personal_repo_group_default_pattern = RepoGroupModel()\
294 .get_personal_group_name_pattern()
297 .get_personal_group_name_pattern()
295
298
296 return htmlfill.render(
299 return htmlfill.render(
297 render('admin/settings/settings.mako'),
300 render('admin/settings/settings.mako'),
298 defaults=self._form_defaults(),
301 defaults=self._form_defaults(),
299 encoding="UTF-8",
302 encoding="UTF-8",
300 force_defaults=False)
303 force_defaults=False)
301
304
302 @HasPermissionAllDecorator('hg.admin')
305 @HasPermissionAllDecorator('hg.admin')
303 @auth.CSRFRequired()
306 @auth.CSRFRequired()
304 def settings_visual_update(self):
307 def settings_visual_update(self):
305 """POST /admin/settings/visual: All items in the collection"""
308 """POST /admin/settings/visual: All items in the collection"""
306 # url('admin_settings_visual')
309 # url('admin_settings_visual')
307 c.active = 'visual'
310 c.active = 'visual'
308 application_form = ApplicationVisualisationForm()()
311 application_form = ApplicationVisualisationForm()()
309 try:
312 try:
310 form_result = application_form.to_python(dict(request.POST))
313 form_result = application_form.to_python(dict(request.POST))
311 except formencode.Invalid as errors:
314 except formencode.Invalid as errors:
312 return htmlfill.render(
315 return htmlfill.render(
313 render('admin/settings/settings.mako'),
316 render('admin/settings/settings.mako'),
314 defaults=errors.value,
317 defaults=errors.value,
315 errors=errors.error_dict or {},
318 errors=errors.error_dict or {},
316 prefix_error=False,
319 prefix_error=False,
317 encoding="UTF-8",
320 encoding="UTF-8",
318 force_defaults=False
321 force_defaults=False
319 )
322 )
320
323
321 try:
324 try:
322 settings = [
325 settings = [
323 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
326 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
324 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
327 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
325 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
328 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
326 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
329 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
327 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
330 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
328 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
331 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
329 ('show_version', 'rhodecode_show_version', 'bool'),
332 ('show_version', 'rhodecode_show_version', 'bool'),
330 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
333 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
331 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
334 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
332 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
335 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
333 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
336 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
334 ('support_url', 'rhodecode_support_url', 'unicode'),
337 ('support_url', 'rhodecode_support_url', 'unicode'),
335 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
338 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
336 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
339 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
337 ]
340 ]
338 for setting, form_key, type_ in settings:
341 for setting, form_key, type_ in settings:
339 sett = SettingsModel().create_or_update_setting(
342 sett = SettingsModel().create_or_update_setting(
340 setting, form_result[form_key], type_)
343 setting, form_result[form_key], type_)
341 Session().add(sett)
344 Session().add(sett)
342
345
343 Session().commit()
346 Session().commit()
344 SettingsModel().invalidate_settings_cache()
347 SettingsModel().invalidate_settings_cache()
345 h.flash(_('Updated visualisation settings'), category='success')
348 h.flash(_('Updated visualisation settings'), category='success')
346 except Exception:
349 except Exception:
347 log.exception("Exception updating visualization settings")
350 log.exception("Exception updating visualization settings")
348 h.flash(_('Error occurred during updating '
351 h.flash(_('Error occurred during updating '
349 'visualisation settings'),
352 'visualisation settings'),
350 category='error')
353 category='error')
351
354
352 return redirect(url('admin_settings_visual'))
355 return redirect(url('admin_settings_visual'))
353
356
354 @HasPermissionAllDecorator('hg.admin')
357 @HasPermissionAllDecorator('hg.admin')
355 def settings_visual(self):
358 def settings_visual(self):
356 """GET /admin/settings/visual: All items in the collection"""
359 """GET /admin/settings/visual: All items in the collection"""
357 # url('admin_settings_visual')
360 # url('admin_settings_visual')
358 c.active = 'visual'
361 c.active = 'visual'
359
362
360 return htmlfill.render(
363 return htmlfill.render(
361 render('admin/settings/settings.mako'),
364 render('admin/settings/settings.mako'),
362 defaults=self._form_defaults(),
365 defaults=self._form_defaults(),
363 encoding="UTF-8",
366 encoding="UTF-8",
364 force_defaults=False)
367 force_defaults=False)
365
368
366 @HasPermissionAllDecorator('hg.admin')
369 @HasPermissionAllDecorator('hg.admin')
367 @auth.CSRFRequired()
370 @auth.CSRFRequired()
368 def settings_issuetracker_test(self):
371 def settings_issuetracker_test(self):
369 if request.is_xhr:
372 if request.is_xhr:
370 return h.urlify_commit_message(
373 return h.urlify_commit_message(
371 request.POST.get('test_text', ''),
374 request.POST.get('test_text', ''),
372 'repo_group/test_repo1')
375 'repo_group/test_repo1')
373 else:
376 else:
374 raise HTTPBadRequest()
377 raise HTTPBadRequest()
375
378
376 @HasPermissionAllDecorator('hg.admin')
379 @HasPermissionAllDecorator('hg.admin')
377 @auth.CSRFRequired()
380 @auth.CSRFRequired()
378 def settings_issuetracker_delete(self):
381 def settings_issuetracker_delete(self):
379 uid = request.POST.get('uid')
382 uid = request.POST.get('uid')
380 IssueTrackerSettingsModel().delete_entries(uid)
383 IssueTrackerSettingsModel().delete_entries(uid)
381 h.flash(_('Removed issue tracker entry'), category='success')
384 h.flash(_('Removed issue tracker entry'), category='success')
382 return redirect(url('admin_settings_issuetracker'))
385 return redirect(url('admin_settings_issuetracker'))
383
386
384 @HasPermissionAllDecorator('hg.admin')
387 @HasPermissionAllDecorator('hg.admin')
385 def settings_issuetracker(self):
388 def settings_issuetracker(self):
386 """GET /admin/settings/issue-tracker: All items in the collection"""
389 """GET /admin/settings/issue-tracker: All items in the collection"""
387 # url('admin_settings_issuetracker')
390 # url('admin_settings_issuetracker')
388 c.active = 'issuetracker'
391 c.active = 'issuetracker'
389 defaults = SettingsModel().get_all_settings()
392 defaults = SettingsModel().get_all_settings()
390
393
391 entry_key = 'rhodecode_issuetracker_pat_'
394 entry_key = 'rhodecode_issuetracker_pat_'
392
395
393 c.issuetracker_entries = {}
396 c.issuetracker_entries = {}
394 for k, v in defaults.items():
397 for k, v in defaults.items():
395 if k.startswith(entry_key):
398 if k.startswith(entry_key):
396 uid = k[len(entry_key):]
399 uid = k[len(entry_key):]
397 c.issuetracker_entries[uid] = None
400 c.issuetracker_entries[uid] = None
398
401
399 for uid in c.issuetracker_entries:
402 for uid in c.issuetracker_entries:
400 c.issuetracker_entries[uid] = AttributeDict({
403 c.issuetracker_entries[uid] = AttributeDict({
401 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
404 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
402 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
405 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
403 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
406 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
404 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
407 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
405 })
408 })
406
409
407 return render('admin/settings/settings.mako')
410 return render('admin/settings/settings.mako')
408
411
409 @HasPermissionAllDecorator('hg.admin')
412 @HasPermissionAllDecorator('hg.admin')
410 @auth.CSRFRequired()
413 @auth.CSRFRequired()
411 def settings_issuetracker_save(self):
414 def settings_issuetracker_save(self):
412 settings_model = IssueTrackerSettingsModel()
415 settings_model = IssueTrackerSettingsModel()
413
416
414 form = IssueTrackerPatternsForm()().to_python(request.POST)
417 form = IssueTrackerPatternsForm()().to_python(request.POST)
415 if form:
418 if form:
416 for uid in form.get('delete_patterns', []):
419 for uid in form.get('delete_patterns', []):
417 settings_model.delete_entries(uid)
420 settings_model.delete_entries(uid)
418
421
419 for pattern in form.get('patterns', []):
422 for pattern in form.get('patterns', []):
420 for setting, value, type_ in pattern:
423 for setting, value, type_ in pattern:
421 sett = settings_model.create_or_update_setting(
424 sett = settings_model.create_or_update_setting(
422 setting, value, type_)
425 setting, value, type_)
423 Session().add(sett)
426 Session().add(sett)
424
427
425 Session().commit()
428 Session().commit()
426
429
427 SettingsModel().invalidate_settings_cache()
430 SettingsModel().invalidate_settings_cache()
428 h.flash(_('Updated issue tracker entries'), category='success')
431 h.flash(_('Updated issue tracker entries'), category='success')
429 return redirect(url('admin_settings_issuetracker'))
432 return redirect(url('admin_settings_issuetracker'))
430
433
431 @HasPermissionAllDecorator('hg.admin')
434 @HasPermissionAllDecorator('hg.admin')
432 @auth.CSRFRequired()
435 @auth.CSRFRequired()
433 def settings_email_update(self):
436 def settings_email_update(self):
434 """POST /admin/settings/email: All items in the collection"""
437 """POST /admin/settings/email: All items in the collection"""
435 # url('admin_settings_email')
438 # url('admin_settings_email')
436 c.active = 'email'
439 c.active = 'email'
437
440
438 test_email = request.POST.get('test_email')
441 test_email = request.POST.get('test_email')
439
442
440 if not test_email:
443 if not test_email:
441 h.flash(_('Please enter email address'), category='error')
444 h.flash(_('Please enter email address'), category='error')
442 return redirect(url('admin_settings_email'))
445 return redirect(url('admin_settings_email'))
443
446
444 email_kwargs = {
447 email_kwargs = {
445 'date': datetime.datetime.now(),
448 'date': datetime.datetime.now(),
446 'user': c.rhodecode_user,
449 'user': c.rhodecode_user,
447 'rhodecode_version': c.rhodecode_version
450 'rhodecode_version': c.rhodecode_version
448 }
451 }
449
452
450 (subject, headers, email_body,
453 (subject, headers, email_body,
451 email_body_plaintext) = EmailNotificationModel().render_email(
454 email_body_plaintext) = EmailNotificationModel().render_email(
452 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
455 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
453
456
454 recipients = [test_email] if test_email else None
457 recipients = [test_email] if test_email else None
455
458
456 run_task(tasks.send_email, recipients, subject,
459 run_task(tasks.send_email, recipients, subject,
457 email_body_plaintext, email_body)
460 email_body_plaintext, email_body)
458
461
459 h.flash(_('Send email task created'), category='success')
462 h.flash(_('Send email task created'), category='success')
460 return redirect(url('admin_settings_email'))
463 return redirect(url('admin_settings_email'))
461
464
462 @HasPermissionAllDecorator('hg.admin')
465 @HasPermissionAllDecorator('hg.admin')
463 def settings_email(self):
466 def settings_email(self):
464 """GET /admin/settings/email: All items in the collection"""
467 """GET /admin/settings/email: All items in the collection"""
465 # url('admin_settings_email')
468 # url('admin_settings_email')
466 c.active = 'email'
469 c.active = 'email'
467 c.rhodecode_ini = rhodecode.CONFIG
470 c.rhodecode_ini = rhodecode.CONFIG
468
471
469 return htmlfill.render(
472 return htmlfill.render(
470 render('admin/settings/settings.mako'),
473 render('admin/settings/settings.mako'),
471 defaults=self._form_defaults(),
474 defaults=self._form_defaults(),
472 encoding="UTF-8",
475 encoding="UTF-8",
473 force_defaults=False)
476 force_defaults=False)
474
477
475 @HasPermissionAllDecorator('hg.admin')
478 @HasPermissionAllDecorator('hg.admin')
476 @auth.CSRFRequired()
479 @auth.CSRFRequired()
477 def settings_hooks_update(self):
480 def settings_hooks_update(self):
478 """POST or DELETE /admin/settings/hooks: All items in the collection"""
481 """POST or DELETE /admin/settings/hooks: All items in the collection"""
479 # url('admin_settings_hooks')
482 # url('admin_settings_hooks')
480 c.active = 'hooks'
483 c.active = 'hooks'
481 if c.visual.allow_custom_hooks_settings:
484 if c.visual.allow_custom_hooks_settings:
482 ui_key = request.POST.get('new_hook_ui_key')
485 ui_key = request.POST.get('new_hook_ui_key')
483 ui_value = request.POST.get('new_hook_ui_value')
486 ui_value = request.POST.get('new_hook_ui_value')
484
487
485 hook_id = request.POST.get('hook_id')
488 hook_id = request.POST.get('hook_id')
486 new_hook = False
489 new_hook = False
487
490
488 model = SettingsModel()
491 model = SettingsModel()
489 try:
492 try:
490 if ui_value and ui_key:
493 if ui_value and ui_key:
491 model.create_or_update_hook(ui_key, ui_value)
494 model.create_or_update_hook(ui_key, ui_value)
492 h.flash(_('Added new hook'), category='success')
495 h.flash(_('Added new hook'), category='success')
493 new_hook = True
496 new_hook = True
494 elif hook_id:
497 elif hook_id:
495 RhodeCodeUi.delete(hook_id)
498 RhodeCodeUi.delete(hook_id)
496 Session().commit()
499 Session().commit()
497
500
498 # check for edits
501 # check for edits
499 update = False
502 update = False
500 _d = request.POST.dict_of_lists()
503 _d = request.POST.dict_of_lists()
501 for k, v in zip(_d.get('hook_ui_key', []),
504 for k, v in zip(_d.get('hook_ui_key', []),
502 _d.get('hook_ui_value_new', [])):
505 _d.get('hook_ui_value_new', [])):
503 model.create_or_update_hook(k, v)
506 model.create_or_update_hook(k, v)
504 update = True
507 update = True
505
508
506 if update and not new_hook:
509 if update and not new_hook:
507 h.flash(_('Updated hooks'), category='success')
510 h.flash(_('Updated hooks'), category='success')
508 Session().commit()
511 Session().commit()
509 except Exception:
512 except Exception:
510 log.exception("Exception during hook creation")
513 log.exception("Exception during hook creation")
511 h.flash(_('Error occurred during hook creation'),
514 h.flash(_('Error occurred during hook creation'),
512 category='error')
515 category='error')
513
516
514 return redirect(url('admin_settings_hooks'))
517 return redirect(url('admin_settings_hooks'))
515
518
516 @HasPermissionAllDecorator('hg.admin')
519 @HasPermissionAllDecorator('hg.admin')
517 def settings_hooks(self):
520 def settings_hooks(self):
518 """GET /admin/settings/hooks: All items in the collection"""
521 """GET /admin/settings/hooks: All items in the collection"""
519 # url('admin_settings_hooks')
522 # url('admin_settings_hooks')
520 c.active = 'hooks'
523 c.active = 'hooks'
521
524
522 model = SettingsModel()
525 model = SettingsModel()
523 c.hooks = model.get_builtin_hooks()
526 c.hooks = model.get_builtin_hooks()
524 c.custom_hooks = model.get_custom_hooks()
527 c.custom_hooks = model.get_custom_hooks()
525
528
526 return htmlfill.render(
529 return htmlfill.render(
527 render('admin/settings/settings.mako'),
530 render('admin/settings/settings.mako'),
528 defaults=self._form_defaults(),
531 defaults=self._form_defaults(),
529 encoding="UTF-8",
532 encoding="UTF-8",
530 force_defaults=False)
533 force_defaults=False)
531
534
532 @HasPermissionAllDecorator('hg.admin')
535 @HasPermissionAllDecorator('hg.admin')
533 def settings_search(self):
536 def settings_search(self):
534 """GET /admin/settings/search: All items in the collection"""
537 """GET /admin/settings/search: All items in the collection"""
535 # url('admin_settings_search')
538 # url('admin_settings_search')
536 c.active = 'search'
539 c.active = 'search'
537
540
538 from rhodecode.lib.index import searcher_from_config
541 from rhodecode.lib.index import searcher_from_config
539 searcher = searcher_from_config(config)
542 searcher = searcher_from_config(config)
540 c.statistics = searcher.statistics()
543 c.statistics = searcher.statistics()
541
544
542 return render('admin/settings/settings.mako')
545 return render('admin/settings/settings.mako')
543
546
544 @HasPermissionAllDecorator('hg.admin')
547 @HasPermissionAllDecorator('hg.admin')
545 def settings_supervisor(self):
548 def settings_supervisor(self):
546 c.rhodecode_ini = rhodecode.CONFIG
549 c.rhodecode_ini = rhodecode.CONFIG
547 c.active = 'supervisor'
550 c.active = 'supervisor'
548
551
549 c.supervisor_procs = OrderedDict([
552 c.supervisor_procs = OrderedDict([
550 (SUPERVISOR_MASTER, {}),
553 (SUPERVISOR_MASTER, {}),
551 ])
554 ])
552
555
553 c.log_size = 10240
556 c.log_size = 10240
554 supervisor = SupervisorModel()
557 supervisor = SupervisorModel()
555
558
556 _connection = supervisor.get_connection(
559 _connection = supervisor.get_connection(
557 c.rhodecode_ini.get('supervisor.uri'))
560 c.rhodecode_ini.get('supervisor.uri'))
558 c.connection_error = None
561 c.connection_error = None
559 try:
562 try:
560 _connection.supervisor.getAllProcessInfo()
563 _connection.supervisor.getAllProcessInfo()
561 except Exception as e:
564 except Exception as e:
562 c.connection_error = str(e)
565 c.connection_error = str(e)
563 log.exception("Exception reading supervisor data")
566 log.exception("Exception reading supervisor data")
564 return render('admin/settings/settings.mako')
567 return render('admin/settings/settings.mako')
565
568
566 groupid = c.rhodecode_ini.get('supervisor.group_id')
569 groupid = c.rhodecode_ini.get('supervisor.group_id')
567
570
568 # feed our group processes to the main
571 # feed our group processes to the main
569 for proc in supervisor.get_group_processes(_connection, groupid):
572 for proc in supervisor.get_group_processes(_connection, groupid):
570 c.supervisor_procs[proc['name']] = {}
573 c.supervisor_procs[proc['name']] = {}
571
574
572 for k in c.supervisor_procs.keys():
575 for k in c.supervisor_procs.keys():
573 try:
576 try:
574 # master process info
577 # master process info
575 if k == SUPERVISOR_MASTER:
578 if k == SUPERVISOR_MASTER:
576 _data = supervisor.get_master_state(_connection)
579 _data = supervisor.get_master_state(_connection)
577 _data['name'] = 'supervisor master'
580 _data['name'] = 'supervisor master'
578 _data['description'] = 'pid %s, id: %s, ver: %s' % (
581 _data['description'] = 'pid %s, id: %s, ver: %s' % (
579 _data['pid'], _data['id'], _data['ver'])
582 _data['pid'], _data['id'], _data['ver'])
580 c.supervisor_procs[k] = _data
583 c.supervisor_procs[k] = _data
581 else:
584 else:
582 procid = groupid + ":" + k
585 procid = groupid + ":" + k
583 c.supervisor_procs[k] = supervisor.get_process_info(_connection, procid)
586 c.supervisor_procs[k] = supervisor.get_process_info(_connection, procid)
584 except Exception as e:
587 except Exception as e:
585 log.exception("Exception reading supervisor data")
588 log.exception("Exception reading supervisor data")
586 c.supervisor_procs[k] = {'_rhodecode_error': str(e)}
589 c.supervisor_procs[k] = {'_rhodecode_error': str(e)}
587
590
588 return render('admin/settings/settings.mako')
591 return render('admin/settings/settings.mako')
589
592
590 @HasPermissionAllDecorator('hg.admin')
593 @HasPermissionAllDecorator('hg.admin')
591 def settings_supervisor_log(self, procid):
594 def settings_supervisor_log(self, procid):
592 import rhodecode
595 import rhodecode
593 c.rhodecode_ini = rhodecode.CONFIG
596 c.rhodecode_ini = rhodecode.CONFIG
594 c.active = 'supervisor_tail'
597 c.active = 'supervisor_tail'
595
598
596 supervisor = SupervisorModel()
599 supervisor = SupervisorModel()
597 _connection = supervisor.get_connection(c.rhodecode_ini.get('supervisor.uri'))
600 _connection = supervisor.get_connection(c.rhodecode_ini.get('supervisor.uri'))
598 groupid = c.rhodecode_ini.get('supervisor.group_id')
601 groupid = c.rhodecode_ini.get('supervisor.group_id')
599 procid = groupid + ":" + procid if procid != SUPERVISOR_MASTER else procid
602 procid = groupid + ":" + procid if procid != SUPERVISOR_MASTER else procid
600
603
601 c.log_size = 10240
604 c.log_size = 10240
602 offset = abs(safe_int(request.GET.get('offset', c.log_size))) * -1
605 offset = abs(safe_int(request.GET.get('offset', c.log_size))) * -1
603 c.log = supervisor.read_process_log(_connection, procid, offset, 0)
606 c.log = supervisor.read_process_log(_connection, procid, offset, 0)
604
607
605 return render('admin/settings/settings.mako')
608 return render('admin/settings/settings.mako')
606
609
607 @HasPermissionAllDecorator('hg.admin')
610 @HasPermissionAllDecorator('hg.admin')
608 @auth.CSRFRequired()
611 @auth.CSRFRequired()
609 def settings_labs_update(self):
612 def settings_labs_update(self):
610 """POST /admin/settings/labs: All items in the collection"""
613 """POST /admin/settings/labs: All items in the collection"""
611 # url('admin_settings/labs', method={'POST'})
614 # url('admin_settings/labs', method={'POST'})
612 c.active = 'labs'
615 c.active = 'labs'
613
616
614 application_form = LabsSettingsForm()()
617 application_form = LabsSettingsForm()()
615 try:
618 try:
616 form_result = application_form.to_python(dict(request.POST))
619 form_result = application_form.to_python(dict(request.POST))
617 except formencode.Invalid as errors:
620 except formencode.Invalid as errors:
618 h.flash(
621 h.flash(
619 _('Some form inputs contain invalid data.'),
622 _('Some form inputs contain invalid data.'),
620 category='error')
623 category='error')
621 return htmlfill.render(
624 return htmlfill.render(
622 render('admin/settings/settings.mako'),
625 render('admin/settings/settings.mako'),
623 defaults=errors.value,
626 defaults=errors.value,
624 errors=errors.error_dict or {},
627 errors=errors.error_dict or {},
625 prefix_error=False,
628 prefix_error=False,
626 encoding='UTF-8',
629 encoding='UTF-8',
627 force_defaults=False
630 force_defaults=False
628 )
631 )
629
632
630 try:
633 try:
631 session = Session()
634 session = Session()
632 for setting in _LAB_SETTINGS:
635 for setting in _LAB_SETTINGS:
633 setting_name = setting.key[len('rhodecode_'):]
636 setting_name = setting.key[len('rhodecode_'):]
634 sett = SettingsModel().create_or_update_setting(
637 sett = SettingsModel().create_or_update_setting(
635 setting_name, form_result[setting.key], setting.type)
638 setting_name, form_result[setting.key], setting.type)
636 session.add(sett)
639 session.add(sett)
637
640
638 except Exception:
641 except Exception:
639 log.exception('Exception while updating lab settings')
642 log.exception('Exception while updating lab settings')
640 h.flash(_('Error occurred during updating labs settings'),
643 h.flash(_('Error occurred during updating labs settings'),
641 category='error')
644 category='error')
642 else:
645 else:
643 Session().commit()
646 Session().commit()
644 SettingsModel().invalidate_settings_cache()
647 SettingsModel().invalidate_settings_cache()
645 h.flash(_('Updated Labs settings'), category='success')
648 h.flash(_('Updated Labs settings'), category='success')
646 return redirect(url('admin_settings_labs'))
649 return redirect(url('admin_settings_labs'))
647
650
648 return htmlfill.render(
651 return htmlfill.render(
649 render('admin/settings/settings.mako'),
652 render('admin/settings/settings.mako'),
650 defaults=self._form_defaults(),
653 defaults=self._form_defaults(),
651 encoding='UTF-8',
654 encoding='UTF-8',
652 force_defaults=False)
655 force_defaults=False)
653
656
654 @HasPermissionAllDecorator('hg.admin')
657 @HasPermissionAllDecorator('hg.admin')
655 def settings_labs(self):
658 def settings_labs(self):
656 """GET /admin/settings/labs: All items in the collection"""
659 """GET /admin/settings/labs: All items in the collection"""
657 # url('admin_settings_labs')
660 # url('admin_settings_labs')
658 if not c.labs_active:
661 if not c.labs_active:
659 redirect(url('admin_settings'))
662 redirect(url('admin_settings'))
660
663
661 c.active = 'labs'
664 c.active = 'labs'
662 c.lab_settings = _LAB_SETTINGS
665 c.lab_settings = _LAB_SETTINGS
663
666
664 return htmlfill.render(
667 return htmlfill.render(
665 render('admin/settings/settings.mako'),
668 render('admin/settings/settings.mako'),
666 defaults=self._form_defaults(),
669 defaults=self._form_defaults(),
667 encoding='UTF-8',
670 encoding='UTF-8',
668 force_defaults=False)
671 force_defaults=False)
669
672
670 def _form_defaults(self):
673 def _form_defaults(self):
671 defaults = SettingsModel().get_all_settings()
674 defaults = SettingsModel().get_all_settings()
672 defaults.update(self._get_ui_settings())
675 defaults.update(self._get_ui_settings())
673
676
674 defaults.update({
677 defaults.update({
675 'new_svn_branch': '',
678 'new_svn_branch': '',
676 'new_svn_tag': '',
679 'new_svn_tag': '',
677 })
680 })
678 return defaults
681 return defaults
679
682
680
683
681 # :param key: name of the setting including the 'rhodecode_' prefix
684 # :param key: name of the setting including the 'rhodecode_' prefix
682 # :param type: the RhodeCodeSetting type to use.
685 # :param type: the RhodeCodeSetting type to use.
683 # :param group: the i18ned group in which we should dispaly this setting
686 # :param group: the i18ned group in which we should dispaly this setting
684 # :param label: the i18ned label we should display for this setting
687 # :param label: the i18ned label we should display for this setting
685 # :param help: the i18ned help we should dispaly for this setting
688 # :param help: the i18ned help we should dispaly for this setting
686 LabSetting = collections.namedtuple(
689 LabSetting = collections.namedtuple(
687 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
690 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
688
691
689
692
690 # This list has to be kept in sync with the form
693 # This list has to be kept in sync with the form
691 # rhodecode.model.forms.LabsSettingsForm.
694 # rhodecode.model.forms.LabsSettingsForm.
692 _LAB_SETTINGS = [
695 _LAB_SETTINGS = [
693
696
694 ]
697 ]
@@ -1,777 +1,802 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 import os
21 import hashlib
22 import hashlib
22 import logging
23 import logging
23 from collections import namedtuple
24 from collections import namedtuple
24 from functools import wraps
25 from functools import wraps
25
26
26 from rhodecode.lib import caches
27 from rhodecode.lib import caches
27 from rhodecode.lib.utils2 import (
28 from rhodecode.lib.utils2 import (
28 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
29 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
29 from rhodecode.lib.vcs.backends import base
30 from rhodecode.lib.vcs.backends import base
30 from rhodecode.model import BaseModel
31 from rhodecode.model import BaseModel
31 from rhodecode.model.db import (
32 from rhodecode.model.db import (
32 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
33 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
33 from rhodecode.model.meta import Session
34 from rhodecode.model.meta import Session
34
35
35
36
36 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
37
38
38
39
39 UiSetting = namedtuple(
40 UiSetting = namedtuple(
40 'UiSetting', ['section', 'key', 'value', 'active'])
41 'UiSetting', ['section', 'key', 'value', 'active'])
41
42
42 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
43 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
43
44
44
45
45 class SettingNotFound(Exception):
46 class SettingNotFound(Exception):
46 def __init__(self):
47 def __init__(self):
47 super(SettingNotFound, self).__init__('Setting is not found')
48 super(SettingNotFound, self).__init__('Setting is not found')
48
49
49
50
50 class SettingsModel(BaseModel):
51 class SettingsModel(BaseModel):
51 BUILTIN_HOOKS = (
52 BUILTIN_HOOKS = (
52 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
53 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
53 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
54 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
54 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL)
55 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL)
55 HOOKS_SECTION = 'hooks'
56 HOOKS_SECTION = 'hooks'
56
57
57 def __init__(self, sa=None, repo=None):
58 def __init__(self, sa=None, repo=None):
58 self.repo = repo
59 self.repo = repo
59 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
60 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
60 self.SettingsDbModel = (
61 self.SettingsDbModel = (
61 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
62 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
62 super(SettingsModel, self).__init__(sa)
63 super(SettingsModel, self).__init__(sa)
63
64
64 def get_ui_by_key(self, key):
65 def get_ui_by_key(self, key):
65 q = self.UiDbModel.query()
66 q = self.UiDbModel.query()
66 q = q.filter(self.UiDbModel.ui_key == key)
67 q = q.filter(self.UiDbModel.ui_key == key)
67 q = self._filter_by_repo(RepoRhodeCodeUi, q)
68 q = self._filter_by_repo(RepoRhodeCodeUi, q)
68 return q.scalar()
69 return q.scalar()
69
70
70 def get_ui_by_section(self, section):
71 def get_ui_by_section(self, section):
71 q = self.UiDbModel.query()
72 q = self.UiDbModel.query()
72 q = q.filter(self.UiDbModel.ui_section == section)
73 q = q.filter(self.UiDbModel.ui_section == section)
73 q = self._filter_by_repo(RepoRhodeCodeUi, q)
74 q = self._filter_by_repo(RepoRhodeCodeUi, q)
74 return q.all()
75 return q.all()
75
76
76 def get_ui_by_section_and_key(self, section, key):
77 def get_ui_by_section_and_key(self, section, key):
77 q = self.UiDbModel.query()
78 q = self.UiDbModel.query()
78 q = q.filter(self.UiDbModel.ui_section == section)
79 q = q.filter(self.UiDbModel.ui_section == section)
79 q = q.filter(self.UiDbModel.ui_key == key)
80 q = q.filter(self.UiDbModel.ui_key == key)
80 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 return q.scalar()
82 return q.scalar()
82
83
83 def get_ui(self, section=None, key=None):
84 def get_ui(self, section=None, key=None):
84 q = self.UiDbModel.query()
85 q = self.UiDbModel.query()
85 q = self._filter_by_repo(RepoRhodeCodeUi, q)
86 q = self._filter_by_repo(RepoRhodeCodeUi, q)
86
87
87 if section:
88 if section:
88 q = q.filter(self.UiDbModel.ui_section == section)
89 q = q.filter(self.UiDbModel.ui_section == section)
89 if key:
90 if key:
90 q = q.filter(self.UiDbModel.ui_key == key)
91 q = q.filter(self.UiDbModel.ui_key == key)
91
92
92 # TODO: mikhail: add caching
93 # TODO: mikhail: add caching
93 result = [
94 result = [
94 UiSetting(
95 UiSetting(
95 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
96 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
96 value=safe_str(r.ui_value), active=r.ui_active
97 value=safe_str(r.ui_value), active=r.ui_active
97 )
98 )
98 for r in q.all()
99 for r in q.all()
99 ]
100 ]
100 return result
101 return result
101
102
102 def get_builtin_hooks(self):
103 def get_builtin_hooks(self):
103 q = self.UiDbModel.query()
104 q = self.UiDbModel.query()
104 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
105 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
105 return self._get_hooks(q)
106 return self._get_hooks(q)
106
107
107 def get_custom_hooks(self):
108 def get_custom_hooks(self):
108 q = self.UiDbModel.query()
109 q = self.UiDbModel.query()
109 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
110 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
110 return self._get_hooks(q)
111 return self._get_hooks(q)
111
112
112 def create_ui_section_value(self, section, val, key=None, active=True):
113 def create_ui_section_value(self, section, val, key=None, active=True):
113 new_ui = self.UiDbModel()
114 new_ui = self.UiDbModel()
114 new_ui.ui_section = section
115 new_ui.ui_section = section
115 new_ui.ui_value = val
116 new_ui.ui_value = val
116 new_ui.ui_active = active
117 new_ui.ui_active = active
117
118
118 if self.repo:
119 if self.repo:
119 repo = self._get_repo(self.repo)
120 repo = self._get_repo(self.repo)
120 repository_id = repo.repo_id
121 repository_id = repo.repo_id
121 new_ui.repository_id = repository_id
122 new_ui.repository_id = repository_id
122
123
123 if not key:
124 if not key:
124 # keys are unique so they need appended info
125 # keys are unique so they need appended info
125 if self.repo:
126 if self.repo:
126 key = hashlib.sha1(
127 key = hashlib.sha1(
127 '{}{}{}'.format(section, val, repository_id)).hexdigest()
128 '{}{}{}'.format(section, val, repository_id)).hexdigest()
128 else:
129 else:
129 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
130 key = hashlib.sha1('{}{}'.format(section, val)).hexdigest()
130
131
131 new_ui.ui_key = key
132 new_ui.ui_key = key
132
133
133 Session().add(new_ui)
134 Session().add(new_ui)
134 return new_ui
135 return new_ui
135
136
136 def create_or_update_hook(self, key, value):
137 def create_or_update_hook(self, key, value):
137 ui = (
138 ui = (
138 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
139 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
139 self.UiDbModel())
140 self.UiDbModel())
140 ui.ui_section = self.HOOKS_SECTION
141 ui.ui_section = self.HOOKS_SECTION
141 ui.ui_active = True
142 ui.ui_active = True
142 ui.ui_key = key
143 ui.ui_key = key
143 ui.ui_value = value
144 ui.ui_value = value
144
145
145 if self.repo:
146 if self.repo:
146 repo = self._get_repo(self.repo)
147 repo = self._get_repo(self.repo)
147 repository_id = repo.repo_id
148 repository_id = repo.repo_id
148 ui.repository_id = repository_id
149 ui.repository_id = repository_id
149
150
150 Session().add(ui)
151 Session().add(ui)
151 return ui
152 return ui
152
153
153 def delete_ui(self, id_):
154 def delete_ui(self, id_):
154 ui = self.UiDbModel.get(id_)
155 ui = self.UiDbModel.get(id_)
155 if not ui:
156 if not ui:
156 raise SettingNotFound()
157 raise SettingNotFound()
157 Session().delete(ui)
158 Session().delete(ui)
158
159
159 def get_setting_by_name(self, name):
160 def get_setting_by_name(self, name):
160 q = self._get_settings_query()
161 q = self._get_settings_query()
161 q = q.filter(self.SettingsDbModel.app_settings_name == name)
162 q = q.filter(self.SettingsDbModel.app_settings_name == name)
162 return q.scalar()
163 return q.scalar()
163
164
164 def create_or_update_setting(
165 def create_or_update_setting(
165 self, name, val=Optional(''), type_=Optional('unicode')):
166 self, name, val=Optional(''), type_=Optional('unicode')):
166 """
167 """
167 Creates or updates RhodeCode setting. If updates is triggered it will
168 Creates or updates RhodeCode setting. If updates is triggered it will
168 only update parameters that are explicityl set Optional instance will
169 only update parameters that are explicityl set Optional instance will
169 be skipped
170 be skipped
170
171
171 :param name:
172 :param name:
172 :param val:
173 :param val:
173 :param type_:
174 :param type_:
174 :return:
175 :return:
175 """
176 """
176
177
177 res = self.get_setting_by_name(name)
178 res = self.get_setting_by_name(name)
178 repo = self._get_repo(self.repo) if self.repo else None
179 repo = self._get_repo(self.repo) if self.repo else None
179
180
180 if not res:
181 if not res:
181 val = Optional.extract(val)
182 val = Optional.extract(val)
182 type_ = Optional.extract(type_)
183 type_ = Optional.extract(type_)
183
184
184 args = (
185 args = (
185 (repo.repo_id, name, val, type_)
186 (repo.repo_id, name, val, type_)
186 if repo else (name, val, type_))
187 if repo else (name, val, type_))
187 res = self.SettingsDbModel(*args)
188 res = self.SettingsDbModel(*args)
188
189
189 else:
190 else:
190 if self.repo:
191 if self.repo:
191 res.repository_id = repo.repo_id
192 res.repository_id = repo.repo_id
192
193
193 res.app_settings_name = name
194 res.app_settings_name = name
194 if not isinstance(type_, Optional):
195 if not isinstance(type_, Optional):
195 # update if set
196 # update if set
196 res.app_settings_type = type_
197 res.app_settings_type = type_
197 if not isinstance(val, Optional):
198 if not isinstance(val, Optional):
198 # update if set
199 # update if set
199 res.app_settings_value = val
200 res.app_settings_value = val
200
201
201 Session().add(res)
202 Session().add(res)
202 return res
203 return res
203
204
204 def invalidate_settings_cache(self):
205 def invalidate_settings_cache(self):
205 namespace = 'rhodecode_settings'
206 namespace = 'rhodecode_settings'
206 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
207 cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
207 caches.clear_cache_manager(cache_manager)
208 caches.clear_cache_manager(cache_manager)
208
209
209 def get_all_settings(self, cache=False):
210 def get_all_settings(self, cache=False):
210
211
211 def _compute():
212 def _compute():
212 q = self._get_settings_query()
213 q = self._get_settings_query()
213 if not q:
214 if not q:
214 raise Exception('Could not get application settings !')
215 raise Exception('Could not get application settings !')
215
216
216 settings = {
217 settings = {
217 'rhodecode_' + result.app_settings_name: result.app_settings_value
218 'rhodecode_' + result.app_settings_name: result.app_settings_value
218 for result in q
219 for result in q
219 }
220 }
220 return settings
221 return settings
221
222
222 if cache:
223 if cache:
223 log.debug('Fetching app settings using cache')
224 log.debug('Fetching app settings using cache')
224 repo = self._get_repo(self.repo) if self.repo else None
225 repo = self._get_repo(self.repo) if self.repo else None
225 namespace = 'rhodecode_settings'
226 namespace = 'rhodecode_settings'
226 cache_manager = caches.get_cache_manager(
227 cache_manager = caches.get_cache_manager(
227 'sql_cache_short', namespace)
228 'sql_cache_short', namespace)
228 _cache_key = (
229 _cache_key = (
229 "get_repo_{}_settings".format(repo.repo_id)
230 "get_repo_{}_settings".format(repo.repo_id)
230 if repo else "get_app_settings")
231 if repo else "get_app_settings")
231
232
232 return cache_manager.get(_cache_key, createfunc=_compute)
233 return cache_manager.get(_cache_key, createfunc=_compute)
233
234
234 else:
235 else:
235 return _compute()
236 return _compute()
236
237
237 def get_auth_settings(self):
238 def get_auth_settings(self):
238 q = self._get_settings_query()
239 q = self._get_settings_query()
239 q = q.filter(
240 q = q.filter(
240 self.SettingsDbModel.app_settings_name.startswith('auth_'))
241 self.SettingsDbModel.app_settings_name.startswith('auth_'))
241 rows = q.all()
242 rows = q.all()
242 auth_settings = {
243 auth_settings = {
243 row.app_settings_name: row.app_settings_value for row in rows}
244 row.app_settings_name: row.app_settings_value for row in rows}
244 return auth_settings
245 return auth_settings
245
246
246 def get_auth_plugins(self):
247 def get_auth_plugins(self):
247 auth_plugins = self.get_setting_by_name("auth_plugins")
248 auth_plugins = self.get_setting_by_name("auth_plugins")
248 return auth_plugins.app_settings_value
249 return auth_plugins.app_settings_value
249
250
250 def get_default_repo_settings(self, strip_prefix=False):
251 def get_default_repo_settings(self, strip_prefix=False):
251 q = self._get_settings_query()
252 q = self._get_settings_query()
252 q = q.filter(
253 q = q.filter(
253 self.SettingsDbModel.app_settings_name.startswith('default_'))
254 self.SettingsDbModel.app_settings_name.startswith('default_'))
254 rows = q.all()
255 rows = q.all()
255
256
256 result = {}
257 result = {}
257 for row in rows:
258 for row in rows:
258 key = row.app_settings_name
259 key = row.app_settings_name
259 if strip_prefix:
260 if strip_prefix:
260 key = remove_prefix(key, prefix='default_')
261 key = remove_prefix(key, prefix='default_')
261 result.update({key: row.app_settings_value})
262 result.update({key: row.app_settings_value})
262 return result
263 return result
263
264
264 def get_repo(self):
265 def get_repo(self):
265 repo = self._get_repo(self.repo)
266 repo = self._get_repo(self.repo)
266 if not repo:
267 if not repo:
267 raise Exception(
268 raise Exception(
268 'Repository `{}` cannot be found inside the database'.format(
269 'Repository `{}` cannot be found inside the database'.format(
269 self.repo))
270 self.repo))
270 return repo
271 return repo
271
272
272 def _filter_by_repo(self, model, query):
273 def _filter_by_repo(self, model, query):
273 if self.repo:
274 if self.repo:
274 repo = self.get_repo()
275 repo = self.get_repo()
275 query = query.filter(model.repository_id == repo.repo_id)
276 query = query.filter(model.repository_id == repo.repo_id)
276 return query
277 return query
277
278
278 def _get_hooks(self, query):
279 def _get_hooks(self, query):
279 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
280 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
280 query = self._filter_by_repo(RepoRhodeCodeUi, query)
281 query = self._filter_by_repo(RepoRhodeCodeUi, query)
281 return query.all()
282 return query.all()
282
283
283 def _get_settings_query(self):
284 def _get_settings_query(self):
284 q = self.SettingsDbModel.query()
285 q = self.SettingsDbModel.query()
285 return self._filter_by_repo(RepoRhodeCodeSetting, q)
286 return self._filter_by_repo(RepoRhodeCodeSetting, q)
286
287
287 def list_enabled_social_plugins(self, settings):
288 def list_enabled_social_plugins(self, settings):
288 enabled = []
289 enabled = []
289 for plug in SOCIAL_PLUGINS_LIST:
290 for plug in SOCIAL_PLUGINS_LIST:
290 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
291 if str2bool(settings.get('rhodecode_auth_{}_enabled'.format(plug)
291 )):
292 )):
292 enabled.append(plug)
293 enabled.append(plug)
293 return enabled
294 return enabled
294
295
295
296
296 def assert_repo_settings(func):
297 def assert_repo_settings(func):
297 @wraps(func)
298 @wraps(func)
298 def _wrapper(self, *args, **kwargs):
299 def _wrapper(self, *args, **kwargs):
299 if not self.repo_settings:
300 if not self.repo_settings:
300 raise Exception('Repository is not specified')
301 raise Exception('Repository is not specified')
301 return func(self, *args, **kwargs)
302 return func(self, *args, **kwargs)
302 return _wrapper
303 return _wrapper
303
304
304
305
305 class IssueTrackerSettingsModel(object):
306 class IssueTrackerSettingsModel(object):
306 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
307 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
307 SETTINGS_PREFIX = 'issuetracker_'
308 SETTINGS_PREFIX = 'issuetracker_'
308
309
309 def __init__(self, sa=None, repo=None):
310 def __init__(self, sa=None, repo=None):
310 self.global_settings = SettingsModel(sa=sa)
311 self.global_settings = SettingsModel(sa=sa)
311 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
312 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
312
313
313 @property
314 @property
314 def inherit_global_settings(self):
315 def inherit_global_settings(self):
315 if not self.repo_settings:
316 if not self.repo_settings:
316 return True
317 return True
317 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
318 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
318 return setting.app_settings_value if setting else True
319 return setting.app_settings_value if setting else True
319
320
320 @inherit_global_settings.setter
321 @inherit_global_settings.setter
321 def inherit_global_settings(self, value):
322 def inherit_global_settings(self, value):
322 if self.repo_settings:
323 if self.repo_settings:
323 settings = self.repo_settings.create_or_update_setting(
324 settings = self.repo_settings.create_or_update_setting(
324 self.INHERIT_SETTINGS, value, type_='bool')
325 self.INHERIT_SETTINGS, value, type_='bool')
325 Session().add(settings)
326 Session().add(settings)
326
327
327 def _get_keyname(self, key, uid, prefix=''):
328 def _get_keyname(self, key, uid, prefix=''):
328 return '{0}{1}{2}_{3}'.format(
329 return '{0}{1}{2}_{3}'.format(
329 prefix, self.SETTINGS_PREFIX, key, uid)
330 prefix, self.SETTINGS_PREFIX, key, uid)
330
331
331 def _make_dict_for_settings(self, qs):
332 def _make_dict_for_settings(self, qs):
332 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
333 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
333
334
334 issuetracker_entries = {}
335 issuetracker_entries = {}
335 # create keys
336 # create keys
336 for k, v in qs.items():
337 for k, v in qs.items():
337 if k.startswith(prefix_match):
338 if k.startswith(prefix_match):
338 uid = k[len(prefix_match):]
339 uid = k[len(prefix_match):]
339 issuetracker_entries[uid] = None
340 issuetracker_entries[uid] = None
340
341
341 # populate
342 # populate
342 for uid in issuetracker_entries:
343 for uid in issuetracker_entries:
343 issuetracker_entries[uid] = AttributeDict({
344 issuetracker_entries[uid] = AttributeDict({
344 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
345 'pat': qs.get(self._get_keyname('pat', uid, 'rhodecode_')),
345 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
346 'url': qs.get(self._get_keyname('url', uid, 'rhodecode_')),
346 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
347 'pref': qs.get(self._get_keyname('pref', uid, 'rhodecode_')),
347 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
348 'desc': qs.get(self._get_keyname('desc', uid, 'rhodecode_')),
348 })
349 })
349 return issuetracker_entries
350 return issuetracker_entries
350
351
351 def get_global_settings(self, cache=False):
352 def get_global_settings(self, cache=False):
352 """
353 """
353 Returns list of global issue tracker settings
354 Returns list of global issue tracker settings
354 """
355 """
355 defaults = self.global_settings.get_all_settings(cache=cache)
356 defaults = self.global_settings.get_all_settings(cache=cache)
356 settings = self._make_dict_for_settings(defaults)
357 settings = self._make_dict_for_settings(defaults)
357 return settings
358 return settings
358
359
359 def get_repo_settings(self, cache=False):
360 def get_repo_settings(self, cache=False):
360 """
361 """
361 Returns list of issue tracker settings per repository
362 Returns list of issue tracker settings per repository
362 """
363 """
363 if not self.repo_settings:
364 if not self.repo_settings:
364 raise Exception('Repository is not specified')
365 raise Exception('Repository is not specified')
365 all_settings = self.repo_settings.get_all_settings(cache=cache)
366 all_settings = self.repo_settings.get_all_settings(cache=cache)
366 settings = self._make_dict_for_settings(all_settings)
367 settings = self._make_dict_for_settings(all_settings)
367 return settings
368 return settings
368
369
369 def get_settings(self, cache=False):
370 def get_settings(self, cache=False):
370 if self.inherit_global_settings:
371 if self.inherit_global_settings:
371 return self.get_global_settings(cache=cache)
372 return self.get_global_settings(cache=cache)
372 else:
373 else:
373 return self.get_repo_settings(cache=cache)
374 return self.get_repo_settings(cache=cache)
374
375
375 def delete_entries(self, uid):
376 def delete_entries(self, uid):
376 if self.repo_settings:
377 if self.repo_settings:
377 all_patterns = self.get_repo_settings()
378 all_patterns = self.get_repo_settings()
378 settings_model = self.repo_settings
379 settings_model = self.repo_settings
379 else:
380 else:
380 all_patterns = self.get_global_settings()
381 all_patterns = self.get_global_settings()
381 settings_model = self.global_settings
382 settings_model = self.global_settings
382 entries = all_patterns.get(uid)
383 entries = all_patterns.get(uid)
383
384
384 for del_key in entries:
385 for del_key in entries:
385 setting_name = self._get_keyname(del_key, uid)
386 setting_name = self._get_keyname(del_key, uid)
386 entry = settings_model.get_setting_by_name(setting_name)
387 entry = settings_model.get_setting_by_name(setting_name)
387 if entry:
388 if entry:
388 Session().delete(entry)
389 Session().delete(entry)
389
390
390 Session().commit()
391 Session().commit()
391
392
392 def create_or_update_setting(
393 def create_or_update_setting(
393 self, name, val=Optional(''), type_=Optional('unicode')):
394 self, name, val=Optional(''), type_=Optional('unicode')):
394 if self.repo_settings:
395 if self.repo_settings:
395 setting = self.repo_settings.create_or_update_setting(
396 setting = self.repo_settings.create_or_update_setting(
396 name, val, type_)
397 name, val, type_)
397 else:
398 else:
398 setting = self.global_settings.create_or_update_setting(
399 setting = self.global_settings.create_or_update_setting(
399 name, val, type_)
400 name, val, type_)
400 return setting
401 return setting
401
402
402
403
403 class VcsSettingsModel(object):
404 class VcsSettingsModel(object):
404
405
405 INHERIT_SETTINGS = 'inherit_vcs_settings'
406 INHERIT_SETTINGS = 'inherit_vcs_settings'
406 GENERAL_SETTINGS = (
407 GENERAL_SETTINGS = (
407 'use_outdated_comments',
408 'use_outdated_comments',
408 'pr_merge_enabled',
409 'pr_merge_enabled',
409 'hg_use_rebase_for_merging')
410 'hg_use_rebase_for_merging')
410
411
411 HOOKS_SETTINGS = (
412 HOOKS_SETTINGS = (
412 ('hooks', 'changegroup.repo_size'),
413 ('hooks', 'changegroup.repo_size'),
413 ('hooks', 'changegroup.push_logger'),
414 ('hooks', 'changegroup.push_logger'),
414 ('hooks', 'outgoing.pull_logger'),)
415 ('hooks', 'outgoing.pull_logger'),)
415 HG_SETTINGS = (
416 HG_SETTINGS = (
416 ('extensions', 'largefiles'),
417 ('extensions', 'largefiles'),
417 ('phases', 'publish'),)
418 ('phases', 'publish'),)
418 GIT_SETTINGS = (
419 GIT_SETTINGS = (
419 ('vcs_git_lfs', 'enabled'),)
420 ('vcs_git_lfs', 'enabled'),)
420
421
421 GLOBAL_HG_SETTINGS = (
422 GLOBAL_HG_SETTINGS = (
422 ('extensions', 'largefiles'),
423 ('extensions', 'largefiles'),
423 ('largefiles', 'usercache'),
424 ('largefiles', 'usercache'),
424 ('phases', 'publish'),
425 ('phases', 'publish'),
425 ('extensions', 'hgsubversion'))
426 ('extensions', 'hgsubversion'))
426 GLOBAL_GIT_SETTINGS = (
427 GLOBAL_GIT_SETTINGS = (
427 ('vcs_git_lfs', 'enabled'),
428 ('vcs_git_lfs', 'enabled'),
428 ('vcs_git_lfs', 'store_location'))
429 ('vcs_git_lfs', 'store_location'))
429 GLOBAL_SVN_SETTINGS = (
430 GLOBAL_SVN_SETTINGS = (
430 ('vcs_svn_proxy', 'http_requests_enabled'),
431 ('vcs_svn_proxy', 'http_requests_enabled'),
431 ('vcs_svn_proxy', 'http_server_url'))
432 ('vcs_svn_proxy', 'http_server_url'))
432
433
433 SVN_BRANCH_SECTION = 'vcs_svn_branch'
434 SVN_BRANCH_SECTION = 'vcs_svn_branch'
434 SVN_TAG_SECTION = 'vcs_svn_tag'
435 SVN_TAG_SECTION = 'vcs_svn_tag'
435 SSL_SETTING = ('web', 'push_ssl')
436 SSL_SETTING = ('web', 'push_ssl')
436 PATH_SETTING = ('paths', '/')
437 PATH_SETTING = ('paths', '/')
437
438
438 def __init__(self, sa=None, repo=None):
439 def __init__(self, sa=None, repo=None):
439 self.global_settings = SettingsModel(sa=sa)
440 self.global_settings = SettingsModel(sa=sa)
440 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
441 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
441 self._ui_settings = (
442 self._ui_settings = (
442 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
443 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
443 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
444 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
444
445
445 @property
446 @property
446 @assert_repo_settings
447 @assert_repo_settings
447 def inherit_global_settings(self):
448 def inherit_global_settings(self):
448 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
449 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
449 return setting.app_settings_value if setting else True
450 return setting.app_settings_value if setting else True
450
451
451 @inherit_global_settings.setter
452 @inherit_global_settings.setter
452 @assert_repo_settings
453 @assert_repo_settings
453 def inherit_global_settings(self, value):
454 def inherit_global_settings(self, value):
454 self.repo_settings.create_or_update_setting(
455 self.repo_settings.create_or_update_setting(
455 self.INHERIT_SETTINGS, value, type_='bool')
456 self.INHERIT_SETTINGS, value, type_='bool')
456
457
457 def get_global_svn_branch_patterns(self):
458 def get_global_svn_branch_patterns(self):
458 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
459 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
459
460
460 @assert_repo_settings
461 @assert_repo_settings
461 def get_repo_svn_branch_patterns(self):
462 def get_repo_svn_branch_patterns(self):
462 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
463 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
463
464
464 def get_global_svn_tag_patterns(self):
465 def get_global_svn_tag_patterns(self):
465 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
466 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
466
467
467 @assert_repo_settings
468 @assert_repo_settings
468 def get_repo_svn_tag_patterns(self):
469 def get_repo_svn_tag_patterns(self):
469 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
470 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
470
471
471 def get_global_settings(self):
472 def get_global_settings(self):
472 return self._collect_all_settings(global_=True)
473 return self._collect_all_settings(global_=True)
473
474
474 @assert_repo_settings
475 @assert_repo_settings
475 def get_repo_settings(self):
476 def get_repo_settings(self):
476 return self._collect_all_settings(global_=False)
477 return self._collect_all_settings(global_=False)
477
478
478 @assert_repo_settings
479 @assert_repo_settings
479 def create_or_update_repo_settings(
480 def create_or_update_repo_settings(
480 self, data, inherit_global_settings=False):
481 self, data, inherit_global_settings=False):
481 from rhodecode.model.scm import ScmModel
482 from rhodecode.model.scm import ScmModel
482
483
483 self.inherit_global_settings = inherit_global_settings
484 self.inherit_global_settings = inherit_global_settings
484
485
485 repo = self.repo_settings.get_repo()
486 repo = self.repo_settings.get_repo()
486 if not inherit_global_settings:
487 if not inherit_global_settings:
487 if repo.repo_type == 'svn':
488 if repo.repo_type == 'svn':
488 self.create_repo_svn_settings(data)
489 self.create_repo_svn_settings(data)
489 else:
490 else:
490 self.create_or_update_repo_hook_settings(data)
491 self.create_or_update_repo_hook_settings(data)
491 self.create_or_update_repo_pr_settings(data)
492 self.create_or_update_repo_pr_settings(data)
492
493
493 if repo.repo_type == 'hg':
494 if repo.repo_type == 'hg':
494 self.create_or_update_repo_hg_settings(data)
495 self.create_or_update_repo_hg_settings(data)
495
496
496 if repo.repo_type == 'git':
497 if repo.repo_type == 'git':
497 self.create_or_update_repo_git_settings(data)
498 self.create_or_update_repo_git_settings(data)
498
499
499 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
500 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
500
501
501 @assert_repo_settings
502 @assert_repo_settings
502 def create_or_update_repo_hook_settings(self, data):
503 def create_or_update_repo_hook_settings(self, data):
503 for section, key in self.HOOKS_SETTINGS:
504 for section, key in self.HOOKS_SETTINGS:
504 data_key = self._get_form_ui_key(section, key)
505 data_key = self._get_form_ui_key(section, key)
505 if data_key not in data:
506 if data_key not in data:
506 raise ValueError(
507 raise ValueError(
507 'The given data does not contain {} key'.format(data_key))
508 'The given data does not contain {} key'.format(data_key))
508
509
509 active = data.get(data_key)
510 active = data.get(data_key)
510 repo_setting = self.repo_settings.get_ui_by_section_and_key(
511 repo_setting = self.repo_settings.get_ui_by_section_and_key(
511 section, key)
512 section, key)
512 if not repo_setting:
513 if not repo_setting:
513 global_setting = self.global_settings.\
514 global_setting = self.global_settings.\
514 get_ui_by_section_and_key(section, key)
515 get_ui_by_section_and_key(section, key)
515 self.repo_settings.create_ui_section_value(
516 self.repo_settings.create_ui_section_value(
516 section, global_setting.ui_value, key=key, active=active)
517 section, global_setting.ui_value, key=key, active=active)
517 else:
518 else:
518 repo_setting.ui_active = active
519 repo_setting.ui_active = active
519 Session().add(repo_setting)
520 Session().add(repo_setting)
520
521
521 def update_global_hook_settings(self, data):
522 def update_global_hook_settings(self, data):
522 for section, key in self.HOOKS_SETTINGS:
523 for section, key in self.HOOKS_SETTINGS:
523 data_key = self._get_form_ui_key(section, key)
524 data_key = self._get_form_ui_key(section, key)
524 if data_key not in data:
525 if data_key not in data:
525 raise ValueError(
526 raise ValueError(
526 'The given data does not contain {} key'.format(data_key))
527 'The given data does not contain {} key'.format(data_key))
527 active = data.get(data_key)
528 active = data.get(data_key)
528 repo_setting = self.global_settings.get_ui_by_section_and_key(
529 repo_setting = self.global_settings.get_ui_by_section_and_key(
529 section, key)
530 section, key)
530 repo_setting.ui_active = active
531 repo_setting.ui_active = active
531 Session().add(repo_setting)
532 Session().add(repo_setting)
532
533
533 @assert_repo_settings
534 @assert_repo_settings
534 def create_or_update_repo_pr_settings(self, data):
535 def create_or_update_repo_pr_settings(self, data):
535 return self._create_or_update_general_settings(
536 return self._create_or_update_general_settings(
536 self.repo_settings, data)
537 self.repo_settings, data)
537
538
538 def create_or_update_global_pr_settings(self, data):
539 def create_or_update_global_pr_settings(self, data):
539 return self._create_or_update_general_settings(
540 return self._create_or_update_general_settings(
540 self.global_settings, data)
541 self.global_settings, data)
541
542
542 @assert_repo_settings
543 @assert_repo_settings
543 def create_repo_svn_settings(self, data):
544 def create_repo_svn_settings(self, data):
544 return self._create_svn_settings(self.repo_settings, data)
545 return self._create_svn_settings(self.repo_settings, data)
545
546
546 @assert_repo_settings
547 @assert_repo_settings
547 def create_or_update_repo_hg_settings(self, data):
548 def create_or_update_repo_hg_settings(self, data):
548 largefiles, phases = \
549 largefiles, phases = \
549 self.HG_SETTINGS
550 self.HG_SETTINGS
550 largefiles_key, phases_key = \
551 largefiles_key, phases_key = \
551 self._get_settings_keys(self.HG_SETTINGS, data)
552 self._get_settings_keys(self.HG_SETTINGS, data)
552
553
553 self._create_or_update_ui(
554 self._create_or_update_ui(
554 self.repo_settings, *largefiles, value='',
555 self.repo_settings, *largefiles, value='',
555 active=data[largefiles_key])
556 active=data[largefiles_key])
556 self._create_or_update_ui(
557 self._create_or_update_ui(
557 self.repo_settings, *phases, value=safe_str(data[phases_key]))
558 self.repo_settings, *phases, value=safe_str(data[phases_key]))
558
559
559 def create_or_update_global_hg_settings(self, data):
560 def create_or_update_global_hg_settings(self, data):
560 largefiles, largefiles_store, phases, hgsubversion \
561 largefiles, largefiles_store, phases, hgsubversion \
561 = self.GLOBAL_HG_SETTINGS
562 = self.GLOBAL_HG_SETTINGS
562 largefiles_key, largefiles_store_key, phases_key, subversion_key \
563 largefiles_key, largefiles_store_key, phases_key, subversion_key \
563 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
564 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS, data)
564 self._create_or_update_ui(
565 self._create_or_update_ui(
565 self.global_settings, *largefiles, value='',
566 self.global_settings, *largefiles, value='',
566 active=data[largefiles_key])
567 active=data[largefiles_key])
567 self._create_or_update_ui(
568 self._create_or_update_ui(
568 self.global_settings, *largefiles_store,
569 self.global_settings, *largefiles_store,
569 value=data[largefiles_store_key])
570 value=data[largefiles_store_key])
570 self._create_or_update_ui(
571 self._create_or_update_ui(
571 self.global_settings, *phases, value=safe_str(data[phases_key]))
572 self.global_settings, *phases, value=safe_str(data[phases_key]))
572 self._create_or_update_ui(
573 self._create_or_update_ui(
573 self.global_settings, *hgsubversion, active=data[subversion_key])
574 self.global_settings, *hgsubversion, active=data[subversion_key])
574
575
575 def create_or_update_repo_git_settings(self, data):
576 def create_or_update_repo_git_settings(self, data):
576 # NOTE(marcink): # comma make unpack work properly
577 # NOTE(marcink): # comma make unpack work properly
577 lfs_enabled, \
578 lfs_enabled, \
578 = self.GIT_SETTINGS
579 = self.GIT_SETTINGS
579
580
580 lfs_enabled_key, \
581 lfs_enabled_key, \
581 = self._get_settings_keys(self.GIT_SETTINGS, data)
582 = self._get_settings_keys(self.GIT_SETTINGS, data)
582
583
583 self._create_or_update_ui(
584 self._create_or_update_ui(
584 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
585 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
585 active=data[lfs_enabled_key])
586 active=data[lfs_enabled_key])
586
587
587 def create_or_update_global_git_settings(self, data):
588 def create_or_update_global_git_settings(self, data):
588 lfs_enabled, lfs_store_location \
589 lfs_enabled, lfs_store_location \
589 = self.GLOBAL_GIT_SETTINGS
590 = self.GLOBAL_GIT_SETTINGS
590 lfs_enabled_key, lfs_store_location_key \
591 lfs_enabled_key, lfs_store_location_key \
591 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
592 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
592
593
593 self._create_or_update_ui(
594 self._create_or_update_ui(
594 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
595 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
595 active=data[lfs_enabled_key])
596 active=data[lfs_enabled_key])
596 self._create_or_update_ui(
597 self._create_or_update_ui(
597 self.global_settings, *lfs_store_location,
598 self.global_settings, *lfs_store_location,
598 value=data[lfs_store_location_key])
599 value=data[lfs_store_location_key])
599
600
600 def create_or_update_global_svn_settings(self, data):
601 def create_or_update_global_svn_settings(self, data):
601 # branch/tags patterns
602 # branch/tags patterns
602 self._create_svn_settings(self.global_settings, data)
603 self._create_svn_settings(self.global_settings, data)
603
604
604 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
605 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
605 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
606 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
606 self.GLOBAL_SVN_SETTINGS, data)
607 self.GLOBAL_SVN_SETTINGS, data)
607
608
608 self._create_or_update_ui(
609 self._create_or_update_ui(
609 self.global_settings, *http_requests_enabled,
610 self.global_settings, *http_requests_enabled,
610 value=safe_str(data[http_requests_enabled_key]))
611 value=safe_str(data[http_requests_enabled_key]))
611 self._create_or_update_ui(
612 self._create_or_update_ui(
612 self.global_settings, *http_server_url,
613 self.global_settings, *http_server_url,
613 value=data[http_server_url_key])
614 value=data[http_server_url_key])
614
615
615 def update_global_ssl_setting(self, value):
616 def update_global_ssl_setting(self, value):
616 self._create_or_update_ui(
617 self._create_or_update_ui(
617 self.global_settings, *self.SSL_SETTING, value=value)
618 self.global_settings, *self.SSL_SETTING, value=value)
618
619
619 def update_global_path_setting(self, value):
620 def update_global_path_setting(self, value):
620 self._create_or_update_ui(
621 self._create_or_update_ui(
621 self.global_settings, *self.PATH_SETTING, value=value)
622 self.global_settings, *self.PATH_SETTING, value=value)
622
623
623 @assert_repo_settings
624 @assert_repo_settings
624 def delete_repo_svn_pattern(self, id_):
625 def delete_repo_svn_pattern(self, id_):
625 self.repo_settings.delete_ui(id_)
626 self.repo_settings.delete_ui(id_)
626
627
627 def delete_global_svn_pattern(self, id_):
628 def delete_global_svn_pattern(self, id_):
628 self.global_settings.delete_ui(id_)
629 self.global_settings.delete_ui(id_)
629
630
630 @assert_repo_settings
631 @assert_repo_settings
631 def get_repo_ui_settings(self, section=None, key=None):
632 def get_repo_ui_settings(self, section=None, key=None):
632 global_uis = self.global_settings.get_ui(section, key)
633 global_uis = self.global_settings.get_ui(section, key)
633 repo_uis = self.repo_settings.get_ui(section, key)
634 repo_uis = self.repo_settings.get_ui(section, key)
634 filtered_repo_uis = self._filter_ui_settings(repo_uis)
635 filtered_repo_uis = self._filter_ui_settings(repo_uis)
635 filtered_repo_uis_keys = [
636 filtered_repo_uis_keys = [
636 (s.section, s.key) for s in filtered_repo_uis]
637 (s.section, s.key) for s in filtered_repo_uis]
637
638
638 def _is_global_ui_filtered(ui):
639 def _is_global_ui_filtered(ui):
639 return (
640 return (
640 (ui.section, ui.key) in filtered_repo_uis_keys
641 (ui.section, ui.key) in filtered_repo_uis_keys
641 or ui.section in self._svn_sections)
642 or ui.section in self._svn_sections)
642
643
643 filtered_global_uis = [
644 filtered_global_uis = [
644 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
645 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
645
646
646 return filtered_global_uis + filtered_repo_uis
647 return filtered_global_uis + filtered_repo_uis
647
648
648 def get_global_ui_settings(self, section=None, key=None):
649 def get_global_ui_settings(self, section=None, key=None):
649 return self.global_settings.get_ui(section, key)
650 return self.global_settings.get_ui(section, key)
650
651
651 def get_ui_settings_as_config_obj(self, section=None, key=None):
652 def get_ui_settings_as_config_obj(self, section=None, key=None):
652 config = base.Config()
653 config = base.Config()
653
654
654 ui_settings = self.get_ui_settings(section=section, key=key)
655 ui_settings = self.get_ui_settings(section=section, key=key)
655
656
656 for entry in ui_settings:
657 for entry in ui_settings:
657 config.set(entry.section, entry.key, entry.value)
658 config.set(entry.section, entry.key, entry.value)
658
659
659 return config
660 return config
660
661
661 def get_ui_settings(self, section=None, key=None):
662 def get_ui_settings(self, section=None, key=None):
662 if not self.repo_settings or self.inherit_global_settings:
663 if not self.repo_settings or self.inherit_global_settings:
663 return self.get_global_ui_settings(section, key)
664 return self.get_global_ui_settings(section, key)
664 else:
665 else:
665 return self.get_repo_ui_settings(section, key)
666 return self.get_repo_ui_settings(section, key)
666
667
667 def get_svn_patterns(self, section=None):
668 def get_svn_patterns(self, section=None):
668 if not self.repo_settings:
669 if not self.repo_settings:
669 return self.get_global_ui_settings(section)
670 return self.get_global_ui_settings(section)
670 else:
671 else:
671 return self.get_repo_ui_settings(section)
672 return self.get_repo_ui_settings(section)
672
673
673 @assert_repo_settings
674 @assert_repo_settings
674 def get_repo_general_settings(self):
675 def get_repo_general_settings(self):
675 global_settings = self.global_settings.get_all_settings()
676 global_settings = self.global_settings.get_all_settings()
676 repo_settings = self.repo_settings.get_all_settings()
677 repo_settings = self.repo_settings.get_all_settings()
677 filtered_repo_settings = self._filter_general_settings(repo_settings)
678 filtered_repo_settings = self._filter_general_settings(repo_settings)
678 global_settings.update(filtered_repo_settings)
679 global_settings.update(filtered_repo_settings)
679 return global_settings
680 return global_settings
680
681
681 def get_global_general_settings(self):
682 def get_global_general_settings(self):
682 return self.global_settings.get_all_settings()
683 return self.global_settings.get_all_settings()
683
684
684 def get_general_settings(self):
685 def get_general_settings(self):
685 if not self.repo_settings or self.inherit_global_settings:
686 if not self.repo_settings or self.inherit_global_settings:
686 return self.get_global_general_settings()
687 return self.get_global_general_settings()
687 else:
688 else:
688 return self.get_repo_general_settings()
689 return self.get_repo_general_settings()
689
690
690 def get_repos_location(self):
691 def get_repos_location(self):
691 return self.global_settings.get_ui_by_key('/').ui_value
692 return self.global_settings.get_ui_by_key('/').ui_value
692
693
693 def _filter_ui_settings(self, settings):
694 def _filter_ui_settings(self, settings):
694 filtered_settings = [
695 filtered_settings = [
695 s for s in settings if self._should_keep_setting(s)]
696 s for s in settings if self._should_keep_setting(s)]
696 return filtered_settings
697 return filtered_settings
697
698
698 def _should_keep_setting(self, setting):
699 def _should_keep_setting(self, setting):
699 keep = (
700 keep = (
700 (setting.section, setting.key) in self._ui_settings or
701 (setting.section, setting.key) in self._ui_settings or
701 setting.section in self._svn_sections)
702 setting.section in self._svn_sections)
702 return keep
703 return keep
703
704
704 def _filter_general_settings(self, settings):
705 def _filter_general_settings(self, settings):
705 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
706 keys = ['rhodecode_{}'.format(key) for key in self.GENERAL_SETTINGS]
706 return {
707 return {
707 k: settings[k]
708 k: settings[k]
708 for k in settings if k in keys}
709 for k in settings if k in keys}
709
710
710 def _collect_all_settings(self, global_=False):
711 def _collect_all_settings(self, global_=False):
711 settings = self.global_settings if global_ else self.repo_settings
712 settings = self.global_settings if global_ else self.repo_settings
712 result = {}
713 result = {}
713
714
714 for section, key in self._ui_settings:
715 for section, key in self._ui_settings:
715 ui = settings.get_ui_by_section_and_key(section, key)
716 ui = settings.get_ui_by_section_and_key(section, key)
716 result_key = self._get_form_ui_key(section, key)
717 result_key = self._get_form_ui_key(section, key)
717
718
718 if ui:
719 if ui:
719 if section in ('hooks', 'extensions'):
720 if section in ('hooks', 'extensions'):
720 result[result_key] = ui.ui_active
721 result[result_key] = ui.ui_active
721 elif result_key in ['vcs_git_lfs_enabled']:
722 elif result_key in ['vcs_git_lfs_enabled']:
722 result[result_key] = ui.ui_active
723 result[result_key] = ui.ui_active
723 else:
724 else:
724 result[result_key] = ui.ui_value
725 result[result_key] = ui.ui_value
725
726
726 for name in self.GENERAL_SETTINGS:
727 for name in self.GENERAL_SETTINGS:
727 setting = settings.get_setting_by_name(name)
728 setting = settings.get_setting_by_name(name)
728 if setting:
729 if setting:
729 result_key = 'rhodecode_{}'.format(name)
730 result_key = 'rhodecode_{}'.format(name)
730 result[result_key] = setting.app_settings_value
731 result[result_key] = setting.app_settings_value
731
732
732 return result
733 return result
733
734
734 def _get_form_ui_key(self, section, key):
735 def _get_form_ui_key(self, section, key):
735 return '{section}_{key}'.format(
736 return '{section}_{key}'.format(
736 section=section, key=key.replace('.', '_'))
737 section=section, key=key.replace('.', '_'))
737
738
738 def _create_or_update_ui(
739 def _create_or_update_ui(
739 self, settings, section, key, value=None, active=None):
740 self, settings, section, key, value=None, active=None):
740 ui = settings.get_ui_by_section_and_key(section, key)
741 ui = settings.get_ui_by_section_and_key(section, key)
741 if not ui:
742 if not ui:
742 active = True if active is None else active
743 active = True if active is None else active
743 settings.create_ui_section_value(
744 settings.create_ui_section_value(
744 section, value, key=key, active=active)
745 section, value, key=key, active=active)
745 else:
746 else:
746 if active is not None:
747 if active is not None:
747 ui.ui_active = active
748 ui.ui_active = active
748 if value is not None:
749 if value is not None:
749 ui.ui_value = value
750 ui.ui_value = value
750 Session().add(ui)
751 Session().add(ui)
751
752
752 def _create_svn_settings(self, settings, data):
753 def _create_svn_settings(self, settings, data):
753 svn_settings = {
754 svn_settings = {
754 'new_svn_branch': self.SVN_BRANCH_SECTION,
755 'new_svn_branch': self.SVN_BRANCH_SECTION,
755 'new_svn_tag': self.SVN_TAG_SECTION
756 'new_svn_tag': self.SVN_TAG_SECTION
756 }
757 }
757 for key in svn_settings:
758 for key in svn_settings:
758 if data.get(key):
759 if data.get(key):
759 settings.create_ui_section_value(svn_settings[key], data[key])
760 settings.create_ui_section_value(svn_settings[key], data[key])
760
761
761 def _create_or_update_general_settings(self, settings, data):
762 def _create_or_update_general_settings(self, settings, data):
762 for name in self.GENERAL_SETTINGS:
763 for name in self.GENERAL_SETTINGS:
763 data_key = 'rhodecode_{}'.format(name)
764 data_key = 'rhodecode_{}'.format(name)
764 if data_key not in data:
765 if data_key not in data:
765 raise ValueError(
766 raise ValueError(
766 'The given data does not contain {} key'.format(data_key))
767 'The given data does not contain {} key'.format(data_key))
767 setting = settings.create_or_update_setting(
768 setting = settings.create_or_update_setting(
768 name, data[data_key], 'bool')
769 name, data[data_key], 'bool')
769 Session().add(setting)
770 Session().add(setting)
770
771
771 def _get_settings_keys(self, settings, data):
772 def _get_settings_keys(self, settings, data):
772 data_keys = [self._get_form_ui_key(*s) for s in settings]
773 data_keys = [self._get_form_ui_key(*s) for s in settings]
773 for data_key in data_keys:
774 for data_key in data_keys:
774 if data_key not in data:
775 if data_key not in data:
775 raise ValueError(
776 raise ValueError(
776 'The given data does not contain {} key'.format(data_key))
777 'The given data does not contain {} key'.format(data_key))
777 return data_keys
778 return data_keys
779
780 def create_largeobjects_dirs_if_needed(self, repo_store_path):
781 """
782 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
783 does a repository scan if enabled in the settings.
784 """
785
786 from rhodecode.lib.vcs.backends.hg import largefiles_store
787 from rhodecode.lib.vcs.backends.git import lfs_store
788
789 paths = [
790 largefiles_store(repo_store_path),
791 lfs_store(repo_store_path)]
792
793 for path in paths:
794 if os.path.isdir(path):
795 continue
796 if os.path.isfile(path):
797 continue
798 # not a file nor dir, we try to create it
799 try:
800 os.makedirs(path)
801 except Exception:
802 log.warning('Failed to create largefiles dir:%s', path)
General Comments 0
You need to be logged in to leave comments. Login now