##// END OF EJS Templates
permissions: flush all when running remap and rescan.
marcink -
r4428:61666194 default
parent child Browse files
Show More
@@ -1,782 +1,784 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2020 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 import logging
23 23 import collections
24 24
25 25 import datetime
26 26 import formencode
27 27 import formencode.htmlfill
28 28
29 29 import rhodecode
30 30 from pyramid.view import view_config
31 31 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
32 32 from pyramid.renderers import render
33 33 from pyramid.response import Response
34 34
35 35 from rhodecode.apps._base import BaseAppView
36 36 from rhodecode.apps._base.navigation import navigation_list
37 37 from rhodecode.apps.svn_support.config_keys import generate_config
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.lib.auth import (
40 40 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
41 41 from rhodecode.lib.celerylib import tasks, run_task
42 42 from rhodecode.lib.utils import repo2db_mapper
43 43 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
44 44 from rhodecode.lib.index import searcher_from_config
45 45
46 46 from rhodecode.model.db import RhodeCodeUi, Repository
47 47 from rhodecode.model.forms import (ApplicationSettingsForm,
48 48 ApplicationUiSettingsForm, ApplicationVisualisationForm,
49 49 LabsSettingsForm, IssueTrackerPatternsForm)
50 from rhodecode.model.permission import PermissionModel
50 51 from rhodecode.model.repo_group import RepoGroupModel
51 52
52 53 from rhodecode.model.scm import ScmModel
53 54 from rhodecode.model.notification import EmailNotificationModel
54 55 from rhodecode.model.meta import Session
55 56 from rhodecode.model.settings import (
56 57 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
57 58 SettingsModel)
58 59
59 60
60 61 log = logging.getLogger(__name__)
61 62
62 63
63 64 class AdminSettingsView(BaseAppView):
64 65
65 66 def load_default_context(self):
66 67 c = self._get_local_tmpl_context()
67 68 c.labs_active = str2bool(
68 69 rhodecode.CONFIG.get('labs_settings_active', 'true'))
69 70 c.navlist = navigation_list(self.request)
70 71
71 72 return c
72 73
73 74 @classmethod
74 75 def _get_ui_settings(cls):
75 76 ret = RhodeCodeUi.query().all()
76 77
77 78 if not ret:
78 79 raise Exception('Could not get application ui settings !')
79 80 settings = {}
80 81 for each in ret:
81 82 k = each.ui_key
82 83 v = each.ui_value
83 84 if k == '/':
84 85 k = 'root_path'
85 86
86 87 if k in ['push_ssl', 'publish', 'enabled']:
87 88 v = str2bool(v)
88 89
89 90 if k.find('.') != -1:
90 91 k = k.replace('.', '_')
91 92
92 93 if each.ui_section in ['hooks', 'extensions']:
93 94 v = each.ui_active
94 95
95 96 settings[each.ui_section + '_' + k] = v
96 97 return settings
97 98
98 99 @classmethod
99 100 def _form_defaults(cls):
100 101 defaults = SettingsModel().get_all_settings()
101 102 defaults.update(cls._get_ui_settings())
102 103
103 104 defaults.update({
104 105 'new_svn_branch': '',
105 106 'new_svn_tag': '',
106 107 })
107 108 return defaults
108 109
109 110 @LoginRequired()
110 111 @HasPermissionAllDecorator('hg.admin')
111 112 @view_config(
112 113 route_name='admin_settings_vcs', request_method='GET',
113 114 renderer='rhodecode:templates/admin/settings/settings.mako')
114 115 def settings_vcs(self):
115 116 c = self.load_default_context()
116 117 c.active = 'vcs'
117 118 model = VcsSettingsModel()
118 119 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
119 120 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
120 121
121 122 settings = self.request.registry.settings
122 123 c.svn_proxy_generate_config = settings[generate_config]
123 124
124 125 defaults = self._form_defaults()
125 126
126 127 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
127 128
128 129 data = render('rhodecode:templates/admin/settings/settings.mako',
129 130 self._get_template_context(c), self.request)
130 131 html = formencode.htmlfill.render(
131 132 data,
132 133 defaults=defaults,
133 134 encoding="UTF-8",
134 135 force_defaults=False
135 136 )
136 137 return Response(html)
137 138
138 139 @LoginRequired()
139 140 @HasPermissionAllDecorator('hg.admin')
140 141 @CSRFRequired()
141 142 @view_config(
142 143 route_name='admin_settings_vcs_update', request_method='POST',
143 144 renderer='rhodecode:templates/admin/settings/settings.mako')
144 145 def settings_vcs_update(self):
145 146 _ = self.request.translate
146 147 c = self.load_default_context()
147 148 c.active = 'vcs'
148 149
149 150 model = VcsSettingsModel()
150 151 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
151 152 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
152 153
153 154 settings = self.request.registry.settings
154 155 c.svn_proxy_generate_config = settings[generate_config]
155 156
156 157 application_form = ApplicationUiSettingsForm(self.request.translate)()
157 158
158 159 try:
159 160 form_result = application_form.to_python(dict(self.request.POST))
160 161 except formencode.Invalid as errors:
161 162 h.flash(
162 163 _("Some form inputs contain invalid data."),
163 164 category='error')
164 165 data = render('rhodecode:templates/admin/settings/settings.mako',
165 166 self._get_template_context(c), self.request)
166 167 html = formencode.htmlfill.render(
167 168 data,
168 169 defaults=errors.value,
169 170 errors=errors.error_dict or {},
170 171 prefix_error=False,
171 172 encoding="UTF-8",
172 173 force_defaults=False
173 174 )
174 175 return Response(html)
175 176
176 177 try:
177 178 if c.visual.allow_repo_location_change:
178 179 model.update_global_path_setting(form_result['paths_root_path'])
179 180
180 181 model.update_global_ssl_setting(form_result['web_push_ssl'])
181 182 model.update_global_hook_settings(form_result)
182 183
183 184 model.create_or_update_global_svn_settings(form_result)
184 185 model.create_or_update_global_hg_settings(form_result)
185 186 model.create_or_update_global_git_settings(form_result)
186 187 model.create_or_update_global_pr_settings(form_result)
187 188 except Exception:
188 189 log.exception("Exception while updating settings")
189 190 h.flash(_('Error occurred during updating '
190 191 'application settings'), category='error')
191 192 else:
192 193 Session().commit()
193 194 h.flash(_('Updated VCS settings'), category='success')
194 195 raise HTTPFound(h.route_path('admin_settings_vcs'))
195 196
196 197 data = render('rhodecode:templates/admin/settings/settings.mako',
197 198 self._get_template_context(c), self.request)
198 199 html = formencode.htmlfill.render(
199 200 data,
200 201 defaults=self._form_defaults(),
201 202 encoding="UTF-8",
202 203 force_defaults=False
203 204 )
204 205 return Response(html)
205 206
206 207 @LoginRequired()
207 208 @HasPermissionAllDecorator('hg.admin')
208 209 @CSRFRequired()
209 210 @view_config(
210 211 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
211 212 renderer='json_ext', xhr=True)
212 213 def settings_vcs_delete_svn_pattern(self):
213 214 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
214 215 model = VcsSettingsModel()
215 216 try:
216 217 model.delete_global_svn_pattern(delete_pattern_id)
217 218 except SettingNotFound:
218 219 log.exception(
219 220 'Failed to delete svn_pattern with id %s', delete_pattern_id)
220 221 raise HTTPNotFound()
221 222
222 223 Session().commit()
223 224 return True
224 225
225 226 @LoginRequired()
226 227 @HasPermissionAllDecorator('hg.admin')
227 228 @view_config(
228 229 route_name='admin_settings_mapping', request_method='GET',
229 230 renderer='rhodecode:templates/admin/settings/settings.mako')
230 231 def settings_mapping(self):
231 232 c = self.load_default_context()
232 233 c.active = 'mapping'
233 234
234 235 data = render('rhodecode:templates/admin/settings/settings.mako',
235 236 self._get_template_context(c), self.request)
236 237 html = formencode.htmlfill.render(
237 238 data,
238 239 defaults=self._form_defaults(),
239 240 encoding="UTF-8",
240 241 force_defaults=False
241 242 )
242 243 return Response(html)
243 244
244 245 @LoginRequired()
245 246 @HasPermissionAllDecorator('hg.admin')
246 247 @CSRFRequired()
247 248 @view_config(
248 249 route_name='admin_settings_mapping_update', request_method='POST',
249 250 renderer='rhodecode:templates/admin/settings/settings.mako')
250 251 def settings_mapping_update(self):
251 252 _ = self.request.translate
252 253 c = self.load_default_context()
253 254 c.active = 'mapping'
254 255 rm_obsolete = self.request.POST.get('destroy', False)
255 256 invalidate_cache = self.request.POST.get('invalidate', False)
256 log.debug(
257 'rescanning repo location with destroy obsolete=%s', rm_obsolete)
257 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
258 258
259 259 if invalidate_cache:
260 260 log.debug('invalidating all repositories cache')
261 261 for repo in Repository.get_all():
262 262 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
263 263
264 264 filesystem_repos = ScmModel().repo_scan()
265 265 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
266 PermissionModel().trigger_permission_flush()
267
266 268 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
267 269 h.flash(_('Repositories successfully '
268 270 'rescanned added: %s ; removed: %s') %
269 271 (_repr(added), _repr(removed)),
270 272 category='success')
271 273 raise HTTPFound(h.route_path('admin_settings_mapping'))
272 274
273 275 @LoginRequired()
274 276 @HasPermissionAllDecorator('hg.admin')
275 277 @view_config(
276 278 route_name='admin_settings', request_method='GET',
277 279 renderer='rhodecode:templates/admin/settings/settings.mako')
278 280 @view_config(
279 281 route_name='admin_settings_global', request_method='GET',
280 282 renderer='rhodecode:templates/admin/settings/settings.mako')
281 283 def settings_global(self):
282 284 c = self.load_default_context()
283 285 c.active = 'global'
284 286 c.personal_repo_group_default_pattern = RepoGroupModel()\
285 287 .get_personal_group_name_pattern()
286 288
287 289 data = render('rhodecode:templates/admin/settings/settings.mako',
288 290 self._get_template_context(c), self.request)
289 291 html = formencode.htmlfill.render(
290 292 data,
291 293 defaults=self._form_defaults(),
292 294 encoding="UTF-8",
293 295 force_defaults=False
294 296 )
295 297 return Response(html)
296 298
297 299 @LoginRequired()
298 300 @HasPermissionAllDecorator('hg.admin')
299 301 @CSRFRequired()
300 302 @view_config(
301 303 route_name='admin_settings_update', request_method='POST',
302 304 renderer='rhodecode:templates/admin/settings/settings.mako')
303 305 @view_config(
304 306 route_name='admin_settings_global_update', request_method='POST',
305 307 renderer='rhodecode:templates/admin/settings/settings.mako')
306 308 def settings_global_update(self):
307 309 _ = self.request.translate
308 310 c = self.load_default_context()
309 311 c.active = 'global'
310 312 c.personal_repo_group_default_pattern = RepoGroupModel()\
311 313 .get_personal_group_name_pattern()
312 314 application_form = ApplicationSettingsForm(self.request.translate)()
313 315 try:
314 316 form_result = application_form.to_python(dict(self.request.POST))
315 317 except formencode.Invalid as errors:
316 318 h.flash(
317 319 _("Some form inputs contain invalid data."),
318 320 category='error')
319 321 data = render('rhodecode:templates/admin/settings/settings.mako',
320 322 self._get_template_context(c), self.request)
321 323 html = formencode.htmlfill.render(
322 324 data,
323 325 defaults=errors.value,
324 326 errors=errors.error_dict or {},
325 327 prefix_error=False,
326 328 encoding="UTF-8",
327 329 force_defaults=False
328 330 )
329 331 return Response(html)
330 332
331 333 settings = [
332 334 ('title', 'rhodecode_title', 'unicode'),
333 335 ('realm', 'rhodecode_realm', 'unicode'),
334 336 ('pre_code', 'rhodecode_pre_code', 'unicode'),
335 337 ('post_code', 'rhodecode_post_code', 'unicode'),
336 338 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
337 339 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
338 340 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
339 341 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
340 342 ]
341 343 try:
342 344 for setting, form_key, type_ in settings:
343 345 sett = SettingsModel().create_or_update_setting(
344 346 setting, form_result[form_key], type_)
345 347 Session().add(sett)
346 348
347 349 Session().commit()
348 350 SettingsModel().invalidate_settings_cache()
349 351 h.flash(_('Updated application settings'), category='success')
350 352 except Exception:
351 353 log.exception("Exception while updating application settings")
352 354 h.flash(
353 355 _('Error occurred during updating application settings'),
354 356 category='error')
355 357
356 358 raise HTTPFound(h.route_path('admin_settings_global'))
357 359
358 360 @LoginRequired()
359 361 @HasPermissionAllDecorator('hg.admin')
360 362 @view_config(
361 363 route_name='admin_settings_visual', request_method='GET',
362 364 renderer='rhodecode:templates/admin/settings/settings.mako')
363 365 def settings_visual(self):
364 366 c = self.load_default_context()
365 367 c.active = 'visual'
366 368
367 369 data = render('rhodecode:templates/admin/settings/settings.mako',
368 370 self._get_template_context(c), self.request)
369 371 html = formencode.htmlfill.render(
370 372 data,
371 373 defaults=self._form_defaults(),
372 374 encoding="UTF-8",
373 375 force_defaults=False
374 376 )
375 377 return Response(html)
376 378
377 379 @LoginRequired()
378 380 @HasPermissionAllDecorator('hg.admin')
379 381 @CSRFRequired()
380 382 @view_config(
381 383 route_name='admin_settings_visual_update', request_method='POST',
382 384 renderer='rhodecode:templates/admin/settings/settings.mako')
383 385 def settings_visual_update(self):
384 386 _ = self.request.translate
385 387 c = self.load_default_context()
386 388 c.active = 'visual'
387 389 application_form = ApplicationVisualisationForm(self.request.translate)()
388 390 try:
389 391 form_result = application_form.to_python(dict(self.request.POST))
390 392 except formencode.Invalid as errors:
391 393 h.flash(
392 394 _("Some form inputs contain invalid data."),
393 395 category='error')
394 396 data = render('rhodecode:templates/admin/settings/settings.mako',
395 397 self._get_template_context(c), self.request)
396 398 html = formencode.htmlfill.render(
397 399 data,
398 400 defaults=errors.value,
399 401 errors=errors.error_dict or {},
400 402 prefix_error=False,
401 403 encoding="UTF-8",
402 404 force_defaults=False
403 405 )
404 406 return Response(html)
405 407
406 408 try:
407 409 settings = [
408 410 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
409 411 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
410 412 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
411 413 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
412 414 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
413 415 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
414 416 ('show_version', 'rhodecode_show_version', 'bool'),
415 417 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
416 418 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
417 419 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
418 420 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
419 421 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
420 422 ('support_url', 'rhodecode_support_url', 'unicode'),
421 423 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
422 424 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
423 425 ]
424 426 for setting, form_key, type_ in settings:
425 427 sett = SettingsModel().create_or_update_setting(
426 428 setting, form_result[form_key], type_)
427 429 Session().add(sett)
428 430
429 431 Session().commit()
430 432 SettingsModel().invalidate_settings_cache()
431 433 h.flash(_('Updated visualisation settings'), category='success')
432 434 except Exception:
433 435 log.exception("Exception updating visualization settings")
434 436 h.flash(_('Error occurred during updating '
435 437 'visualisation settings'),
436 438 category='error')
437 439
438 440 raise HTTPFound(h.route_path('admin_settings_visual'))
439 441
440 442 @LoginRequired()
441 443 @HasPermissionAllDecorator('hg.admin')
442 444 @view_config(
443 445 route_name='admin_settings_issuetracker', request_method='GET',
444 446 renderer='rhodecode:templates/admin/settings/settings.mako')
445 447 def settings_issuetracker(self):
446 448 c = self.load_default_context()
447 449 c.active = 'issuetracker'
448 450 defaults = c.rc_config
449 451
450 452 entry_key = 'rhodecode_issuetracker_pat_'
451 453
452 454 c.issuetracker_entries = {}
453 455 for k, v in defaults.items():
454 456 if k.startswith(entry_key):
455 457 uid = k[len(entry_key):]
456 458 c.issuetracker_entries[uid] = None
457 459
458 460 for uid in c.issuetracker_entries:
459 461 c.issuetracker_entries[uid] = AttributeDict({
460 462 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
461 463 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
462 464 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
463 465 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
464 466 })
465 467
466 468 return self._get_template_context(c)
467 469
468 470 @LoginRequired()
469 471 @HasPermissionAllDecorator('hg.admin')
470 472 @CSRFRequired()
471 473 @view_config(
472 474 route_name='admin_settings_issuetracker_test', request_method='POST',
473 475 renderer='string', xhr=True)
474 476 def settings_issuetracker_test(self):
475 477 return h.urlify_commit_message(
476 478 self.request.POST.get('test_text', ''),
477 479 'repo_group/test_repo1')
478 480
479 481 @LoginRequired()
480 482 @HasPermissionAllDecorator('hg.admin')
481 483 @CSRFRequired()
482 484 @view_config(
483 485 route_name='admin_settings_issuetracker_update', request_method='POST',
484 486 renderer='rhodecode:templates/admin/settings/settings.mako')
485 487 def settings_issuetracker_update(self):
486 488 _ = self.request.translate
487 489 self.load_default_context()
488 490 settings_model = IssueTrackerSettingsModel()
489 491
490 492 try:
491 493 form = IssueTrackerPatternsForm(self.request.translate)()
492 494 data = form.to_python(self.request.POST)
493 495 except formencode.Invalid as errors:
494 496 log.exception('Failed to add new pattern')
495 497 error = errors
496 498 h.flash(_('Invalid issue tracker pattern: {}'.format(error)),
497 499 category='error')
498 500 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
499 501
500 502 if data:
501 503 for uid in data.get('delete_patterns', []):
502 504 settings_model.delete_entries(uid)
503 505
504 506 for pattern in data.get('patterns', []):
505 507 for setting, value, type_ in pattern:
506 508 sett = settings_model.create_or_update_setting(
507 509 setting, value, type_)
508 510 Session().add(sett)
509 511
510 512 Session().commit()
511 513
512 514 SettingsModel().invalidate_settings_cache()
513 515 h.flash(_('Updated issue tracker entries'), category='success')
514 516 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
515 517
516 518 @LoginRequired()
517 519 @HasPermissionAllDecorator('hg.admin')
518 520 @CSRFRequired()
519 521 @view_config(
520 522 route_name='admin_settings_issuetracker_delete', request_method='POST',
521 523 renderer='json_ext', xhr=True)
522 524 def settings_issuetracker_delete(self):
523 525 _ = self.request.translate
524 526 self.load_default_context()
525 527 uid = self.request.POST.get('uid')
526 528 try:
527 529 IssueTrackerSettingsModel().delete_entries(uid)
528 530 except Exception:
529 531 log.exception('Failed to delete issue tracker setting %s', uid)
530 532 raise HTTPNotFound()
531 533
532 534 SettingsModel().invalidate_settings_cache()
533 535 h.flash(_('Removed issue tracker entry.'), category='success')
534 536
535 537 return {'deleted': uid}
536 538
537 539 @LoginRequired()
538 540 @HasPermissionAllDecorator('hg.admin')
539 541 @view_config(
540 542 route_name='admin_settings_email', request_method='GET',
541 543 renderer='rhodecode:templates/admin/settings/settings.mako')
542 544 def settings_email(self):
543 545 c = self.load_default_context()
544 546 c.active = 'email'
545 547 c.rhodecode_ini = rhodecode.CONFIG
546 548
547 549 data = render('rhodecode:templates/admin/settings/settings.mako',
548 550 self._get_template_context(c), self.request)
549 551 html = formencode.htmlfill.render(
550 552 data,
551 553 defaults=self._form_defaults(),
552 554 encoding="UTF-8",
553 555 force_defaults=False
554 556 )
555 557 return Response(html)
556 558
557 559 @LoginRequired()
558 560 @HasPermissionAllDecorator('hg.admin')
559 561 @CSRFRequired()
560 562 @view_config(
561 563 route_name='admin_settings_email_update', request_method='POST',
562 564 renderer='rhodecode:templates/admin/settings/settings.mako')
563 565 def settings_email_update(self):
564 566 _ = self.request.translate
565 567 c = self.load_default_context()
566 568 c.active = 'email'
567 569
568 570 test_email = self.request.POST.get('test_email')
569 571
570 572 if not test_email:
571 573 h.flash(_('Please enter email address'), category='error')
572 574 raise HTTPFound(h.route_path('admin_settings_email'))
573 575
574 576 email_kwargs = {
575 577 'date': datetime.datetime.now(),
576 578 'user': self._rhodecode_db_user
577 579 }
578 580
579 581 (subject, headers, email_body,
580 582 email_body_plaintext) = EmailNotificationModel().render_email(
581 583 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
582 584
583 585 recipients = [test_email] if test_email else None
584 586
585 587 run_task(tasks.send_email, recipients, subject,
586 588 email_body_plaintext, email_body)
587 589
588 590 h.flash(_('Send email task created'), category='success')
589 591 raise HTTPFound(h.route_path('admin_settings_email'))
590 592
591 593 @LoginRequired()
592 594 @HasPermissionAllDecorator('hg.admin')
593 595 @view_config(
594 596 route_name='admin_settings_hooks', request_method='GET',
595 597 renderer='rhodecode:templates/admin/settings/settings.mako')
596 598 def settings_hooks(self):
597 599 c = self.load_default_context()
598 600 c.active = 'hooks'
599 601
600 602 model = SettingsModel()
601 603 c.hooks = model.get_builtin_hooks()
602 604 c.custom_hooks = model.get_custom_hooks()
603 605
604 606 data = render('rhodecode:templates/admin/settings/settings.mako',
605 607 self._get_template_context(c), self.request)
606 608 html = formencode.htmlfill.render(
607 609 data,
608 610 defaults=self._form_defaults(),
609 611 encoding="UTF-8",
610 612 force_defaults=False
611 613 )
612 614 return Response(html)
613 615
614 616 @LoginRequired()
615 617 @HasPermissionAllDecorator('hg.admin')
616 618 @CSRFRequired()
617 619 @view_config(
618 620 route_name='admin_settings_hooks_update', request_method='POST',
619 621 renderer='rhodecode:templates/admin/settings/settings.mako')
620 622 @view_config(
621 623 route_name='admin_settings_hooks_delete', request_method='POST',
622 624 renderer='rhodecode:templates/admin/settings/settings.mako')
623 625 def settings_hooks_update(self):
624 626 _ = self.request.translate
625 627 c = self.load_default_context()
626 628 c.active = 'hooks'
627 629 if c.visual.allow_custom_hooks_settings:
628 630 ui_key = self.request.POST.get('new_hook_ui_key')
629 631 ui_value = self.request.POST.get('new_hook_ui_value')
630 632
631 633 hook_id = self.request.POST.get('hook_id')
632 634 new_hook = False
633 635
634 636 model = SettingsModel()
635 637 try:
636 638 if ui_value and ui_key:
637 639 model.create_or_update_hook(ui_key, ui_value)
638 640 h.flash(_('Added new hook'), category='success')
639 641 new_hook = True
640 642 elif hook_id:
641 643 RhodeCodeUi.delete(hook_id)
642 644 Session().commit()
643 645
644 646 # check for edits
645 647 update = False
646 648 _d = self.request.POST.dict_of_lists()
647 649 for k, v in zip(_d.get('hook_ui_key', []),
648 650 _d.get('hook_ui_value_new', [])):
649 651 model.create_or_update_hook(k, v)
650 652 update = True
651 653
652 654 if update and not new_hook:
653 655 h.flash(_('Updated hooks'), category='success')
654 656 Session().commit()
655 657 except Exception:
656 658 log.exception("Exception during hook creation")
657 659 h.flash(_('Error occurred during hook creation'),
658 660 category='error')
659 661
660 662 raise HTTPFound(h.route_path('admin_settings_hooks'))
661 663
662 664 @LoginRequired()
663 665 @HasPermissionAllDecorator('hg.admin')
664 666 @view_config(
665 667 route_name='admin_settings_search', request_method='GET',
666 668 renderer='rhodecode:templates/admin/settings/settings.mako')
667 669 def settings_search(self):
668 670 c = self.load_default_context()
669 671 c.active = 'search'
670 672
671 673 c.searcher = searcher_from_config(self.request.registry.settings)
672 674 c.statistics = c.searcher.statistics(self.request.translate)
673 675
674 676 return self._get_template_context(c)
675 677
676 678 @LoginRequired()
677 679 @HasPermissionAllDecorator('hg.admin')
678 680 @view_config(
679 681 route_name='admin_settings_automation', request_method='GET',
680 682 renderer='rhodecode:templates/admin/settings/settings.mako')
681 683 def settings_automation(self):
682 684 c = self.load_default_context()
683 685 c.active = 'automation'
684 686
685 687 return self._get_template_context(c)
686 688
687 689 @LoginRequired()
688 690 @HasPermissionAllDecorator('hg.admin')
689 691 @view_config(
690 692 route_name='admin_settings_labs', request_method='GET',
691 693 renderer='rhodecode:templates/admin/settings/settings.mako')
692 694 def settings_labs(self):
693 695 c = self.load_default_context()
694 696 if not c.labs_active:
695 697 raise HTTPFound(h.route_path('admin_settings'))
696 698
697 699 c.active = 'labs'
698 700 c.lab_settings = _LAB_SETTINGS
699 701
700 702 data = render('rhodecode:templates/admin/settings/settings.mako',
701 703 self._get_template_context(c), self.request)
702 704 html = formencode.htmlfill.render(
703 705 data,
704 706 defaults=self._form_defaults(),
705 707 encoding="UTF-8",
706 708 force_defaults=False
707 709 )
708 710 return Response(html)
709 711
710 712 @LoginRequired()
711 713 @HasPermissionAllDecorator('hg.admin')
712 714 @CSRFRequired()
713 715 @view_config(
714 716 route_name='admin_settings_labs_update', request_method='POST',
715 717 renderer='rhodecode:templates/admin/settings/settings.mako')
716 718 def settings_labs_update(self):
717 719 _ = self.request.translate
718 720 c = self.load_default_context()
719 721 c.active = 'labs'
720 722
721 723 application_form = LabsSettingsForm(self.request.translate)()
722 724 try:
723 725 form_result = application_form.to_python(dict(self.request.POST))
724 726 except formencode.Invalid as errors:
725 727 h.flash(
726 728 _("Some form inputs contain invalid data."),
727 729 category='error')
728 730 data = render('rhodecode:templates/admin/settings/settings.mako',
729 731 self._get_template_context(c), self.request)
730 732 html = formencode.htmlfill.render(
731 733 data,
732 734 defaults=errors.value,
733 735 errors=errors.error_dict or {},
734 736 prefix_error=False,
735 737 encoding="UTF-8",
736 738 force_defaults=False
737 739 )
738 740 return Response(html)
739 741
740 742 try:
741 743 session = Session()
742 744 for setting in _LAB_SETTINGS:
743 745 setting_name = setting.key[len('rhodecode_'):]
744 746 sett = SettingsModel().create_or_update_setting(
745 747 setting_name, form_result[setting.key], setting.type)
746 748 session.add(sett)
747 749
748 750 except Exception:
749 751 log.exception('Exception while updating lab settings')
750 752 h.flash(_('Error occurred during updating labs settings'),
751 753 category='error')
752 754 else:
753 755 Session().commit()
754 756 SettingsModel().invalidate_settings_cache()
755 757 h.flash(_('Updated Labs settings'), category='success')
756 758 raise HTTPFound(h.route_path('admin_settings_labs'))
757 759
758 760 data = render('rhodecode:templates/admin/settings/settings.mako',
759 761 self._get_template_context(c), self.request)
760 762 html = formencode.htmlfill.render(
761 763 data,
762 764 defaults=self._form_defaults(),
763 765 encoding="UTF-8",
764 766 force_defaults=False
765 767 )
766 768 return Response(html)
767 769
768 770
769 771 # :param key: name of the setting including the 'rhodecode_' prefix
770 772 # :param type: the RhodeCodeSetting type to use.
771 773 # :param group: the i18ned group in which we should dispaly this setting
772 774 # :param label: the i18ned label we should display for this setting
773 775 # :param help: the i18ned help we should dispaly for this setting
774 776 LabSetting = collections.namedtuple(
775 777 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
776 778
777 779
778 780 # This list has to be kept in sync with the form
779 781 # rhodecode.model.forms.LabsSettingsForm.
780 782 _LAB_SETTINGS = [
781 783
782 784 ]
@@ -1,597 +1,598 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2020 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 permissions model for RhodeCode
23 23 """
24 24 import collections
25 25 import logging
26 26 import traceback
27 27
28 28 from sqlalchemy.exc import DatabaseError
29 29
30 30 from rhodecode import events
31 31 from rhodecode.model import BaseModel
32 32 from rhodecode.model.db import (
33 33 User, Permission, UserToPerm, UserRepoToPerm, UserRepoGroupToPerm,
34 34 UserUserGroupToPerm, UserGroup, UserGroupToPerm, UserToRepoBranchPermission)
35 35 from rhodecode.lib.utils2 import str2bool, safe_int
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 class PermissionModel(BaseModel):
41 41 """
42 42 Permissions model for RhodeCode
43 43 """
44 44
45 45 cls = Permission
46 46 global_perms = {
47 47 'default_repo_create': None,
48 48 # special case for create repos on write access to group
49 49 'default_repo_create_on_write': None,
50 50 'default_repo_group_create': None,
51 51 'default_user_group_create': None,
52 52 'default_fork_create': None,
53 53 'default_inherit_default_permissions': None,
54 54 'default_register': None,
55 55 'default_password_reset': None,
56 56 'default_extern_activate': None,
57 57
58 58 # object permissions below
59 59 'default_repo_perm': None,
60 60 'default_group_perm': None,
61 61 'default_user_group_perm': None,
62 62
63 63 # branch
64 64 'default_branch_perm': None,
65 65 }
66 66
67 67 def set_global_permission_choices(self, c_obj, gettext_translator):
68 68 _ = gettext_translator
69 69
70 70 c_obj.repo_perms_choices = [
71 71 ('repository.none', _('None'),),
72 72 ('repository.read', _('Read'),),
73 73 ('repository.write', _('Write'),),
74 74 ('repository.admin', _('Admin'),)]
75 75
76 76 c_obj.group_perms_choices = [
77 77 ('group.none', _('None'),),
78 78 ('group.read', _('Read'),),
79 79 ('group.write', _('Write'),),
80 80 ('group.admin', _('Admin'),)]
81 81
82 82 c_obj.user_group_perms_choices = [
83 83 ('usergroup.none', _('None'),),
84 84 ('usergroup.read', _('Read'),),
85 85 ('usergroup.write', _('Write'),),
86 86 ('usergroup.admin', _('Admin'),)]
87 87
88 88 c_obj.branch_perms_choices = [
89 89 ('branch.none', _('Protected/No Access'),),
90 90 ('branch.merge', _('Web merge'),),
91 91 ('branch.push', _('Push'),),
92 92 ('branch.push_force', _('Force Push'),)]
93 93
94 94 c_obj.register_choices = [
95 95 ('hg.register.none', _('Disabled')),
96 96 ('hg.register.manual_activate', _('Allowed with manual account activation')),
97 97 ('hg.register.auto_activate', _('Allowed with automatic account activation')),]
98 98
99 99 c_obj.password_reset_choices = [
100 100 ('hg.password_reset.enabled', _('Allow password recovery')),
101 101 ('hg.password_reset.hidden', _('Hide password recovery link')),
102 102 ('hg.password_reset.disabled', _('Disable password recovery')),]
103 103
104 104 c_obj.extern_activate_choices = [
105 105 ('hg.extern_activate.manual', _('Manual activation of external account')),
106 106 ('hg.extern_activate.auto', _('Automatic activation of external account')),]
107 107
108 108 c_obj.repo_create_choices = [
109 109 ('hg.create.none', _('Disabled')),
110 110 ('hg.create.repository', _('Enabled'))]
111 111
112 112 c_obj.repo_create_on_write_choices = [
113 113 ('hg.create.write_on_repogroup.false', _('Disabled')),
114 114 ('hg.create.write_on_repogroup.true', _('Enabled'))]
115 115
116 116 c_obj.user_group_create_choices = [
117 117 ('hg.usergroup.create.false', _('Disabled')),
118 118 ('hg.usergroup.create.true', _('Enabled'))]
119 119
120 120 c_obj.repo_group_create_choices = [
121 121 ('hg.repogroup.create.false', _('Disabled')),
122 122 ('hg.repogroup.create.true', _('Enabled'))]
123 123
124 124 c_obj.fork_choices = [
125 125 ('hg.fork.none', _('Disabled')),
126 126 ('hg.fork.repository', _('Enabled'))]
127 127
128 128 c_obj.inherit_default_permission_choices = [
129 129 ('hg.inherit_default_perms.false', _('Disabled')),
130 130 ('hg.inherit_default_perms.true', _('Enabled'))]
131 131
132 132 def get_default_perms(self, object_perms, suffix):
133 133 defaults = {}
134 134 for perm in object_perms:
135 135 # perms
136 136 if perm.permission.permission_name.startswith('repository.'):
137 137 defaults['default_repo_perm' + suffix] = perm.permission.permission_name
138 138
139 139 if perm.permission.permission_name.startswith('group.'):
140 140 defaults['default_group_perm' + suffix] = perm.permission.permission_name
141 141
142 142 if perm.permission.permission_name.startswith('usergroup.'):
143 143 defaults['default_user_group_perm' + suffix] = perm.permission.permission_name
144 144
145 145 # branch
146 146 if perm.permission.permission_name.startswith('branch.'):
147 147 defaults['default_branch_perm' + suffix] = perm.permission.permission_name
148 148
149 149 # creation of objects
150 150 if perm.permission.permission_name.startswith('hg.create.write_on_repogroup'):
151 151 defaults['default_repo_create_on_write' + suffix] = perm.permission.permission_name
152 152
153 153 elif perm.permission.permission_name.startswith('hg.create.'):
154 154 defaults['default_repo_create' + suffix] = perm.permission.permission_name
155 155
156 156 if perm.permission.permission_name.startswith('hg.fork.'):
157 157 defaults['default_fork_create' + suffix] = perm.permission.permission_name
158 158
159 159 if perm.permission.permission_name.startswith('hg.inherit_default_perms.'):
160 160 defaults['default_inherit_default_permissions' + suffix] = perm.permission.permission_name
161 161
162 162 if perm.permission.permission_name.startswith('hg.repogroup.'):
163 163 defaults['default_repo_group_create' + suffix] = perm.permission.permission_name
164 164
165 165 if perm.permission.permission_name.startswith('hg.usergroup.'):
166 166 defaults['default_user_group_create' + suffix] = perm.permission.permission_name
167 167
168 168 # registration and external account activation
169 169 if perm.permission.permission_name.startswith('hg.register.'):
170 170 defaults['default_register' + suffix] = perm.permission.permission_name
171 171
172 172 if perm.permission.permission_name.startswith('hg.password_reset.'):
173 173 defaults['default_password_reset' + suffix] = perm.permission.permission_name
174 174
175 175 if perm.permission.permission_name.startswith('hg.extern_activate.'):
176 176 defaults['default_extern_activate' + suffix] = perm.permission.permission_name
177 177
178 178 return defaults
179 179
180 180 def _make_new_user_perm(self, user, perm_name):
181 181 log.debug('Creating new user permission:%s', perm_name)
182 182 new = UserToPerm()
183 183 new.user = user
184 184 new.permission = Permission.get_by_key(perm_name)
185 185 return new
186 186
187 187 def _make_new_user_group_perm(self, user_group, perm_name):
188 188 log.debug('Creating new user group permission:%s', perm_name)
189 189 new = UserGroupToPerm()
190 190 new.users_group = user_group
191 191 new.permission = Permission.get_by_key(perm_name)
192 192 return new
193 193
194 194 def _keep_perm(self, perm_name, keep_fields):
195 195 def get_pat(field_name):
196 196 return {
197 197 # global perms
198 198 'default_repo_create': 'hg.create.',
199 199 # special case for create repos on write access to group
200 200 'default_repo_create_on_write': 'hg.create.write_on_repogroup.',
201 201 'default_repo_group_create': 'hg.repogroup.create.',
202 202 'default_user_group_create': 'hg.usergroup.create.',
203 203 'default_fork_create': 'hg.fork.',
204 204 'default_inherit_default_permissions': 'hg.inherit_default_perms.',
205 205
206 206 # application perms
207 207 'default_register': 'hg.register.',
208 208 'default_password_reset': 'hg.password_reset.',
209 209 'default_extern_activate': 'hg.extern_activate.',
210 210
211 211 # object permissions below
212 212 'default_repo_perm': 'repository.',
213 213 'default_group_perm': 'group.',
214 214 'default_user_group_perm': 'usergroup.',
215 215 # branch
216 216 'default_branch_perm': 'branch.',
217 217
218 218 }[field_name]
219 219 for field in keep_fields:
220 220 pat = get_pat(field)
221 221 if perm_name.startswith(pat):
222 222 return True
223 223 return False
224 224
225 225 def _clear_object_perm(self, object_perms, preserve=None):
226 226 preserve = preserve or []
227 227 _deleted = []
228 228 for perm in object_perms:
229 229 perm_name = perm.permission.permission_name
230 230 if not self._keep_perm(perm_name, keep_fields=preserve):
231 231 _deleted.append(perm_name)
232 232 self.sa.delete(perm)
233 233 return _deleted
234 234
235 235 def _clear_user_perms(self, user_id, preserve=None):
236 236 perms = self.sa.query(UserToPerm)\
237 237 .filter(UserToPerm.user_id == user_id)\
238 238 .all()
239 239 return self._clear_object_perm(perms, preserve=preserve)
240 240
241 241 def _clear_user_group_perms(self, user_group_id, preserve=None):
242 242 perms = self.sa.query(UserGroupToPerm)\
243 243 .filter(UserGroupToPerm.users_group_id == user_group_id)\
244 244 .all()
245 245 return self._clear_object_perm(perms, preserve=preserve)
246 246
247 247 def _set_new_object_perms(self, obj_type, object, form_result, preserve=None):
248 248 # clear current entries, to make this function idempotent
249 249 # it will fix even if we define more permissions or permissions
250 250 # are somehow missing
251 251 preserve = preserve or []
252 252 _global_perms = self.global_perms.copy()
253 253 if obj_type not in ['user', 'user_group']:
254 254 raise ValueError("obj_type must be on of 'user' or 'user_group'")
255 255 global_perms = len(_global_perms)
256 256 default_user_perms = len(Permission.DEFAULT_USER_PERMISSIONS)
257 257 if global_perms != default_user_perms:
258 258 raise Exception(
259 259 'Inconsistent permissions definition. Got {} vs {}'.format(
260 260 global_perms, default_user_perms))
261 261
262 262 if obj_type == 'user':
263 263 self._clear_user_perms(object.user_id, preserve)
264 264 if obj_type == 'user_group':
265 265 self._clear_user_group_perms(object.users_group_id, preserve)
266 266
267 267 # now kill the keys that we want to preserve from the form.
268 268 for key in preserve:
269 269 del _global_perms[key]
270 270
271 271 for k in _global_perms.copy():
272 272 _global_perms[k] = form_result[k]
273 273
274 274 # at that stage we validate all are passed inside form_result
275 275 for _perm_key, perm_value in _global_perms.items():
276 276 if perm_value is None:
277 277 raise ValueError('Missing permission for %s' % (_perm_key,))
278 278
279 279 if obj_type == 'user':
280 280 p = self._make_new_user_perm(object, perm_value)
281 281 self.sa.add(p)
282 282 if obj_type == 'user_group':
283 283 p = self._make_new_user_group_perm(object, perm_value)
284 284 self.sa.add(p)
285 285
286 286 def _set_new_user_perms(self, user, form_result, preserve=None):
287 287 return self._set_new_object_perms(
288 288 'user', user, form_result, preserve)
289 289
290 290 def _set_new_user_group_perms(self, user_group, form_result, preserve=None):
291 291 return self._set_new_object_perms(
292 292 'user_group', user_group, form_result, preserve)
293 293
294 294 def set_new_user_perms(self, user, form_result):
295 295 # calculate what to preserve from what is given in form_result
296 296 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
297 297 return self._set_new_user_perms(user, form_result, preserve)
298 298
299 299 def set_new_user_group_perms(self, user_group, form_result):
300 300 # calculate what to preserve from what is given in form_result
301 301 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
302 302 return self._set_new_user_group_perms(user_group, form_result, preserve)
303 303
304 304 def create_permissions(self):
305 305 """
306 306 Create permissions for whole system
307 307 """
308 308 for p in Permission.PERMS:
309 309 if not Permission.get_by_key(p[0]):
310 310 new_perm = Permission()
311 311 new_perm.permission_name = p[0]
312 312 new_perm.permission_longname = p[0] # translation err with p[1]
313 313 self.sa.add(new_perm)
314 314
315 315 def _create_default_object_permission(self, obj_type, obj, obj_perms,
316 316 force=False):
317 317 if obj_type not in ['user', 'user_group']:
318 318 raise ValueError("obj_type must be on of 'user' or 'user_group'")
319 319
320 320 def _get_group(perm_name):
321 321 return '.'.join(perm_name.split('.')[:1])
322 322
323 323 defined_perms_groups = map(
324 324 _get_group, (x.permission.permission_name for x in obj_perms))
325 325 log.debug('GOT ALREADY DEFINED:%s', obj_perms)
326 326
327 327 if force:
328 328 self._clear_object_perm(obj_perms)
329 329 self.sa.commit()
330 330 defined_perms_groups = []
331 331 # for every default permission that needs to be created, we check if
332 332 # it's group is already defined, if it's not we create default perm
333 333 for perm_name in Permission.DEFAULT_USER_PERMISSIONS:
334 334 gr = _get_group(perm_name)
335 335 if gr not in defined_perms_groups:
336 336 log.debug('GR:%s not found, creating permission %s',
337 337 gr, perm_name)
338 338 if obj_type == 'user':
339 339 new_perm = self._make_new_user_perm(obj, perm_name)
340 340 self.sa.add(new_perm)
341 341 if obj_type == 'user_group':
342 342 new_perm = self._make_new_user_group_perm(obj, perm_name)
343 343 self.sa.add(new_perm)
344 344
345 345 def create_default_user_permissions(self, user, force=False):
346 346 """
347 347 Creates only missing default permissions for user, if force is set it
348 348 resets the default permissions for that user
349 349
350 350 :param user:
351 351 :param force:
352 352 """
353 353 user = self._get_user(user)
354 354 obj_perms = UserToPerm.query().filter(UserToPerm.user == user).all()
355 355 return self._create_default_object_permission(
356 356 'user', user, obj_perms, force)
357 357
358 358 def create_default_user_group_permissions(self, user_group, force=False):
359 359 """
360 360 Creates only missing default permissions for user group, if force is
361 361 set it resets the default permissions for that user group
362 362
363 363 :param user_group:
364 364 :param force:
365 365 """
366 366 user_group = self._get_user_group(user_group)
367 367 obj_perms = UserToPerm.query().filter(UserGroupToPerm.users_group == user_group).all()
368 368 return self._create_default_object_permission(
369 369 'user_group', user_group, obj_perms, force)
370 370
371 371 def update_application_permissions(self, form_result):
372 372 if 'perm_user_id' in form_result:
373 373 perm_user = User.get(safe_int(form_result['perm_user_id']))
374 374 else:
375 375 # used mostly to do lookup for default user
376 376 perm_user = User.get_by_username(form_result['perm_user_name'])
377 377
378 378 try:
379 379 # stage 1 set anonymous access
380 380 if perm_user.username == User.DEFAULT_USER:
381 381 perm_user.active = str2bool(form_result['anonymous'])
382 382 self.sa.add(perm_user)
383 383
384 384 # stage 2 reset defaults and set them from form data
385 385 self._set_new_user_perms(perm_user, form_result, preserve=[
386 386 'default_repo_perm',
387 387 'default_group_perm',
388 388 'default_user_group_perm',
389 389 'default_branch_perm',
390 390
391 391 'default_repo_group_create',
392 392 'default_user_group_create',
393 393 'default_repo_create_on_write',
394 394 'default_repo_create',
395 395 'default_fork_create',
396 396 'default_inherit_default_permissions',])
397 397
398 398 self.sa.commit()
399 399 except (DatabaseError,):
400 400 log.error(traceback.format_exc())
401 401 self.sa.rollback()
402 402 raise
403 403
404 404 def update_user_permissions(self, form_result):
405 405 if 'perm_user_id' in form_result:
406 406 perm_user = User.get(safe_int(form_result['perm_user_id']))
407 407 else:
408 408 # used mostly to do lookup for default user
409 409 perm_user = User.get_by_username(form_result['perm_user_name'])
410 410 try:
411 411 # stage 2 reset defaults and set them from form data
412 412 self._set_new_user_perms(perm_user, form_result, preserve=[
413 413 'default_repo_perm',
414 414 'default_group_perm',
415 415 'default_user_group_perm',
416 416 'default_branch_perm',
417 417
418 418 'default_register',
419 419 'default_password_reset',
420 420 'default_extern_activate'])
421 421 self.sa.commit()
422 422 except (DatabaseError,):
423 423 log.error(traceback.format_exc())
424 424 self.sa.rollback()
425 425 raise
426 426
427 427 def update_user_group_permissions(self, form_result):
428 428 if 'perm_user_group_id' in form_result:
429 429 perm_user_group = UserGroup.get(safe_int(form_result['perm_user_group_id']))
430 430 else:
431 431 # used mostly to do lookup for default user
432 432 perm_user_group = UserGroup.get_by_group_name(form_result['perm_user_group_name'])
433 433 try:
434 434 # stage 2 reset defaults and set them from form data
435 435 self._set_new_user_group_perms(perm_user_group, form_result, preserve=[
436 436 'default_repo_perm',
437 437 'default_group_perm',
438 438 'default_user_group_perm',
439 439 'default_branch_perm',
440 440
441 441 'default_register',
442 442 'default_password_reset',
443 443 'default_extern_activate'])
444 444 self.sa.commit()
445 445 except (DatabaseError,):
446 446 log.error(traceback.format_exc())
447 447 self.sa.rollback()
448 448 raise
449 449
450 450 def update_object_permissions(self, form_result):
451 451 if 'perm_user_id' in form_result:
452 452 perm_user = User.get(safe_int(form_result['perm_user_id']))
453 453 else:
454 454 # used mostly to do lookup for default user
455 455 perm_user = User.get_by_username(form_result['perm_user_name'])
456 456 try:
457 457
458 458 # stage 2 reset defaults and set them from form data
459 459 self._set_new_user_perms(perm_user, form_result, preserve=[
460 460 'default_repo_group_create',
461 461 'default_user_group_create',
462 462 'default_repo_create_on_write',
463 463 'default_repo_create',
464 464 'default_fork_create',
465 465 'default_inherit_default_permissions',
466 466 'default_branch_perm',
467 467
468 468 'default_register',
469 469 'default_password_reset',
470 470 'default_extern_activate'])
471 471
472 472 # overwrite default repo permissions
473 473 if form_result['overwrite_default_repo']:
474 474 _def_name = form_result['default_repo_perm'].split('repository.')[-1]
475 475 _def = Permission.get_by_key('repository.' + _def_name)
476 476 for r2p in self.sa.query(UserRepoToPerm)\
477 477 .filter(UserRepoToPerm.user == perm_user)\
478 478 .all():
479 479 # don't reset PRIVATE repositories
480 480 if not r2p.repository.private:
481 481 r2p.permission = _def
482 482 self.sa.add(r2p)
483 483
484 484 # overwrite default repo group permissions
485 485 if form_result['overwrite_default_group']:
486 486 _def_name = form_result['default_group_perm'].split('group.')[-1]
487 487 _def = Permission.get_by_key('group.' + _def_name)
488 488 for g2p in self.sa.query(UserRepoGroupToPerm)\
489 489 .filter(UserRepoGroupToPerm.user == perm_user)\
490 490 .all():
491 491 g2p.permission = _def
492 492 self.sa.add(g2p)
493 493
494 494 # overwrite default user group permissions
495 495 if form_result['overwrite_default_user_group']:
496 496 _def_name = form_result['default_user_group_perm'].split('usergroup.')[-1]
497 497 # user groups
498 498 _def = Permission.get_by_key('usergroup.' + _def_name)
499 499 for g2p in self.sa.query(UserUserGroupToPerm)\
500 500 .filter(UserUserGroupToPerm.user == perm_user)\
501 501 .all():
502 502 g2p.permission = _def
503 503 self.sa.add(g2p)
504 504
505 505 # COMMIT
506 506 self.sa.commit()
507 507 except (DatabaseError,):
508 508 log.exception('Failed to set default object permissions')
509 509 self.sa.rollback()
510 510 raise
511 511
512 512 def update_branch_permissions(self, form_result):
513 513 if 'perm_user_id' in form_result:
514 514 perm_user = User.get(safe_int(form_result['perm_user_id']))
515 515 else:
516 516 # used mostly to do lookup for default user
517 517 perm_user = User.get_by_username(form_result['perm_user_name'])
518 518 try:
519 519
520 520 # stage 2 reset defaults and set them from form data
521 521 self._set_new_user_perms(perm_user, form_result, preserve=[
522 522 'default_repo_perm',
523 523 'default_group_perm',
524 524 'default_user_group_perm',
525 525
526 526 'default_repo_group_create',
527 527 'default_user_group_create',
528 528 'default_repo_create_on_write',
529 529 'default_repo_create',
530 530 'default_fork_create',
531 531 'default_inherit_default_permissions',
532 532
533 533 'default_register',
534 534 'default_password_reset',
535 535 'default_extern_activate'])
536 536
537 537 # overwrite default branch permissions
538 538 if form_result['overwrite_default_branch']:
539 539 _def_name = \
540 540 form_result['default_branch_perm'].split('branch.')[-1]
541 541
542 542 _def = Permission.get_by_key('branch.' + _def_name)
543 543
544 544 user_perms = UserToRepoBranchPermission.query()\
545 545 .join(UserToRepoBranchPermission.user_repo_to_perm)\
546 546 .filter(UserRepoToPerm.user == perm_user).all()
547 547
548 548 for g2p in user_perms:
549 549 g2p.permission = _def
550 550 self.sa.add(g2p)
551 551
552 552 # COMMIT
553 553 self.sa.commit()
554 554 except (DatabaseError,):
555 555 log.exception('Failed to set default branch permissions')
556 556 self.sa.rollback()
557 557 raise
558 558
559 559 def get_users_with_repo_write(self, db_repo):
560 560 write_plus = ['repository.write', 'repository.admin']
561 561 default_user_id = User.get_default_user_id()
562 562 user_write_permissions = collections.OrderedDict()
563 563
564 564 # write+ and DEFAULT user for inheritance
565 565 for perm in db_repo.permissions():
566 566 if perm.permission in write_plus or perm.user_id == default_user_id:
567 567 user_write_permissions[perm.user_id] = perm
568 568 return user_write_permissions
569 569
570 570 def get_user_groups_with_repo_write(self, db_repo):
571 571 write_plus = ['repository.write', 'repository.admin']
572 572 user_group_write_permissions = collections.OrderedDict()
573 573
574 574 # write+ and DEFAULT user for inheritance
575 575 for p in db_repo.permission_user_groups():
576 576 if p.permission in write_plus:
577 577 user_group_write_permissions[p.users_group_id] = p
578 578 return user_group_write_permissions
579 579
580 def trigger_permission_flush(self, affected_user_ids):
580 def trigger_permission_flush(self, affected_user_ids=None):
581 affected_user_ids or User.get_all_user_ids()
581 582 events.trigger(events.UserPermissionsChange(affected_user_ids))
582 583
583 584 def flush_user_permission_caches(self, changes, affected_user_ids=None):
584 585 affected_user_ids = affected_user_ids or []
585 586
586 587 for change in changes['added'] + changes['updated'] + changes['deleted']:
587 588 if change['type'] == 'user':
588 589 affected_user_ids.append(change['id'])
589 590 if change['type'] == 'user_group':
590 591 user_group = UserGroup.get(safe_int(change['id']))
591 592 if user_group:
592 593 group_members_ids = [x.user_id for x in user_group.members]
593 594 affected_user_ids.extend(group_members_ids)
594 595
595 596 self.trigger_permission_flush(affected_user_ids)
596 597
597 598 return affected_user_ids
General Comments 0
You need to be logged in to leave comments. Login now