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