##// END OF EJS Templates
permissions: show overridden permissions in permission summary page
dan -
r100:5b55789f default
parent child Browse files
Show More
@@ -299,6 +299,54 b' def _cached_perms_data(user_id, scope, u'
299 299 explicit, algo)
300 300 return permissions.calculate()
301 301
302 class PermOrigin:
303 ADMIN = 'superadmin'
304
305 REPO_USER = 'user:%s'
306 REPO_USERGROUP = 'usergroup:%s'
307 REPO_OWNER = 'repo.owner'
308 REPO_DEFAULT = 'repo.default'
309 REPO_PRIVATE = 'repo.private'
310
311 REPOGROUP_USER = 'user:%s'
312 REPOGROUP_USERGROUP = 'usergroup:%s'
313 REPOGROUP_OWNER = 'group.owner'
314 REPOGROUP_DEFAULT = 'group.default'
315
316 USERGROUP_USER = 'user:%s'
317 USERGROUP_USERGROUP = 'usergroup:%s'
318 USERGROUP_OWNER = 'usergroup.owner'
319 USERGROUP_DEFAULT = 'usergroup.default'
320
321
322 class PermOriginDict(dict):
323 """
324 A special dict used for tracking permissions along with their origins.
325
326 `__setitem__` has been overridden to expect a tuple(perm, origin)
327 `__getitem__` will return only the perm
328 `.perm_origin_stack` will return the stack of (perm, origin) set per key
329
330 >>> perms = PermOriginDict()
331 >>> perms['resource'] = 'read', 'default'
332 >>> perms['resource']
333 'read'
334 >>> perms['resource'] = 'write', 'admin'
335 >>> perms['resource']
336 'write'
337 >>> perms.perm_origin_stack
338 {'resource': [('read', 'default'), ('write', 'admin')]}
339 """
340
341
342 def __init__(self, *args, **kw):
343 dict.__init__(self, *args, **kw)
344 self.perm_origin_stack = {}
345
346 def __setitem__(self, key, (perm, origin)):
347 self.perm_origin_stack.setdefault(key, []).append((perm, origin))
348 dict.__setitem__(self, key, perm)
349
302 350
303 351 class PermissionCalculator(object):
304 352
@@ -318,9 +366,9 b' class PermissionCalculator(object):'
318 366
319 367 self.default_user_id = User.get_default_user(cache=True).user_id
320 368
321 self.permissions_repositories = {}
322 self.permissions_repository_groups = {}
323 self.permissions_user_groups = {}
369 self.permissions_repositories = PermOriginDict()
370 self.permissions_repository_groups = PermOriginDict()
371 self.permissions_user_groups = PermOriginDict()
324 372 self.permissions_global = set()
325 373
326 374 self.default_repo_perms = Permission.get_default_repo_perms(
@@ -355,19 +403,19 b' class PermissionCalculator(object):'
355 403 for perm in self.default_repo_perms:
356 404 r_k = perm.UserRepoToPerm.repository.repo_name
357 405 p = 'repository.admin'
358 self.permissions_repositories[r_k] = p
406 self.permissions_repositories[r_k] = p, PermOrigin.ADMIN
359 407
360 408 # repository groups
361 409 for perm in self.default_repo_groups_perms:
362 410 rg_k = perm.UserRepoGroupToPerm.group.group_name
363 411 p = 'group.admin'
364 self.permissions_repository_groups[rg_k] = p
412 self.permissions_repository_groups[rg_k] = p, PermOrigin.ADMIN
365 413
366 414 # user groups
367 415 for perm in self.default_user_group_perms:
368 416 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
369 417 p = 'usergroup.admin'
370 self.permissions_user_groups[u_k] = p
418 self.permissions_user_groups[u_k] = p, PermOrigin.ADMIN
371 419
372 420 return self._permission_structure()
373 421
@@ -438,8 +486,7 b' class PermissionCalculator(object):'
438 486 self.permissions_global = self.permissions_global.difference(
439 487 _configurable)
440 488 for perm in perms:
441 self.permissions_global.add(
442 perm.permission.permission_name)
489 self.permissions_global.add(perm.permission.permission_name)
443 490
444 491 # user explicit global permissions
445 492 user_perms = Session().query(UserToPerm)\
@@ -478,13 +525,16 b' class PermissionCalculator(object):'
478 525 # on given repo
479 526 for perm in self.default_repo_perms:
480 527 r_k = perm.UserRepoToPerm.repository.repo_name
528 o = PermOrigin.REPO_DEFAULT
481 529 if perm.Repository.private and not (
482 530 perm.Repository.user_id == self.user_id):
483 531 # disable defaults for private repos,
484 532 p = 'repository.none'
533 o = PermOrigin.REPO_PRIVATE
485 534 elif perm.Repository.user_id == self.user_id:
486 535 # set admin if owner
487 536 p = 'repository.admin'
537 o = PermOrigin.REPO_OWNER
488 538 else:
489 539 p = perm.Permission.permission_name
490 540 # if we decide this user isn't inheriting permissions from
@@ -492,15 +542,17 b' class PermissionCalculator(object):'
492 542 # permissions work
493 543 if not user_inherit_object_permissions:
494 544 p = 'repository.none'
495 self.permissions_repositories[r_k] = p
545 self.permissions_repositories[r_k] = p, o
496 546
497 547 # defaults for repository groups taken from `default` user permission
498 548 # on given group
499 549 for perm in self.default_repo_groups_perms:
500 550 rg_k = perm.UserRepoGroupToPerm.group.group_name
551 o = PermOrigin.REPOGROUP_DEFAULT
501 552 if perm.RepoGroup.user_id == self.user_id:
502 553 # set admin if owner
503 554 p = 'group.admin'
555 o = PermOrigin.REPOGROUP_OWNER
504 556 else:
505 557 p = perm.Permission.permission_name
506 558
@@ -508,18 +560,19 b' class PermissionCalculator(object):'
508 560 # user we set him to .none so only explicit permissions work
509 561 if not user_inherit_object_permissions:
510 562 p = 'group.none'
511 self.permissions_repository_groups[rg_k] = p
563 self.permissions_repository_groups[rg_k] = p, o
512 564
513 565 # defaults for user groups taken from `default` user permission
514 566 # on given user group
515 567 for perm in self.default_user_group_perms:
516 568 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
517 569 p = perm.Permission.permission_name
570 o = PermOrigin.USERGROUP_DEFAULT
518 571 # if we decide this user isn't inheriting permissions from default
519 572 # user we set him to .none so only explicit permissions work
520 573 if not user_inherit_object_permissions:
521 574 p = 'usergroup.none'
522 self.permissions_user_groups[u_k] = p
575 self.permissions_user_groups[u_k] = p, o
523 576
524 577 def _calculate_repository_permissions(self):
525 578 """
@@ -538,17 +591,20 b' class PermissionCalculator(object):'
538 591 multiple_counter = collections.defaultdict(int)
539 592 for perm in user_repo_perms_from_user_group:
540 593 r_k = perm.UserGroupRepoToPerm.repository.repo_name
594 ug_k = perm.UserGroupRepoToPerm.users_group.users_group_name
541 595 multiple_counter[r_k] += 1
542 596 p = perm.Permission.permission_name
597 o = PermOrigin.REPO_USERGROUP % ug_k
543 598
544 599 if perm.Repository.user_id == self.user_id:
545 600 # set admin if owner
546 601 p = 'repository.admin'
602 o = PermOrigin.REPO_OWNER
547 603 else:
548 604 if multiple_counter[r_k] > 1:
549 605 cur_perm = self.permissions_repositories[r_k]
550 606 p = self._choose_permission(p, cur_perm)
551 self.permissions_repositories[r_k] = p
607 self.permissions_repositories[r_k] = p, o
552 608
553 609 # user explicit permissions for repositories, overrides any specified
554 610 # by the group permission
@@ -556,16 +612,18 b' class PermissionCalculator(object):'
556 612 self.user_id, self.scope_repo_id)
557 613 for perm in user_repo_perms:
558 614 r_k = perm.UserRepoToPerm.repository.repo_name
615 o = PermOrigin.REPO_USER % perm.UserRepoToPerm.user.username
559 616 # set admin if owner
560 617 if perm.Repository.user_id == self.user_id:
561 618 p = 'repository.admin'
619 o = PermOrigin.REPO_OWNER
562 620 else:
563 621 p = perm.Permission.permission_name
564 622 if not self.explicit:
565 623 cur_perm = self.permissions_repositories.get(
566 624 r_k, 'repository.none')
567 625 p = self._choose_permission(p, cur_perm)
568 self.permissions_repositories[r_k] = p
626 self.permissions_repositories[r_k] = p, o
569 627
570 628 def _calculate_repository_group_permissions(self):
571 629 """
@@ -583,32 +641,39 b' class PermissionCalculator(object):'
583 641 multiple_counter = collections.defaultdict(int)
584 642 for perm in user_repo_group_perms_from_user_group:
585 643 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
644 ug_k = perm.UserGroupRepoGroupToPerm.users_group.users_group_name
645 o = PermOrigin.REPOGROUP_USERGROUP % ug_k
586 646 multiple_counter[g_k] += 1
587 647 p = perm.Permission.permission_name
588 648 if perm.RepoGroup.user_id == self.user_id:
589 649 # set admin if owner
590 650 p = 'group.admin'
651 o = PermOrigin.REPOGROUP_OWNER
591 652 else:
592 653 if multiple_counter[g_k] > 1:
593 654 cur_perm = self.permissions_repository_groups[g_k]
594 655 p = self._choose_permission(p, cur_perm)
595 self.permissions_repository_groups[g_k] = p
656 self.permissions_repository_groups[g_k] = p, o
596 657
597 658 # user explicit permissions for repository groups
598 659 user_repo_groups_perms = Permission.get_default_group_perms(
599 660 self.user_id, self.scope_repo_group_id)
600 661 for perm in user_repo_groups_perms:
601 662 rg_k = perm.UserRepoGroupToPerm.group.group_name
663 u_k = perm.UserRepoGroupToPerm.user.username
664 o = PermOrigin.REPOGROUP_USER % u_k
665
602 666 if perm.RepoGroup.user_id == self.user_id:
603 667 # set admin if owner
604 668 p = 'group.admin'
669 o = PermOrigin.REPOGROUP_OWNER
605 670 else:
606 671 p = perm.Permission.permission_name
607 672 if not self.explicit:
608 673 cur_perm = self.permissions_repository_groups.get(
609 674 rg_k, 'group.none')
610 675 p = self._choose_permission(p, cur_perm)
611 self.permissions_repository_groups[rg_k] = p
676 self.permissions_repository_groups[rg_k] = p, o
612 677
613 678 def _calculate_user_group_permissions(self):
614 679 """
@@ -623,24 +688,29 b' class PermissionCalculator(object):'
623 688 for perm in user_group_from_user_group:
624 689 g_k = perm.UserGroupUserGroupToPerm\
625 690 .target_user_group.users_group_name
691 u_k = perm.UserGroupUserGroupToPerm\
692 .user_group.users_group_name
693 o = PermOrigin.USERGROUP_USERGROUP % u_k
626 694 multiple_counter[g_k] += 1
627 695 p = perm.Permission.permission_name
628 696 if multiple_counter[g_k] > 1:
629 697 cur_perm = self.permissions_user_groups[g_k]
630 698 p = self._choose_permission(p, cur_perm)
631 self.permissions_user_groups[g_k] = p
699 self.permissions_user_groups[g_k] = p, o
632 700
633 701 # user explicit permission for user groups
634 702 user_user_groups_perms = Permission.get_default_user_group_perms(
635 703 self.user_id, self.scope_user_group_id)
636 704 for perm in user_user_groups_perms:
637 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
705 ug_k = perm.UserUserGroupToPerm.user_group.users_group_name
706 u_k = perm.UserUserGroupToPerm.user.username
638 707 p = perm.Permission.permission_name
708 o = PermOrigin.USERGROUP_USER % u_k
639 709 if not self.explicit:
640 710 cur_perm = self.permissions_user_groups.get(
641 u_k, 'usergroup.none')
711 ug_k, 'usergroup.none')
642 712 p = self._choose_permission(p, cur_perm)
643 self.permissions_user_groups[u_k] = p
713 self.permissions_user_groups[ug_k] = p, o
644 714
645 715 def _choose_permission(self, new_perm, cur_perm):
646 716 new_perm_val = Permission.PERM_WEIGHTS[new_perm]
@@ -799,7 +869,7 b' class AuthUser(object):'
799 869 log.debug('No data in %s that could been used to log in' % self)
800 870
801 871 if not is_user_loaded:
802 log.debug('Failed to load user %s. Fallback to default user', self)
872 log.debug('Failed to load user. Fallback to default user')
803 873 # if we cannot authenticate user try anonymous
804 874 if anon_user.active:
805 875 user_model.fill_data(self, user_id=anon_user.user_id)
@@ -80,6 +80,11 b''
80 80 [tag="recommends"] { &:extend(.tag7); }
81 81 [tag="see"] { &:extend(.tag8); }
82 82
83 .perm_overriden {
84 text-decoration: line-through;
85 opacity: 0.6;
86 }
87
83 88 .perm_tag {
84 89 &:extend(.tag);
85 90
@@ -4,7 +4,6 b''
4 4 ## ${p.perms_summary(c.perm_user.permissions)}
5 5
6 6 <%def name="perms_summary(permissions, show_all=False, actions=True)">
7
8 7 <div id="perms" class="table fields">
9 8 %for section in sorted(permissions.keys()):
10 9 <div class="panel panel-default">
@@ -134,7 +133,15 b''
134 133 %endif
135 134 </td>
136 135 <td class="td-tags">
136 %if hasattr(permissions[section], 'perm_origin_stack'):
137 %for i, (perm, origin) in enumerate(reversed(permissions[section].perm_origin_stack[k])):
138 <span class="${i > 0 and 'perm_overriden' or ''} perm_tag ${perm.split('.')[-1]}">
139 ${perm} (${origin})
140 </span>
141 %endfor
142 %else:
137 143 <span class="perm_tag ${section_perm.split('.')[-1]}">${section_perm}</span>
144 %endif
138 145 </td>
139 146 %if actions:
140 147 <td class="td-action">
@@ -36,7 +36,7 b' class TestAdminUsersGroupsController(Tes'
36 36 def test_index(self):
37 37 self.log_user()
38 38 response = self.app.get(url('users_groups'))
39 response.mustcontain('No members yet')
39 response.status_int == 200
40 40
41 41 def test_create(self):
42 42 self.log_user()
@@ -32,6 +32,36 b' from rhodecode.model.user import UserMod'
32 32 from rhodecode.model.user_group import UserGroupModel
33 33
34 34
35 def test_perm_origin_dict():
36 pod = auth.PermOriginDict()
37 pod['thing'] = 'read', 'default'
38 assert pod['thing'] == 'read'
39
40 assert pod.perm_origin_stack == {
41 'thing': [('read', 'default')]}
42
43 pod['thing'] = 'write', 'admin'
44 assert pod['thing'] == 'write'
45
46 assert pod.perm_origin_stack == {
47 'thing': [('read', 'default'), ('write', 'admin')]}
48
49 pod['other'] = 'write', 'default'
50
51 assert pod.perm_origin_stack == {
52 'other': [('write', 'default')],
53 'thing': [('read', 'default'), ('write', 'admin')]}
54
55 pod['other'] = 'none', 'override'
56
57 assert pod.perm_origin_stack == {
58 'other': [('write', 'default'), ('none', 'override')],
59 'thing': [('read', 'default'), ('write', 'admin')]}
60
61 with pytest.raises(ValueError):
62 pod['thing'] = 'read'
63
64
35 65 def test_cached_perms_data(user_regular, backend_random):
36 66 permissions = get_permissions(user_regular)
37 67 repo_name = backend_random.repo.repo_name
General Comments 0
You need to be logged in to leave comments. Login now