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