##// END OF EJS Templates
settings: fixes for 5.0.0 release new license key storage
super-admin -
r5144:02a0c91d default
parent child Browse files
Show More
@@ -1,923 +1,927 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import os
19 import os
20 import re
20 import re
21 import logging
21 import logging
22 import time
22 import time
23 import functools
23 import functools
24 from collections import namedtuple
24 from collections import namedtuple
25
25
26 from pyramid.threadlocal import get_current_request
26 from pyramid.threadlocal import get_current_request
27
27
28 from rhodecode.lib import rc_cache
28 from rhodecode.lib import rc_cache
29 from rhodecode.lib.hash_utils import sha1_safe
29 from rhodecode.lib.hash_utils import sha1_safe
30 from rhodecode.lib.html_filters import sanitize_html
30 from rhodecode.lib.html_filters import sanitize_html
31 from rhodecode.lib.utils2 import (
31 from rhodecode.lib.utils2 import (
32 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
32 Optional, AttributeDict, safe_str, remove_prefix, str2bool)
33 from rhodecode.lib.vcs.backends import base
33 from rhodecode.lib.vcs.backends import base
34 from rhodecode.lib.statsd_client import StatsdClient
34 from rhodecode.lib.statsd_client import StatsdClient
35 from rhodecode.model import BaseModel
35 from rhodecode.model import BaseModel
36 from rhodecode.model.db import (
36 from rhodecode.model.db import (
37 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
37 RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi, RhodeCodeSetting)
38 from rhodecode.model.meta import Session
38 from rhodecode.model.meta import Session
39
39
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43
43
44 UiSetting = namedtuple(
44 UiSetting = namedtuple(
45 'UiSetting', ['section', 'key', 'value', 'active'])
45 'UiSetting', ['section', 'key', 'value', 'active'])
46
46
47 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
47 SOCIAL_PLUGINS_LIST = ['github', 'bitbucket', 'twitter', 'google']
48
48
49
49
50 class SettingNotFound(Exception):
50 class SettingNotFound(Exception):
51 def __init__(self, setting_id):
51 def __init__(self, setting_id):
52 msg = f'Setting `{setting_id}` is not found'
52 msg = f'Setting `{setting_id}` is not found'
53 super().__init__(msg)
53 super().__init__(msg)
54
54
55
55
56 class SettingsModel(BaseModel):
56 class SettingsModel(BaseModel):
57 BUILTIN_HOOKS = (
57 BUILTIN_HOOKS = (
58 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
58 RhodeCodeUi.HOOK_REPO_SIZE, RhodeCodeUi.HOOK_PUSH,
59 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
59 RhodeCodeUi.HOOK_PRE_PUSH, RhodeCodeUi.HOOK_PRETX_PUSH,
60 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
60 RhodeCodeUi.HOOK_PULL, RhodeCodeUi.HOOK_PRE_PULL,
61 RhodeCodeUi.HOOK_PUSH_KEY,)
61 RhodeCodeUi.HOOK_PUSH_KEY,)
62 HOOKS_SECTION = 'hooks'
62 HOOKS_SECTION = 'hooks'
63
63
64 def __init__(self, sa=None, repo=None):
64 def __init__(self, sa=None, repo=None):
65 self.repo = repo
65 self.repo = repo
66 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
66 self.UiDbModel = RepoRhodeCodeUi if repo else RhodeCodeUi
67 self.SettingsDbModel = (
67 self.SettingsDbModel = (
68 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
68 RepoRhodeCodeSetting if repo else RhodeCodeSetting)
69 super().__init__(sa)
69 super().__init__(sa)
70
70
71 def get_keyname(self, key_name, prefix='rhodecode_'):
72 return f'{prefix}{key_name}'
73
71 def get_ui_by_key(self, key):
74 def get_ui_by_key(self, key):
72 q = self.UiDbModel.query()
75 q = self.UiDbModel.query()
73 q = q.filter(self.UiDbModel.ui_key == key)
76 q = q.filter(self.UiDbModel.ui_key == key)
74 q = self._filter_by_repo(RepoRhodeCodeUi, q)
77 q = self._filter_by_repo(RepoRhodeCodeUi, q)
75 return q.scalar()
78 return q.scalar()
76
79
77 def get_ui_by_section(self, section):
80 def get_ui_by_section(self, section):
78 q = self.UiDbModel.query()
81 q = self.UiDbModel.query()
79 q = q.filter(self.UiDbModel.ui_section == section)
82 q = q.filter(self.UiDbModel.ui_section == section)
80 q = self._filter_by_repo(RepoRhodeCodeUi, q)
83 q = self._filter_by_repo(RepoRhodeCodeUi, q)
81 return q.all()
84 return q.all()
82
85
83 def get_ui_by_section_and_key(self, section, key):
86 def get_ui_by_section_and_key(self, section, key):
84 q = self.UiDbModel.query()
87 q = self.UiDbModel.query()
85 q = q.filter(self.UiDbModel.ui_section == section)
88 q = q.filter(self.UiDbModel.ui_section == section)
86 q = q.filter(self.UiDbModel.ui_key == key)
89 q = q.filter(self.UiDbModel.ui_key == key)
87 q = self._filter_by_repo(RepoRhodeCodeUi, q)
90 q = self._filter_by_repo(RepoRhodeCodeUi, q)
88 return q.scalar()
91 return q.scalar()
89
92
90 def get_ui(self, section=None, key=None):
93 def get_ui(self, section=None, key=None):
91 q = self.UiDbModel.query()
94 q = self.UiDbModel.query()
92 q = self._filter_by_repo(RepoRhodeCodeUi, q)
95 q = self._filter_by_repo(RepoRhodeCodeUi, q)
93
96
94 if section:
97 if section:
95 q = q.filter(self.UiDbModel.ui_section == section)
98 q = q.filter(self.UiDbModel.ui_section == section)
96 if key:
99 if key:
97 q = q.filter(self.UiDbModel.ui_key == key)
100 q = q.filter(self.UiDbModel.ui_key == key)
98
101
99 # TODO: mikhail: add caching
102 # TODO: mikhail: add caching
100 result = [
103 result = [
101 UiSetting(
104 UiSetting(
102 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
105 section=safe_str(r.ui_section), key=safe_str(r.ui_key),
103 value=safe_str(r.ui_value), active=r.ui_active
106 value=safe_str(r.ui_value), active=r.ui_active
104 )
107 )
105 for r in q.all()
108 for r in q.all()
106 ]
109 ]
107 return result
110 return result
108
111
109 def get_builtin_hooks(self):
112 def get_builtin_hooks(self):
110 q = self.UiDbModel.query()
113 q = self.UiDbModel.query()
111 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
114 q = q.filter(self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
112 return self._get_hooks(q)
115 return self._get_hooks(q)
113
116
114 def get_custom_hooks(self):
117 def get_custom_hooks(self):
115 q = self.UiDbModel.query()
118 q = self.UiDbModel.query()
116 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
119 q = q.filter(~self.UiDbModel.ui_key.in_(self.BUILTIN_HOOKS))
117 return self._get_hooks(q)
120 return self._get_hooks(q)
118
121
119 def create_ui_section_value(self, section, val, key=None, active=True):
122 def create_ui_section_value(self, section, val, key=None, active=True):
120 new_ui = self.UiDbModel()
123 new_ui = self.UiDbModel()
121 new_ui.ui_section = section
124 new_ui.ui_section = section
122 new_ui.ui_value = val
125 new_ui.ui_value = val
123 new_ui.ui_active = active
126 new_ui.ui_active = active
124
127
125 repository_id = ''
128 repository_id = ''
126 if self.repo:
129 if self.repo:
127 repo = self._get_repo(self.repo)
130 repo = self._get_repo(self.repo)
128 repository_id = repo.repo_id
131 repository_id = repo.repo_id
129 new_ui.repository_id = repository_id
132 new_ui.repository_id = repository_id
130
133
131 if not key:
134 if not key:
132 # keys are unique so they need appended info
135 # keys are unique so they need appended info
133 if self.repo:
136 if self.repo:
134 key = sha1_safe(f'{section}{val}{repository_id}')
137 key = sha1_safe(f'{section}{val}{repository_id}')
135 else:
138 else:
136 key = sha1_safe(f'{section}{val}')
139 key = sha1_safe(f'{section}{val}')
137
140
138 new_ui.ui_key = key
141 new_ui.ui_key = key
139
142
140 Session().add(new_ui)
143 Session().add(new_ui)
141 return new_ui
144 return new_ui
142
145
143 def create_or_update_hook(self, key, value):
146 def create_or_update_hook(self, key, value):
144 ui = (
147 ui = (
145 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
148 self.get_ui_by_section_and_key(self.HOOKS_SECTION, key) or
146 self.UiDbModel())
149 self.UiDbModel())
147 ui.ui_section = self.HOOKS_SECTION
150 ui.ui_section = self.HOOKS_SECTION
148 ui.ui_active = True
151 ui.ui_active = True
149 ui.ui_key = key
152 ui.ui_key = key
150 ui.ui_value = value
153 ui.ui_value = value
151
154
152 if self.repo:
155 if self.repo:
153 repo = self._get_repo(self.repo)
156 repo = self._get_repo(self.repo)
154 repository_id = repo.repo_id
157 repository_id = repo.repo_id
155 ui.repository_id = repository_id
158 ui.repository_id = repository_id
156
159
157 Session().add(ui)
160 Session().add(ui)
158 return ui
161 return ui
159
162
160 def delete_ui(self, id_):
163 def delete_ui(self, id_):
161 ui = self.UiDbModel.get(id_)
164 ui = self.UiDbModel.get(id_)
162 if not ui:
165 if not ui:
163 raise SettingNotFound(id_)
166 raise SettingNotFound(id_)
164 Session().delete(ui)
167 Session().delete(ui)
165
168
166 def get_setting_by_name(self, name):
169 def get_setting_by_name(self, name):
167 q = self._get_settings_query()
170 q = self._get_settings_query()
168 q = q.filter(self.SettingsDbModel.app_settings_name == name)
171 q = q.filter(self.SettingsDbModel.app_settings_name == name)
169 return q.scalar()
172 return q.scalar()
170
173
171 def create_or_update_setting(
174 def create_or_update_setting(
172 self, name, val=Optional(''), type_=Optional('unicode')):
175 self, name, val: Optional | str = Optional(''), type_: Optional | str = Optional('unicode')):
173 """
176 """
174 Creates or updates RhodeCode setting. If updates is triggered it will
177 Creates or updates RhodeCode setting. If updates are triggered, it will
175 only update parameters that are explicitly set Optional instance will
178 only update parameters that are explicitly set Optional instance will
176 be skipped
179 be skipped
177
180
178 :param name:
181 :param name:
179 :param val:
182 :param val:
180 :param type_:
183 :param type_:
181 :return:
184 :return:
182 """
185 """
183
186
184 res = self.get_setting_by_name(name)
187 res = self.get_setting_by_name(name)
185 repo = self._get_repo(self.repo) if self.repo else None
188 repo = self._get_repo(self.repo) if self.repo else None
186
189
187 if not res:
190 if not res:
188 val = Optional.extract(val)
191 val = Optional.extract(val)
189 type_ = Optional.extract(type_)
192 type_ = Optional.extract(type_)
190
193
191 args = (
194 args = (
192 (repo.repo_id, name, val, type_)
195 (repo.repo_id, name, val, type_)
193 if repo else (name, val, type_))
196 if repo else (name, val, type_))
194 res = self.SettingsDbModel(*args)
197 res = self.SettingsDbModel(*args)
195
198
196 else:
199 else:
197 if self.repo:
200 if self.repo:
198 res.repository_id = repo.repo_id
201 res.repository_id = repo.repo_id
199
202
200 res.app_settings_name = name
203 res.app_settings_name = name
201 if not isinstance(type_, Optional):
204 if not isinstance(type_, Optional):
202 # update if set
205 # update if set
203 res.app_settings_type = type_
206 res.app_settings_type = type_
204 if not isinstance(val, Optional):
207 if not isinstance(val, Optional):
205 # update if set
208 # update if set
206 res.app_settings_value = val
209 res.app_settings_value = val
207
210
208 Session().add(res)
211 Session().add(res)
209 return res
212 return res
210
213
211 def get_cache_region(self):
214 def get_cache_region(self):
212 repo = self._get_repo(self.repo) if self.repo else None
215 repo = self._get_repo(self.repo) if self.repo else None
213 cache_key = f"repo.v1.{repo.repo_id}" if repo else "repo.v1.ALL"
216 cache_key = f"repo.v1.{repo.repo_id}" if repo else "repo.v1.ALL"
214 cache_namespace_uid = f'cache_settings.{cache_key}'
217 cache_namespace_uid = f'cache_settings.{cache_key}'
215 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
218 region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
216 return region, cache_namespace_uid
219 return region, cache_namespace_uid
217
220
218 def invalidate_settings_cache(self, hard=False):
221 def invalidate_settings_cache(self, hard=False):
219 region, namespace_key = self.get_cache_region()
222 region, namespace_key = self.get_cache_region()
220 log.debug('Invalidation cache [%s] region %s for cache_key: %s',
223 log.debug('Invalidation cache [%s] region %s for cache_key: %s',
221 'invalidate_settings_cache', region, namespace_key)
224 'invalidate_settings_cache', region, namespace_key)
222
225
223 # we use hard cleanup if invalidation is sent
226 # we use hard cleanup if invalidation is sent
224 rc_cache.clear_cache_namespace(region, namespace_key, method=rc_cache.CLEAR_DELETE)
227 rc_cache.clear_cache_namespace(region, namespace_key, method=rc_cache.CLEAR_DELETE)
225
228
226 def get_cache_call_method(self, cache=True):
229 def get_cache_call_method(self, cache=True):
227 region, cache_key = self.get_cache_region()
230 region, cache_key = self.get_cache_region()
228
231
229 @region.conditional_cache_on_arguments(condition=cache)
232 @region.conditional_cache_on_arguments(condition=cache)
230 def _get_all_settings(name, key):
233 def _get_all_settings(name, key):
231 q = self._get_settings_query()
234 q = self._get_settings_query()
232 if not q:
235 if not q:
233 raise Exception('Could not get application settings !')
236 raise Exception('Could not get application settings !')
234
237
235 settings = {
238 settings = {
236 f'rhodecode_{res.app_settings_name}': res.app_settings_value
239 self.get_keyname(res.app_settings_name): res.app_settings_value
237 for res in q
240 for res in q
238 }
241 }
239 return settings
242 return settings
240 return _get_all_settings
243 return _get_all_settings
241
244
242 def get_all_settings(self, cache=False, from_request=True):
245 def get_all_settings(self, cache=False, from_request=True):
243 # defines if we use GLOBAL, or PER_REPO
246 # defines if we use GLOBAL, or PER_REPO
244 repo = self._get_repo(self.repo) if self.repo else None
247 repo = self._get_repo(self.repo) if self.repo else None
245
248
246 # initially try the requests context, this is the fastest
249 # initially try the request context; this is the fastest
247 # we only fetch global config, NOT for repo-specific
250 # we only fetch global config, NOT for repo-specific
248 if from_request and not repo:
251 if from_request and not repo:
249 request = get_current_request()
252 request = get_current_request()
250
253
251 if request and hasattr(request, 'call_context') and hasattr(request.call_context, 'rc_config'):
254 if request and hasattr(request, 'call_context') and hasattr(request.call_context, 'rc_config'):
252 rc_config = request.call_context.rc_config
255 rc_config = request.call_context.rc_config
253 if rc_config:
256 if rc_config:
254 return rc_config
257 return rc_config
255
258
256 _region, cache_key = self.get_cache_region()
259 _region, cache_key = self.get_cache_region()
257 _get_all_settings = self.get_cache_call_method(cache=cache)
260 _get_all_settings = self.get_cache_call_method(cache=cache)
258
261
259 start = time.time()
262 start = time.time()
260 result = _get_all_settings('rhodecode_settings', cache_key)
263 result = _get_all_settings('rhodecode_settings', cache_key)
261 compute_time = time.time() - start
264 compute_time = time.time() - start
262 log.debug('cached method:%s took %.4fs', _get_all_settings.__name__, compute_time)
265 log.debug('cached method:%s took %.4fs', _get_all_settings.__name__, compute_time)
263
266
264 statsd = StatsdClient.statsd
267 statsd = StatsdClient.statsd
265 if statsd:
268 if statsd:
266 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
269 elapsed_time_ms = round(1000.0 * compute_time) # use ms only
267 statsd.timing("rhodecode_settings_timing.histogram", elapsed_time_ms,
270 statsd.timing("rhodecode_settings_timing.histogram", elapsed_time_ms,
268 use_decimals=False)
271 use_decimals=False)
269
272
270 log.debug('Fetching app settings for key: %s took: %.4fs: cache: %s', cache_key, compute_time, cache)
273 log.debug('Fetching app settings for key: %s took: %.4fs: cache: %s', cache_key, compute_time, cache)
271
274
272 return result
275 return result
273
276
274 def get_auth_settings(self):
277 def get_auth_settings(self):
275 q = self._get_settings_query()
278 q = self._get_settings_query()
276 q = q.filter(
279 q = q.filter(
277 self.SettingsDbModel.app_settings_name.startswith('auth_'))
280 self.SettingsDbModel.app_settings_name.startswith('auth_'))
278 rows = q.all()
281 rows = q.all()
279 auth_settings = {
282 auth_settings = {
280 row.app_settings_name: row.app_settings_value for row in rows}
283 row.app_settings_name: row.app_settings_value for row in rows}
281 return auth_settings
284 return auth_settings
282
285
283 def get_auth_plugins(self):
286 def get_auth_plugins(self):
284 auth_plugins = self.get_setting_by_name("auth_plugins")
287 auth_plugins = self.get_setting_by_name("auth_plugins")
285 return auth_plugins.app_settings_value
288 return auth_plugins.app_settings_value
286
289
287 def get_default_repo_settings(self, strip_prefix=False):
290 def get_default_repo_settings(self, strip_prefix=False):
288 q = self._get_settings_query()
291 q = self._get_settings_query()
289 q = q.filter(
292 q = q.filter(
290 self.SettingsDbModel.app_settings_name.startswith('default_'))
293 self.SettingsDbModel.app_settings_name.startswith('default_'))
291 rows = q.all()
294 rows = q.all()
292
295
293 result = {}
296 result = {}
294 for row in rows:
297 for row in rows:
295 key = row.app_settings_name
298 key = row.app_settings_name
296 if strip_prefix:
299 if strip_prefix:
297 key = remove_prefix(key, prefix='default_')
300 key = remove_prefix(key, prefix='default_')
298 result.update({key: row.app_settings_value})
301 result.update({key: row.app_settings_value})
299 return result
302 return result
300
303
301 def get_repo(self):
304 def get_repo(self):
302 repo = self._get_repo(self.repo)
305 repo = self._get_repo(self.repo)
303 if not repo:
306 if not repo:
304 raise Exception(
307 raise Exception(
305 'Repository `{}` cannot be found inside the database'.format(
308 f'Repository `{self.repo}` cannot be found inside the database')
306 self.repo))
307 return repo
309 return repo
308
310
309 def _filter_by_repo(self, model, query):
311 def _filter_by_repo(self, model, query):
310 if self.repo:
312 if self.repo:
311 repo = self.get_repo()
313 repo = self.get_repo()
312 query = query.filter(model.repository_id == repo.repo_id)
314 query = query.filter(model.repository_id == repo.repo_id)
313 return query
315 return query
314
316
315 def _get_hooks(self, query):
317 def _get_hooks(self, query):
316 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
318 query = query.filter(self.UiDbModel.ui_section == self.HOOKS_SECTION)
317 query = self._filter_by_repo(RepoRhodeCodeUi, query)
319 query = self._filter_by_repo(RepoRhodeCodeUi, query)
318 return query.all()
320 return query.all()
319
321
320 def _get_settings_query(self):
322 def _get_settings_query(self):
321 q = self.SettingsDbModel.query()
323 q = self.SettingsDbModel.query()
322 return self._filter_by_repo(RepoRhodeCodeSetting, q)
324 return self._filter_by_repo(RepoRhodeCodeSetting, q)
323
325
324 def list_enabled_social_plugins(self, settings):
326 def list_enabled_social_plugins(self, settings):
325 enabled = []
327 enabled = []
326 for plug in SOCIAL_PLUGINS_LIST:
328 for plug in SOCIAL_PLUGINS_LIST:
327 if str2bool(settings.get(f'rhodecode_auth_{plug}_enabled')):
329 if str2bool(settings.get(f'rhodecode_auth_{plug}_enabled')):
328 enabled.append(plug)
330 enabled.append(plug)
329 return enabled
331 return enabled
330
332
331
333
332 def assert_repo_settings(func):
334 def assert_repo_settings(func):
333 @functools.wraps(func)
335 @functools.wraps(func)
334 def _wrapper(self, *args, **kwargs):
336 def _wrapper(self, *args, **kwargs):
335 if not self.repo_settings:
337 if not self.repo_settings:
336 raise Exception('Repository is not specified')
338 raise Exception('Repository is not specified')
337 return func(self, *args, **kwargs)
339 return func(self, *args, **kwargs)
338 return _wrapper
340 return _wrapper
339
341
340
342
341 class IssueTrackerSettingsModel(object):
343 class IssueTrackerSettingsModel(object):
342 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
344 INHERIT_SETTINGS = 'inherit_issue_tracker_settings'
343 SETTINGS_PREFIX = 'issuetracker_'
345 SETTINGS_PREFIX = 'issuetracker_'
344
346
345 def __init__(self, sa=None, repo=None):
347 def __init__(self, sa=None, repo=None):
346 self.global_settings = SettingsModel(sa=sa)
348 self.global_settings = SettingsModel(sa=sa)
347 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
349 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
348
350
349 @property
351 @property
350 def inherit_global_settings(self):
352 def inherit_global_settings(self):
351 if not self.repo_settings:
353 if not self.repo_settings:
352 return True
354 return True
353 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
355 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
354 return setting.app_settings_value if setting else True
356 return setting.app_settings_value if setting else True
355
357
356 @inherit_global_settings.setter
358 @inherit_global_settings.setter
357 def inherit_global_settings(self, value):
359 def inherit_global_settings(self, value):
358 if self.repo_settings:
360 if self.repo_settings:
359 settings = self.repo_settings.create_or_update_setting(
361 settings = self.repo_settings.create_or_update_setting(
360 self.INHERIT_SETTINGS, value, type_='bool')
362 self.INHERIT_SETTINGS, value, type_='bool')
361 Session().add(settings)
363 Session().add(settings)
362
364
363 def _get_keyname(self, key, uid, prefix=''):
365 def _get_keyname(self, key, uid, prefix='rhodecode_'):
364 return '{}{}{}_{}'.format(
366 return f'{prefix}{self.SETTINGS_PREFIX}{key}_{uid}'
365 prefix, self.SETTINGS_PREFIX, key, uid)
366
367
367 def _make_dict_for_settings(self, qs):
368 def _make_dict_for_settings(self, qs):
368 prefix_match = self._get_keyname('pat', '', 'rhodecode_')
369 prefix_match = self._get_keyname('pat', '',)
369
370
370 issuetracker_entries = {}
371 issuetracker_entries = {}
371 # create keys
372 # create keys
372 for k, v in qs.items():
373 for k, v in qs.items():
373 if k.startswith(prefix_match):
374 if k.startswith(prefix_match):
374 uid = k[len(prefix_match):]
375 uid = k[len(prefix_match):]
375 issuetracker_entries[uid] = None
376 issuetracker_entries[uid] = None
376
377
377 def url_cleaner(input_str):
378 def url_cleaner(input_str):
378 input_str = input_str.replace('"', '').replace("'", '')
379 input_str = input_str.replace('"', '').replace("'", '')
379 input_str = sanitize_html(input_str, strip=True)
380 input_str = sanitize_html(input_str, strip=True)
380 return input_str
381 return input_str
381
382
382 # populate
383 # populate
383 for uid in issuetracker_entries:
384 for uid in issuetracker_entries:
384 url_data = qs.get(self._get_keyname('url', uid, 'rhodecode_'))
385 url_data = qs.get(self._get_keyname('url', uid))
385
386
386 pat = qs.get(self._get_keyname('pat', uid, 'rhodecode_'))
387 pat = qs.get(self._get_keyname('pat', uid))
387 try:
388 try:
388 pat_compiled = re.compile(r'%s' % pat)
389 pat_compiled = re.compile(r'%s' % pat)
389 except re.error:
390 except re.error:
390 pat_compiled = None
391 pat_compiled = None
391
392
392 issuetracker_entries[uid] = AttributeDict({
393 issuetracker_entries[uid] = AttributeDict({
393 'pat': pat,
394 'pat': pat,
394 'pat_compiled': pat_compiled,
395 'pat_compiled': pat_compiled,
395 'url': url_cleaner(
396 'url': url_cleaner(
396 qs.get(self._get_keyname('url', uid, 'rhodecode_')) or ''),
397 qs.get(self._get_keyname('url', uid)) or ''),
397 'pref': sanitize_html(
398 'pref': sanitize_html(
398 qs.get(self._get_keyname('pref', uid, 'rhodecode_')) or ''),
399 qs.get(self._get_keyname('pref', uid)) or ''),
399 'desc': qs.get(
400 'desc': qs.get(
400 self._get_keyname('desc', uid, 'rhodecode_')),
401 self._get_keyname('desc', uid)),
401 })
402 })
402
403
403 return issuetracker_entries
404 return issuetracker_entries
404
405
405 def get_global_settings(self, cache=False):
406 def get_global_settings(self, cache=False):
406 """
407 """
407 Returns list of global issue tracker settings
408 Returns list of global issue tracker settings
408 """
409 """
409 defaults = self.global_settings.get_all_settings(cache=cache)
410 defaults = self.global_settings.get_all_settings(cache=cache)
410 settings = self._make_dict_for_settings(defaults)
411 settings = self._make_dict_for_settings(defaults)
411 return settings
412 return settings
412
413
413 def get_repo_settings(self, cache=False):
414 def get_repo_settings(self, cache=False):
414 """
415 """
415 Returns list of issue tracker settings per repository
416 Returns list of issue tracker settings per repository
416 """
417 """
417 if not self.repo_settings:
418 if not self.repo_settings:
418 raise Exception('Repository is not specified')
419 raise Exception('Repository is not specified')
419 all_settings = self.repo_settings.get_all_settings(cache=cache)
420 all_settings = self.repo_settings.get_all_settings(cache=cache)
420 settings = self._make_dict_for_settings(all_settings)
421 settings = self._make_dict_for_settings(all_settings)
421 return settings
422 return settings
422
423
423 def get_settings(self, cache=False):
424 def get_settings(self, cache=False):
424 if self.inherit_global_settings:
425 if self.inherit_global_settings:
425 return self.get_global_settings(cache=cache)
426 return self.get_global_settings(cache=cache)
426 else:
427 else:
427 return self.get_repo_settings(cache=cache)
428 return self.get_repo_settings(cache=cache)
428
429
429 def delete_entries(self, uid):
430 def delete_entries(self, uid):
430 if self.repo_settings:
431 if self.repo_settings:
431 all_patterns = self.get_repo_settings()
432 all_patterns = self.get_repo_settings()
432 settings_model = self.repo_settings
433 settings_model = self.repo_settings
433 else:
434 else:
434 all_patterns = self.get_global_settings()
435 all_patterns = self.get_global_settings()
435 settings_model = self.global_settings
436 settings_model = self.global_settings
436 entries = all_patterns.get(uid, [])
437 entries = all_patterns.get(uid, [])
437
438
438 for del_key in entries:
439 for del_key in entries:
439 setting_name = self._get_keyname(del_key, uid)
440 setting_name = self._get_keyname(del_key, uid, prefix='')
440 entry = settings_model.get_setting_by_name(setting_name)
441 entry = settings_model.get_setting_by_name(setting_name)
441 if entry:
442 if entry:
442 Session().delete(entry)
443 Session().delete(entry)
443
444
444 Session().commit()
445 Session().commit()
445
446
446 def create_or_update_setting(
447 def create_or_update_setting(
447 self, name, val=Optional(''), type_=Optional('unicode')):
448 self, name, val=Optional(''), type_=Optional('unicode')):
448 if self.repo_settings:
449 if self.repo_settings:
449 setting = self.repo_settings.create_or_update_setting(
450 setting = self.repo_settings.create_or_update_setting(
450 name, val, type_)
451 name, val, type_)
451 else:
452 else:
452 setting = self.global_settings.create_or_update_setting(
453 setting = self.global_settings.create_or_update_setting(
453 name, val, type_)
454 name, val, type_)
454 return setting
455 return setting
455
456
456
457
457 class VcsSettingsModel(object):
458 class VcsSettingsModel(object):
458
459
459 INHERIT_SETTINGS = 'inherit_vcs_settings'
460 INHERIT_SETTINGS = 'inherit_vcs_settings'
460 GENERAL_SETTINGS = (
461 GENERAL_SETTINGS = (
461 'use_outdated_comments',
462 'use_outdated_comments',
462 'pr_merge_enabled',
463 'pr_merge_enabled',
463 'hg_use_rebase_for_merging',
464 'hg_use_rebase_for_merging',
464 'hg_close_branch_before_merging',
465 'hg_close_branch_before_merging',
465 'git_use_rebase_for_merging',
466 'git_use_rebase_for_merging',
466 'git_close_branch_before_merging',
467 'git_close_branch_before_merging',
467 'diff_cache',
468 'diff_cache',
468 )
469 )
469
470
470 HOOKS_SETTINGS = (
471 HOOKS_SETTINGS = (
471 ('hooks', 'changegroup.repo_size'),
472 ('hooks', 'changegroup.repo_size'),
472 ('hooks', 'changegroup.push_logger'),
473 ('hooks', 'changegroup.push_logger'),
473 ('hooks', 'outgoing.pull_logger'),
474 ('hooks', 'outgoing.pull_logger'),
474 )
475 )
475 HG_SETTINGS = (
476 HG_SETTINGS = (
476 ('extensions', 'largefiles'),
477 ('extensions', 'largefiles'),
477 ('phases', 'publish'),
478 ('phases', 'publish'),
478 ('extensions', 'evolve'),
479 ('extensions', 'evolve'),
479 ('extensions', 'topic'),
480 ('extensions', 'topic'),
480 ('experimental', 'evolution'),
481 ('experimental', 'evolution'),
481 ('experimental', 'evolution.exchange'),
482 ('experimental', 'evolution.exchange'),
482 )
483 )
483 GIT_SETTINGS = (
484 GIT_SETTINGS = (
484 ('vcs_git_lfs', 'enabled'),
485 ('vcs_git_lfs', 'enabled'),
485 )
486 )
486 GLOBAL_HG_SETTINGS = (
487 GLOBAL_HG_SETTINGS = (
487 ('extensions', 'largefiles'),
488 ('extensions', 'largefiles'),
488 ('largefiles', 'usercache'),
489 ('largefiles', 'usercache'),
489 ('phases', 'publish'),
490 ('phases', 'publish'),
490 ('extensions', 'hgsubversion'),
491 ('extensions', 'hgsubversion'),
491 ('extensions', 'evolve'),
492 ('extensions', 'evolve'),
492 ('extensions', 'topic'),
493 ('extensions', 'topic'),
493 ('experimental', 'evolution'),
494 ('experimental', 'evolution'),
494 ('experimental', 'evolution.exchange'),
495 ('experimental', 'evolution.exchange'),
495 )
496 )
496
497
497 GLOBAL_GIT_SETTINGS = (
498 GLOBAL_GIT_SETTINGS = (
498 ('vcs_git_lfs', 'enabled'),
499 ('vcs_git_lfs', 'enabled'),
499 ('vcs_git_lfs', 'store_location')
500 ('vcs_git_lfs', 'store_location')
500 )
501 )
501
502
502 GLOBAL_SVN_SETTINGS = (
503 GLOBAL_SVN_SETTINGS = (
503 ('vcs_svn_proxy', 'http_requests_enabled'),
504 ('vcs_svn_proxy', 'http_requests_enabled'),
504 ('vcs_svn_proxy', 'http_server_url')
505 ('vcs_svn_proxy', 'http_server_url')
505 )
506 )
506
507
507 SVN_BRANCH_SECTION = 'vcs_svn_branch'
508 SVN_BRANCH_SECTION = 'vcs_svn_branch'
508 SVN_TAG_SECTION = 'vcs_svn_tag'
509 SVN_TAG_SECTION = 'vcs_svn_tag'
509 SSL_SETTING = ('web', 'push_ssl')
510 SSL_SETTING = ('web', 'push_ssl')
510 PATH_SETTING = ('paths', '/')
511 PATH_SETTING = ('paths', '/')
511
512
512 def __init__(self, sa=None, repo=None):
513 def __init__(self, sa=None, repo=None):
513 self.global_settings = SettingsModel(sa=sa)
514 self.global_settings = SettingsModel(sa=sa)
514 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
515 self.repo_settings = SettingsModel(sa=sa, repo=repo) if repo else None
515 self._ui_settings = (
516 self._ui_settings = (
516 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
517 self.HG_SETTINGS + self.GIT_SETTINGS + self.HOOKS_SETTINGS)
517 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
518 self._svn_sections = (self.SVN_BRANCH_SECTION, self.SVN_TAG_SECTION)
518
519
519 @property
520 @property
520 @assert_repo_settings
521 @assert_repo_settings
521 def inherit_global_settings(self):
522 def inherit_global_settings(self):
522 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
523 setting = self.repo_settings.get_setting_by_name(self.INHERIT_SETTINGS)
523 return setting.app_settings_value if setting else True
524 return setting.app_settings_value if setting else True
524
525
525 @inherit_global_settings.setter
526 @inherit_global_settings.setter
526 @assert_repo_settings
527 @assert_repo_settings
527 def inherit_global_settings(self, value):
528 def inherit_global_settings(self, value):
528 self.repo_settings.create_or_update_setting(
529 self.repo_settings.create_or_update_setting(
529 self.INHERIT_SETTINGS, value, type_='bool')
530 self.INHERIT_SETTINGS, value, type_='bool')
530
531
532 def get_keyname(self, key_name, prefix='rhodecode_'):
533 return f'{prefix}{key_name}'
534
531 def get_global_svn_branch_patterns(self):
535 def get_global_svn_branch_patterns(self):
532 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
536 return self.global_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
533
537
534 @assert_repo_settings
538 @assert_repo_settings
535 def get_repo_svn_branch_patterns(self):
539 def get_repo_svn_branch_patterns(self):
536 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
540 return self.repo_settings.get_ui_by_section(self.SVN_BRANCH_SECTION)
537
541
538 def get_global_svn_tag_patterns(self):
542 def get_global_svn_tag_patterns(self):
539 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
543 return self.global_settings.get_ui_by_section(self.SVN_TAG_SECTION)
540
544
541 @assert_repo_settings
545 @assert_repo_settings
542 def get_repo_svn_tag_patterns(self):
546 def get_repo_svn_tag_patterns(self):
543 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
547 return self.repo_settings.get_ui_by_section(self.SVN_TAG_SECTION)
544
548
545 def get_global_settings(self):
549 def get_global_settings(self):
546 return self._collect_all_settings(global_=True)
550 return self._collect_all_settings(global_=True)
547
551
548 @assert_repo_settings
552 @assert_repo_settings
549 def get_repo_settings(self):
553 def get_repo_settings(self):
550 return self._collect_all_settings(global_=False)
554 return self._collect_all_settings(global_=False)
551
555
552 @assert_repo_settings
556 @assert_repo_settings
553 def get_repo_settings_inherited(self):
557 def get_repo_settings_inherited(self):
554 global_settings = self.get_global_settings()
558 global_settings = self.get_global_settings()
555 global_settings.update(self.get_repo_settings())
559 global_settings.update(self.get_repo_settings())
556 return global_settings
560 return global_settings
557
561
558 @assert_repo_settings
562 @assert_repo_settings
559 def create_or_update_repo_settings(
563 def create_or_update_repo_settings(
560 self, data, inherit_global_settings=False):
564 self, data, inherit_global_settings=False):
561 from rhodecode.model.scm import ScmModel
565 from rhodecode.model.scm import ScmModel
562
566
563 self.inherit_global_settings = inherit_global_settings
567 self.inherit_global_settings = inherit_global_settings
564
568
565 repo = self.repo_settings.get_repo()
569 repo = self.repo_settings.get_repo()
566 if not inherit_global_settings:
570 if not inherit_global_settings:
567 if repo.repo_type == 'svn':
571 if repo.repo_type == 'svn':
568 self.create_repo_svn_settings(data)
572 self.create_repo_svn_settings(data)
569 else:
573 else:
570 self.create_or_update_repo_hook_settings(data)
574 self.create_or_update_repo_hook_settings(data)
571 self.create_or_update_repo_pr_settings(data)
575 self.create_or_update_repo_pr_settings(data)
572
576
573 if repo.repo_type == 'hg':
577 if repo.repo_type == 'hg':
574 self.create_or_update_repo_hg_settings(data)
578 self.create_or_update_repo_hg_settings(data)
575
579
576 if repo.repo_type == 'git':
580 if repo.repo_type == 'git':
577 self.create_or_update_repo_git_settings(data)
581 self.create_or_update_repo_git_settings(data)
578
582
579 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
583 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
580
584
581 @assert_repo_settings
585 @assert_repo_settings
582 def create_or_update_repo_hook_settings(self, data):
586 def create_or_update_repo_hook_settings(self, data):
583 for section, key in self.HOOKS_SETTINGS:
587 for section, key in self.HOOKS_SETTINGS:
584 data_key = self._get_form_ui_key(section, key)
588 data_key = self._get_form_ui_key(section, key)
585 if data_key not in data:
589 if data_key not in data:
586 raise ValueError(
590 raise ValueError(
587 f'The given data does not contain {data_key} key')
591 f'The given data does not contain {data_key} key')
588
592
589 active = data.get(data_key)
593 active = data.get(data_key)
590 repo_setting = self.repo_settings.get_ui_by_section_and_key(
594 repo_setting = self.repo_settings.get_ui_by_section_and_key(
591 section, key)
595 section, key)
592 if not repo_setting:
596 if not repo_setting:
593 global_setting = self.global_settings.\
597 global_setting = self.global_settings.\
594 get_ui_by_section_and_key(section, key)
598 get_ui_by_section_and_key(section, key)
595 self.repo_settings.create_ui_section_value(
599 self.repo_settings.create_ui_section_value(
596 section, global_setting.ui_value, key=key, active=active)
600 section, global_setting.ui_value, key=key, active=active)
597 else:
601 else:
598 repo_setting.ui_active = active
602 repo_setting.ui_active = active
599 Session().add(repo_setting)
603 Session().add(repo_setting)
600
604
601 def update_global_hook_settings(self, data):
605 def update_global_hook_settings(self, data):
602 for section, key in self.HOOKS_SETTINGS:
606 for section, key in self.HOOKS_SETTINGS:
603 data_key = self._get_form_ui_key(section, key)
607 data_key = self._get_form_ui_key(section, key)
604 if data_key not in data:
608 if data_key not in data:
605 raise ValueError(
609 raise ValueError(
606 f'The given data does not contain {data_key} key')
610 f'The given data does not contain {data_key} key')
607 active = data.get(data_key)
611 active = data.get(data_key)
608 repo_setting = self.global_settings.get_ui_by_section_and_key(
612 repo_setting = self.global_settings.get_ui_by_section_and_key(
609 section, key)
613 section, key)
610 repo_setting.ui_active = active
614 repo_setting.ui_active = active
611 Session().add(repo_setting)
615 Session().add(repo_setting)
612
616
613 @assert_repo_settings
617 @assert_repo_settings
614 def create_or_update_repo_pr_settings(self, data):
618 def create_or_update_repo_pr_settings(self, data):
615 return self._create_or_update_general_settings(
619 return self._create_or_update_general_settings(
616 self.repo_settings, data)
620 self.repo_settings, data)
617
621
618 def create_or_update_global_pr_settings(self, data):
622 def create_or_update_global_pr_settings(self, data):
619 return self._create_or_update_general_settings(
623 return self._create_or_update_general_settings(
620 self.global_settings, data)
624 self.global_settings, data)
621
625
622 @assert_repo_settings
626 @assert_repo_settings
623 def create_repo_svn_settings(self, data):
627 def create_repo_svn_settings(self, data):
624 return self._create_svn_settings(self.repo_settings, data)
628 return self._create_svn_settings(self.repo_settings, data)
625
629
626 def _set_evolution(self, settings, is_enabled):
630 def _set_evolution(self, settings, is_enabled):
627 if is_enabled:
631 if is_enabled:
628 # if evolve is active set evolution=all
632 # if evolve is active set evolution=all
629
633
630 self._create_or_update_ui(
634 self._create_or_update_ui(
631 settings, *('experimental', 'evolution'), value='all',
635 settings, *('experimental', 'evolution'), value='all',
632 active=True)
636 active=True)
633 self._create_or_update_ui(
637 self._create_or_update_ui(
634 settings, *('experimental', 'evolution.exchange'), value='yes',
638 settings, *('experimental', 'evolution.exchange'), value='yes',
635 active=True)
639 active=True)
636 # if evolve is active set topics server support
640 # if evolve is active set topics server support
637 self._create_or_update_ui(
641 self._create_or_update_ui(
638 settings, *('extensions', 'topic'), value='',
642 settings, *('extensions', 'topic'), value='',
639 active=True)
643 active=True)
640
644
641 else:
645 else:
642 self._create_or_update_ui(
646 self._create_or_update_ui(
643 settings, *('experimental', 'evolution'), value='',
647 settings, *('experimental', 'evolution'), value='',
644 active=False)
648 active=False)
645 self._create_or_update_ui(
649 self._create_or_update_ui(
646 settings, *('experimental', 'evolution.exchange'), value='no',
650 settings, *('experimental', 'evolution.exchange'), value='no',
647 active=False)
651 active=False)
648 self._create_or_update_ui(
652 self._create_or_update_ui(
649 settings, *('extensions', 'topic'), value='',
653 settings, *('extensions', 'topic'), value='',
650 active=False)
654 active=False)
651
655
652 @assert_repo_settings
656 @assert_repo_settings
653 def create_or_update_repo_hg_settings(self, data):
657 def create_or_update_repo_hg_settings(self, data):
654 largefiles, phases, evolve = \
658 largefiles, phases, evolve = \
655 self.HG_SETTINGS[:3]
659 self.HG_SETTINGS[:3]
656 largefiles_key, phases_key, evolve_key = \
660 largefiles_key, phases_key, evolve_key = \
657 self._get_settings_keys(self.HG_SETTINGS[:3], data)
661 self._get_settings_keys(self.HG_SETTINGS[:3], data)
658
662
659 self._create_or_update_ui(
663 self._create_or_update_ui(
660 self.repo_settings, *largefiles, value='',
664 self.repo_settings, *largefiles, value='',
661 active=data[largefiles_key])
665 active=data[largefiles_key])
662 self._create_or_update_ui(
666 self._create_or_update_ui(
663 self.repo_settings, *evolve, value='',
667 self.repo_settings, *evolve, value='',
664 active=data[evolve_key])
668 active=data[evolve_key])
665 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
669 self._set_evolution(self.repo_settings, is_enabled=data[evolve_key])
666
670
667 self._create_or_update_ui(
671 self._create_or_update_ui(
668 self.repo_settings, *phases, value=safe_str(data[phases_key]))
672 self.repo_settings, *phases, value=safe_str(data[phases_key]))
669
673
670 def create_or_update_global_hg_settings(self, data):
674 def create_or_update_global_hg_settings(self, data):
671 largefiles, largefiles_store, phases, hgsubversion, evolve \
675 largefiles, largefiles_store, phases, hgsubversion, evolve \
672 = self.GLOBAL_HG_SETTINGS[:5]
676 = self.GLOBAL_HG_SETTINGS[:5]
673 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
677 largefiles_key, largefiles_store_key, phases_key, subversion_key, evolve_key \
674 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
678 = self._get_settings_keys(self.GLOBAL_HG_SETTINGS[:5], data)
675
679
676 self._create_or_update_ui(
680 self._create_or_update_ui(
677 self.global_settings, *largefiles, value='',
681 self.global_settings, *largefiles, value='',
678 active=data[largefiles_key])
682 active=data[largefiles_key])
679 self._create_or_update_ui(
683 self._create_or_update_ui(
680 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
684 self.global_settings, *largefiles_store, value=data[largefiles_store_key])
681 self._create_or_update_ui(
685 self._create_or_update_ui(
682 self.global_settings, *phases, value=safe_str(data[phases_key]))
686 self.global_settings, *phases, value=safe_str(data[phases_key]))
683 self._create_or_update_ui(
687 self._create_or_update_ui(
684 self.global_settings, *hgsubversion, active=data[subversion_key])
688 self.global_settings, *hgsubversion, active=data[subversion_key])
685 self._create_or_update_ui(
689 self._create_or_update_ui(
686 self.global_settings, *evolve, value='',
690 self.global_settings, *evolve, value='',
687 active=data[evolve_key])
691 active=data[evolve_key])
688 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
692 self._set_evolution(self.global_settings, is_enabled=data[evolve_key])
689
693
690 def create_or_update_repo_git_settings(self, data):
694 def create_or_update_repo_git_settings(self, data):
691 # NOTE(marcink): # comma makes unpack work properly
695 # NOTE(marcink): # comma makes unpack work properly
692 lfs_enabled, \
696 lfs_enabled, \
693 = self.GIT_SETTINGS
697 = self.GIT_SETTINGS
694
698
695 lfs_enabled_key, \
699 lfs_enabled_key, \
696 = self._get_settings_keys(self.GIT_SETTINGS, data)
700 = self._get_settings_keys(self.GIT_SETTINGS, data)
697
701
698 self._create_or_update_ui(
702 self._create_or_update_ui(
699 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
703 self.repo_settings, *lfs_enabled, value=data[lfs_enabled_key],
700 active=data[lfs_enabled_key])
704 active=data[lfs_enabled_key])
701
705
702 def create_or_update_global_git_settings(self, data):
706 def create_or_update_global_git_settings(self, data):
703 lfs_enabled, lfs_store_location \
707 lfs_enabled, lfs_store_location \
704 = self.GLOBAL_GIT_SETTINGS
708 = self.GLOBAL_GIT_SETTINGS
705 lfs_enabled_key, lfs_store_location_key \
709 lfs_enabled_key, lfs_store_location_key \
706 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
710 = self._get_settings_keys(self.GLOBAL_GIT_SETTINGS, data)
707
711
708 self._create_or_update_ui(
712 self._create_or_update_ui(
709 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
713 self.global_settings, *lfs_enabled, value=data[lfs_enabled_key],
710 active=data[lfs_enabled_key])
714 active=data[lfs_enabled_key])
711 self._create_or_update_ui(
715 self._create_or_update_ui(
712 self.global_settings, *lfs_store_location,
716 self.global_settings, *lfs_store_location,
713 value=data[lfs_store_location_key])
717 value=data[lfs_store_location_key])
714
718
715 def create_or_update_global_svn_settings(self, data):
719 def create_or_update_global_svn_settings(self, data):
716 # branch/tags patterns
720 # branch/tags patterns
717 self._create_svn_settings(self.global_settings, data)
721 self._create_svn_settings(self.global_settings, data)
718
722
719 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
723 http_requests_enabled, http_server_url = self.GLOBAL_SVN_SETTINGS
720 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
724 http_requests_enabled_key, http_server_url_key = self._get_settings_keys(
721 self.GLOBAL_SVN_SETTINGS, data)
725 self.GLOBAL_SVN_SETTINGS, data)
722
726
723 self._create_or_update_ui(
727 self._create_or_update_ui(
724 self.global_settings, *http_requests_enabled,
728 self.global_settings, *http_requests_enabled,
725 value=safe_str(data[http_requests_enabled_key]))
729 value=safe_str(data[http_requests_enabled_key]))
726 self._create_or_update_ui(
730 self._create_or_update_ui(
727 self.global_settings, *http_server_url,
731 self.global_settings, *http_server_url,
728 value=data[http_server_url_key])
732 value=data[http_server_url_key])
729
733
730 def update_global_ssl_setting(self, value):
734 def update_global_ssl_setting(self, value):
731 self._create_or_update_ui(
735 self._create_or_update_ui(
732 self.global_settings, *self.SSL_SETTING, value=value)
736 self.global_settings, *self.SSL_SETTING, value=value)
733
737
734 def update_global_path_setting(self, value):
738 def update_global_path_setting(self, value):
735 self._create_or_update_ui(
739 self._create_or_update_ui(
736 self.global_settings, *self.PATH_SETTING, value=value)
740 self.global_settings, *self.PATH_SETTING, value=value)
737
741
738 @assert_repo_settings
742 @assert_repo_settings
739 def delete_repo_svn_pattern(self, id_):
743 def delete_repo_svn_pattern(self, id_):
740 ui = self.repo_settings.UiDbModel.get(id_)
744 ui = self.repo_settings.UiDbModel.get(id_)
741 if ui and ui.repository.repo_name == self.repo_settings.repo:
745 if ui and ui.repository.repo_name == self.repo_settings.repo:
742 # only delete if it's the same repo as initialized settings
746 # only delete if it's the same repo as initialized settings
743 self.repo_settings.delete_ui(id_)
747 self.repo_settings.delete_ui(id_)
744 else:
748 else:
745 # raise error as if we wouldn't find this option
749 # raise error as if we wouldn't find this option
746 self.repo_settings.delete_ui(-1)
750 self.repo_settings.delete_ui(-1)
747
751
748 def delete_global_svn_pattern(self, id_):
752 def delete_global_svn_pattern(self, id_):
749 self.global_settings.delete_ui(id_)
753 self.global_settings.delete_ui(id_)
750
754
751 @assert_repo_settings
755 @assert_repo_settings
752 def get_repo_ui_settings(self, section=None, key=None):
756 def get_repo_ui_settings(self, section=None, key=None):
753 global_uis = self.global_settings.get_ui(section, key)
757 global_uis = self.global_settings.get_ui(section, key)
754 repo_uis = self.repo_settings.get_ui(section, key)
758 repo_uis = self.repo_settings.get_ui(section, key)
755
759
756 filtered_repo_uis = self._filter_ui_settings(repo_uis)
760 filtered_repo_uis = self._filter_ui_settings(repo_uis)
757 filtered_repo_uis_keys = [
761 filtered_repo_uis_keys = [
758 (s.section, s.key) for s in filtered_repo_uis]
762 (s.section, s.key) for s in filtered_repo_uis]
759
763
760 def _is_global_ui_filtered(ui):
764 def _is_global_ui_filtered(ui):
761 return (
765 return (
762 (ui.section, ui.key) in filtered_repo_uis_keys
766 (ui.section, ui.key) in filtered_repo_uis_keys
763 or ui.section in self._svn_sections)
767 or ui.section in self._svn_sections)
764
768
765 filtered_global_uis = [
769 filtered_global_uis = [
766 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
770 ui for ui in global_uis if not _is_global_ui_filtered(ui)]
767
771
768 return filtered_global_uis + filtered_repo_uis
772 return filtered_global_uis + filtered_repo_uis
769
773
770 def get_global_ui_settings(self, section=None, key=None):
774 def get_global_ui_settings(self, section=None, key=None):
771 return self.global_settings.get_ui(section, key)
775 return self.global_settings.get_ui(section, key)
772
776
773 def get_ui_settings_as_config_obj(self, section=None, key=None):
777 def get_ui_settings_as_config_obj(self, section=None, key=None):
774 config = base.Config()
778 config = base.Config()
775
779
776 ui_settings = self.get_ui_settings(section=section, key=key)
780 ui_settings = self.get_ui_settings(section=section, key=key)
777
781
778 for entry in ui_settings:
782 for entry in ui_settings:
779 config.set(entry.section, entry.key, entry.value)
783 config.set(entry.section, entry.key, entry.value)
780
784
781 return config
785 return config
782
786
783 def get_ui_settings(self, section=None, key=None):
787 def get_ui_settings(self, section=None, key=None):
784 if not self.repo_settings or self.inherit_global_settings:
788 if not self.repo_settings or self.inherit_global_settings:
785 return self.get_global_ui_settings(section, key)
789 return self.get_global_ui_settings(section, key)
786 else:
790 else:
787 return self.get_repo_ui_settings(section, key)
791 return self.get_repo_ui_settings(section, key)
788
792
789 def get_svn_patterns(self, section=None):
793 def get_svn_patterns(self, section=None):
790 if not self.repo_settings:
794 if not self.repo_settings:
791 return self.get_global_ui_settings(section)
795 return self.get_global_ui_settings(section)
792 else:
796 else:
793 return self.get_repo_ui_settings(section)
797 return self.get_repo_ui_settings(section)
794
798
795 @assert_repo_settings
799 @assert_repo_settings
796 def get_repo_general_settings(self):
800 def get_repo_general_settings(self):
797 global_settings = self.global_settings.get_all_settings()
801 global_settings = self.global_settings.get_all_settings()
798 repo_settings = self.repo_settings.get_all_settings()
802 repo_settings = self.repo_settings.get_all_settings()
799 filtered_repo_settings = self._filter_general_settings(repo_settings)
803 filtered_repo_settings = self._filter_general_settings(repo_settings)
800 global_settings.update(filtered_repo_settings)
804 global_settings.update(filtered_repo_settings)
801 return global_settings
805 return global_settings
802
806
803 def get_global_general_settings(self):
807 def get_global_general_settings(self):
804 return self.global_settings.get_all_settings()
808 return self.global_settings.get_all_settings()
805
809
806 def get_general_settings(self):
810 def get_general_settings(self):
807 if not self.repo_settings or self.inherit_global_settings:
811 if not self.repo_settings or self.inherit_global_settings:
808 return self.get_global_general_settings()
812 return self.get_global_general_settings()
809 else:
813 else:
810 return self.get_repo_general_settings()
814 return self.get_repo_general_settings()
811
815
812 def get_repos_location(self):
816 def get_repos_location(self):
813 return self.global_settings.get_ui_by_key('/').ui_value
817 return self.global_settings.get_ui_by_key('/').ui_value
814
818
815 def _filter_ui_settings(self, settings):
819 def _filter_ui_settings(self, settings):
816 filtered_settings = [
820 filtered_settings = [
817 s for s in settings if self._should_keep_setting(s)]
821 s for s in settings if self._should_keep_setting(s)]
818 return filtered_settings
822 return filtered_settings
819
823
820 def _should_keep_setting(self, setting):
824 def _should_keep_setting(self, setting):
821 keep = (
825 keep = (
822 (setting.section, setting.key) in self._ui_settings or
826 (setting.section, setting.key) in self._ui_settings or
823 setting.section in self._svn_sections)
827 setting.section in self._svn_sections)
824 return keep
828 return keep
825
829
826 def _filter_general_settings(self, settings):
830 def _filter_general_settings(self, settings):
827 keys = [f'rhodecode_{key}' for key in self.GENERAL_SETTINGS]
831 keys = [self.get_keyname(key) for key in self.GENERAL_SETTINGS]
828 return {
832 return {
829 k: settings[k]
833 k: settings[k]
830 for k in settings if k in keys}
834 for k in settings if k in keys}
831
835
832 def _collect_all_settings(self, global_=False):
836 def _collect_all_settings(self, global_=False):
833 settings = self.global_settings if global_ else self.repo_settings
837 settings = self.global_settings if global_ else self.repo_settings
834 result = {}
838 result = {}
835
839
836 for section, key in self._ui_settings:
840 for section, key in self._ui_settings:
837 ui = settings.get_ui_by_section_and_key(section, key)
841 ui = settings.get_ui_by_section_and_key(section, key)
838 result_key = self._get_form_ui_key(section, key)
842 result_key = self._get_form_ui_key(section, key)
839
843
840 if ui:
844 if ui:
841 if section in ('hooks', 'extensions'):
845 if section in ('hooks', 'extensions'):
842 result[result_key] = ui.ui_active
846 result[result_key] = ui.ui_active
843 elif result_key in ['vcs_git_lfs_enabled']:
847 elif result_key in ['vcs_git_lfs_enabled']:
844 result[result_key] = ui.ui_active
848 result[result_key] = ui.ui_active
845 else:
849 else:
846 result[result_key] = ui.ui_value
850 result[result_key] = ui.ui_value
847
851
848 for name in self.GENERAL_SETTINGS:
852 for name in self.GENERAL_SETTINGS:
849 setting = settings.get_setting_by_name(name)
853 setting = settings.get_setting_by_name(name)
850 if setting:
854 if setting:
851 result_key = f'rhodecode_{name}'
855 result_key = self.get_keyname(name)
852 result[result_key] = setting.app_settings_value
856 result[result_key] = setting.app_settings_value
853
857
854 return result
858 return result
855
859
856 def _get_form_ui_key(self, section, key):
860 def _get_form_ui_key(self, section, key):
857 return '{section}_{key}'.format(
861 return '{section}_{key}'.format(
858 section=section, key=key.replace('.', '_'))
862 section=section, key=key.replace('.', '_'))
859
863
860 def _create_or_update_ui(
864 def _create_or_update_ui(
861 self, settings, section, key, value=None, active=None):
865 self, settings, section, key, value=None, active=None):
862 ui = settings.get_ui_by_section_and_key(section, key)
866 ui = settings.get_ui_by_section_and_key(section, key)
863 if not ui:
867 if not ui:
864 active = True if active is None else active
868 active = True if active is None else active
865 settings.create_ui_section_value(
869 settings.create_ui_section_value(
866 section, value, key=key, active=active)
870 section, value, key=key, active=active)
867 else:
871 else:
868 if active is not None:
872 if active is not None:
869 ui.ui_active = active
873 ui.ui_active = active
870 if value is not None:
874 if value is not None:
871 ui.ui_value = value
875 ui.ui_value = value
872 Session().add(ui)
876 Session().add(ui)
873
877
874 def _create_svn_settings(self, settings, data):
878 def _create_svn_settings(self, settings, data):
875 svn_settings = {
879 svn_settings = {
876 'new_svn_branch': self.SVN_BRANCH_SECTION,
880 'new_svn_branch': self.SVN_BRANCH_SECTION,
877 'new_svn_tag': self.SVN_TAG_SECTION
881 'new_svn_tag': self.SVN_TAG_SECTION
878 }
882 }
879 for key in svn_settings:
883 for key in svn_settings:
880 if data.get(key):
884 if data.get(key):
881 settings.create_ui_section_value(svn_settings[key], data[key])
885 settings.create_ui_section_value(svn_settings[key], data[key])
882
886
883 def _create_or_update_general_settings(self, settings, data):
887 def _create_or_update_general_settings(self, settings, data):
884 for name in self.GENERAL_SETTINGS:
888 for name in self.GENERAL_SETTINGS:
885 data_key = f'rhodecode_{name}'
889 data_key = self.get_keyname(name)
886 if data_key not in data:
890 if data_key not in data:
887 raise ValueError(
891 raise ValueError(
888 f'The given data does not contain {data_key} key')
892 f'The given data does not contain {data_key} key')
889 setting = settings.create_or_update_setting(
893 setting = settings.create_or_update_setting(
890 name, data[data_key], 'bool')
894 name, data[data_key], 'bool')
891 Session().add(setting)
895 Session().add(setting)
892
896
893 def _get_settings_keys(self, settings, data):
897 def _get_settings_keys(self, settings, data):
894 data_keys = [self._get_form_ui_key(*s) for s in settings]
898 data_keys = [self._get_form_ui_key(*s) for s in settings]
895 for data_key in data_keys:
899 for data_key in data_keys:
896 if data_key not in data:
900 if data_key not in data:
897 raise ValueError(
901 raise ValueError(
898 f'The given data does not contain {data_key} key')
902 f'The given data does not contain {data_key} key')
899 return data_keys
903 return data_keys
900
904
901 def create_largeobjects_dirs_if_needed(self, repo_store_path):
905 def create_largeobjects_dirs_if_needed(self, repo_store_path):
902 """
906 """
903 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
907 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
904 does a repository scan if enabled in the settings.
908 does a repository scan if enabled in the settings.
905 """
909 """
906
910
907 from rhodecode.lib.vcs.backends.hg import largefiles_store
911 from rhodecode.lib.vcs.backends.hg import largefiles_store
908 from rhodecode.lib.vcs.backends.git import lfs_store
912 from rhodecode.lib.vcs.backends.git import lfs_store
909
913
910 paths = [
914 paths = [
911 largefiles_store(repo_store_path),
915 largefiles_store(repo_store_path),
912 lfs_store(repo_store_path)]
916 lfs_store(repo_store_path)]
913
917
914 for path in paths:
918 for path in paths:
915 if os.path.isdir(path):
919 if os.path.isdir(path):
916 continue
920 continue
917 if os.path.isfile(path):
921 if os.path.isfile(path):
918 continue
922 continue
919 # not a file nor dir, we try to create it
923 # not a file nor dir, we try to create it
920 try:
924 try:
921 os.makedirs(path)
925 os.makedirs(path)
922 except Exception:
926 except Exception:
923 log.warning('Failed to create largefiles dir:%s', path)
927 log.warning('Failed to create largefiles dir:%s', path)
General Comments 0
You need to be logged in to leave comments. Login now