##// 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 explicit, algo)
299 explicit, algo)
300 return permissions.calculate()
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 class PermissionCalculator(object):
351 class PermissionCalculator(object):
304
352
@@ -318,9 +366,9 b' class PermissionCalculator(object):'
318
366
319 self.default_user_id = User.get_default_user(cache=True).user_id
367 self.default_user_id = User.get_default_user(cache=True).user_id
320
368
321 self.permissions_repositories = {}
369 self.permissions_repositories = PermOriginDict()
322 self.permissions_repository_groups = {}
370 self.permissions_repository_groups = PermOriginDict()
323 self.permissions_user_groups = {}
371 self.permissions_user_groups = PermOriginDict()
324 self.permissions_global = set()
372 self.permissions_global = set()
325
373
326 self.default_repo_perms = Permission.get_default_repo_perms(
374 self.default_repo_perms = Permission.get_default_repo_perms(
@@ -355,19 +403,19 b' class PermissionCalculator(object):'
355 for perm in self.default_repo_perms:
403 for perm in self.default_repo_perms:
356 r_k = perm.UserRepoToPerm.repository.repo_name
404 r_k = perm.UserRepoToPerm.repository.repo_name
357 p = 'repository.admin'
405 p = 'repository.admin'
358 self.permissions_repositories[r_k] = p
406 self.permissions_repositories[r_k] = p, PermOrigin.ADMIN
359
407
360 # repository groups
408 # repository groups
361 for perm in self.default_repo_groups_perms:
409 for perm in self.default_repo_groups_perms:
362 rg_k = perm.UserRepoGroupToPerm.group.group_name
410 rg_k = perm.UserRepoGroupToPerm.group.group_name
363 p = 'group.admin'
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 # user groups
414 # user groups
367 for perm in self.default_user_group_perms:
415 for perm in self.default_user_group_perms:
368 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
416 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
369 p = 'usergroup.admin'
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 return self._permission_structure()
420 return self._permission_structure()
373
421
@@ -438,8 +486,7 b' class PermissionCalculator(object):'
438 self.permissions_global = self.permissions_global.difference(
486 self.permissions_global = self.permissions_global.difference(
439 _configurable)
487 _configurable)
440 for perm in perms:
488 for perm in perms:
441 self.permissions_global.add(
489 self.permissions_global.add(perm.permission.permission_name)
442 perm.permission.permission_name)
443
490
444 # user explicit global permissions
491 # user explicit global permissions
445 user_perms = Session().query(UserToPerm)\
492 user_perms = Session().query(UserToPerm)\
@@ -478,13 +525,16 b' class PermissionCalculator(object):'
478 # on given repo
525 # on given repo
479 for perm in self.default_repo_perms:
526 for perm in self.default_repo_perms:
480 r_k = perm.UserRepoToPerm.repository.repo_name
527 r_k = perm.UserRepoToPerm.repository.repo_name
528 o = PermOrigin.REPO_DEFAULT
481 if perm.Repository.private and not (
529 if perm.Repository.private and not (
482 perm.Repository.user_id == self.user_id):
530 perm.Repository.user_id == self.user_id):
483 # disable defaults for private repos,
531 # disable defaults for private repos,
484 p = 'repository.none'
532 p = 'repository.none'
533 o = PermOrigin.REPO_PRIVATE
485 elif perm.Repository.user_id == self.user_id:
534 elif perm.Repository.user_id == self.user_id:
486 # set admin if owner
535 # set admin if owner
487 p = 'repository.admin'
536 p = 'repository.admin'
537 o = PermOrigin.REPO_OWNER
488 else:
538 else:
489 p = perm.Permission.permission_name
539 p = perm.Permission.permission_name
490 # if we decide this user isn't inheriting permissions from
540 # if we decide this user isn't inheriting permissions from
@@ -492,15 +542,17 b' class PermissionCalculator(object):'
492 # permissions work
542 # permissions work
493 if not user_inherit_object_permissions:
543 if not user_inherit_object_permissions:
494 p = 'repository.none'
544 p = 'repository.none'
495 self.permissions_repositories[r_k] = p
545 self.permissions_repositories[r_k] = p, o
496
546
497 # defaults for repository groups taken from `default` user permission
547 # defaults for repository groups taken from `default` user permission
498 # on given group
548 # on given group
499 for perm in self.default_repo_groups_perms:
549 for perm in self.default_repo_groups_perms:
500 rg_k = perm.UserRepoGroupToPerm.group.group_name
550 rg_k = perm.UserRepoGroupToPerm.group.group_name
551 o = PermOrigin.REPOGROUP_DEFAULT
501 if perm.RepoGroup.user_id == self.user_id:
552 if perm.RepoGroup.user_id == self.user_id:
502 # set admin if owner
553 # set admin if owner
503 p = 'group.admin'
554 p = 'group.admin'
555 o = PermOrigin.REPOGROUP_OWNER
504 else:
556 else:
505 p = perm.Permission.permission_name
557 p = perm.Permission.permission_name
506
558
@@ -508,18 +560,19 b' class PermissionCalculator(object):'
508 # user we set him to .none so only explicit permissions work
560 # user we set him to .none so only explicit permissions work
509 if not user_inherit_object_permissions:
561 if not user_inherit_object_permissions:
510 p = 'group.none'
562 p = 'group.none'
511 self.permissions_repository_groups[rg_k] = p
563 self.permissions_repository_groups[rg_k] = p, o
512
564
513 # defaults for user groups taken from `default` user permission
565 # defaults for user groups taken from `default` user permission
514 # on given user group
566 # on given user group
515 for perm in self.default_user_group_perms:
567 for perm in self.default_user_group_perms:
516 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
568 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
517 p = perm.Permission.permission_name
569 p = perm.Permission.permission_name
570 o = PermOrigin.USERGROUP_DEFAULT
518 # if we decide this user isn't inheriting permissions from default
571 # if we decide this user isn't inheriting permissions from default
519 # user we set him to .none so only explicit permissions work
572 # user we set him to .none so only explicit permissions work
520 if not user_inherit_object_permissions:
573 if not user_inherit_object_permissions:
521 p = 'usergroup.none'
574 p = 'usergroup.none'
522 self.permissions_user_groups[u_k] = p
575 self.permissions_user_groups[u_k] = p, o
523
576
524 def _calculate_repository_permissions(self):
577 def _calculate_repository_permissions(self):
525 """
578 """
@@ -538,17 +591,20 b' class PermissionCalculator(object):'
538 multiple_counter = collections.defaultdict(int)
591 multiple_counter = collections.defaultdict(int)
539 for perm in user_repo_perms_from_user_group:
592 for perm in user_repo_perms_from_user_group:
540 r_k = perm.UserGroupRepoToPerm.repository.repo_name
593 r_k = perm.UserGroupRepoToPerm.repository.repo_name
594 ug_k = perm.UserGroupRepoToPerm.users_group.users_group_name
541 multiple_counter[r_k] += 1
595 multiple_counter[r_k] += 1
542 p = perm.Permission.permission_name
596 p = perm.Permission.permission_name
597 o = PermOrigin.REPO_USERGROUP % ug_k
543
598
544 if perm.Repository.user_id == self.user_id:
599 if perm.Repository.user_id == self.user_id:
545 # set admin if owner
600 # set admin if owner
546 p = 'repository.admin'
601 p = 'repository.admin'
602 o = PermOrigin.REPO_OWNER
547 else:
603 else:
548 if multiple_counter[r_k] > 1:
604 if multiple_counter[r_k] > 1:
549 cur_perm = self.permissions_repositories[r_k]
605 cur_perm = self.permissions_repositories[r_k]
550 p = self._choose_permission(p, cur_perm)
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 # user explicit permissions for repositories, overrides any specified
609 # user explicit permissions for repositories, overrides any specified
554 # by the group permission
610 # by the group permission
@@ -556,16 +612,18 b' class PermissionCalculator(object):'
556 self.user_id, self.scope_repo_id)
612 self.user_id, self.scope_repo_id)
557 for perm in user_repo_perms:
613 for perm in user_repo_perms:
558 r_k = perm.UserRepoToPerm.repository.repo_name
614 r_k = perm.UserRepoToPerm.repository.repo_name
615 o = PermOrigin.REPO_USER % perm.UserRepoToPerm.user.username
559 # set admin if owner
616 # set admin if owner
560 if perm.Repository.user_id == self.user_id:
617 if perm.Repository.user_id == self.user_id:
561 p = 'repository.admin'
618 p = 'repository.admin'
619 o = PermOrigin.REPO_OWNER
562 else:
620 else:
563 p = perm.Permission.permission_name
621 p = perm.Permission.permission_name
564 if not self.explicit:
622 if not self.explicit:
565 cur_perm = self.permissions_repositories.get(
623 cur_perm = self.permissions_repositories.get(
566 r_k, 'repository.none')
624 r_k, 'repository.none')
567 p = self._choose_permission(p, cur_perm)
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 def _calculate_repository_group_permissions(self):
628 def _calculate_repository_group_permissions(self):
571 """
629 """
@@ -583,32 +641,39 b' class PermissionCalculator(object):'
583 multiple_counter = collections.defaultdict(int)
641 multiple_counter = collections.defaultdict(int)
584 for perm in user_repo_group_perms_from_user_group:
642 for perm in user_repo_group_perms_from_user_group:
585 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
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 multiple_counter[g_k] += 1
646 multiple_counter[g_k] += 1
587 p = perm.Permission.permission_name
647 p = perm.Permission.permission_name
588 if perm.RepoGroup.user_id == self.user_id:
648 if perm.RepoGroup.user_id == self.user_id:
589 # set admin if owner
649 # set admin if owner
590 p = 'group.admin'
650 p = 'group.admin'
651 o = PermOrigin.REPOGROUP_OWNER
591 else:
652 else:
592 if multiple_counter[g_k] > 1:
653 if multiple_counter[g_k] > 1:
593 cur_perm = self.permissions_repository_groups[g_k]
654 cur_perm = self.permissions_repository_groups[g_k]
594 p = self._choose_permission(p, cur_perm)
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 # user explicit permissions for repository groups
658 # user explicit permissions for repository groups
598 user_repo_groups_perms = Permission.get_default_group_perms(
659 user_repo_groups_perms = Permission.get_default_group_perms(
599 self.user_id, self.scope_repo_group_id)
660 self.user_id, self.scope_repo_group_id)
600 for perm in user_repo_groups_perms:
661 for perm in user_repo_groups_perms:
601 rg_k = perm.UserRepoGroupToPerm.group.group_name
662 rg_k = perm.UserRepoGroupToPerm.group.group_name
663 u_k = perm.UserRepoGroupToPerm.user.username
664 o = PermOrigin.REPOGROUP_USER % u_k
665
602 if perm.RepoGroup.user_id == self.user_id:
666 if perm.RepoGroup.user_id == self.user_id:
603 # set admin if owner
667 # set admin if owner
604 p = 'group.admin'
668 p = 'group.admin'
669 o = PermOrigin.REPOGROUP_OWNER
605 else:
670 else:
606 p = perm.Permission.permission_name
671 p = perm.Permission.permission_name
607 if not self.explicit:
672 if not self.explicit:
608 cur_perm = self.permissions_repository_groups.get(
673 cur_perm = self.permissions_repository_groups.get(
609 rg_k, 'group.none')
674 rg_k, 'group.none')
610 p = self._choose_permission(p, cur_perm)
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 def _calculate_user_group_permissions(self):
678 def _calculate_user_group_permissions(self):
614 """
679 """
@@ -623,24 +688,29 b' class PermissionCalculator(object):'
623 for perm in user_group_from_user_group:
688 for perm in user_group_from_user_group:
624 g_k = perm.UserGroupUserGroupToPerm\
689 g_k = perm.UserGroupUserGroupToPerm\
625 .target_user_group.users_group_name
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 multiple_counter[g_k] += 1
694 multiple_counter[g_k] += 1
627 p = perm.Permission.permission_name
695 p = perm.Permission.permission_name
628 if multiple_counter[g_k] > 1:
696 if multiple_counter[g_k] > 1:
629 cur_perm = self.permissions_user_groups[g_k]
697 cur_perm = self.permissions_user_groups[g_k]
630 p = self._choose_permission(p, cur_perm)
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 # user explicit permission for user groups
701 # user explicit permission for user groups
634 user_user_groups_perms = Permission.get_default_user_group_perms(
702 user_user_groups_perms = Permission.get_default_user_group_perms(
635 self.user_id, self.scope_user_group_id)
703 self.user_id, self.scope_user_group_id)
636 for perm in user_user_groups_perms:
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 p = perm.Permission.permission_name
707 p = perm.Permission.permission_name
708 o = PermOrigin.USERGROUP_USER % u_k
639 if not self.explicit:
709 if not self.explicit:
640 cur_perm = self.permissions_user_groups.get(
710 cur_perm = self.permissions_user_groups.get(
641 u_k, 'usergroup.none')
711 ug_k, 'usergroup.none')
642 p = self._choose_permission(p, cur_perm)
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 def _choose_permission(self, new_perm, cur_perm):
715 def _choose_permission(self, new_perm, cur_perm):
646 new_perm_val = Permission.PERM_WEIGHTS[new_perm]
716 new_perm_val = Permission.PERM_WEIGHTS[new_perm]
@@ -799,7 +869,7 b' class AuthUser(object):'
799 log.debug('No data in %s that could been used to log in' % self)
869 log.debug('No data in %s that could been used to log in' % self)
800
870
801 if not is_user_loaded:
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 # if we cannot authenticate user try anonymous
873 # if we cannot authenticate user try anonymous
804 if anon_user.active:
874 if anon_user.active:
805 user_model.fill_data(self, user_id=anon_user.user_id)
875 user_model.fill_data(self, user_id=anon_user.user_id)
@@ -80,6 +80,11 b''
80 [tag="recommends"] { &:extend(.tag7); }
80 [tag="recommends"] { &:extend(.tag7); }
81 [tag="see"] { &:extend(.tag8); }
81 [tag="see"] { &:extend(.tag8); }
82
82
83 .perm_overriden {
84 text-decoration: line-through;
85 opacity: 0.6;
86 }
87
83 .perm_tag {
88 .perm_tag {
84 &:extend(.tag);
89 &:extend(.tag);
85
90
@@ -4,7 +4,6 b''
4 ## ${p.perms_summary(c.perm_user.permissions)}
4 ## ${p.perms_summary(c.perm_user.permissions)}
5
5
6 <%def name="perms_summary(permissions, show_all=False, actions=True)">
6 <%def name="perms_summary(permissions, show_all=False, actions=True)">
7
8 <div id="perms" class="table fields">
7 <div id="perms" class="table fields">
9 %for section in sorted(permissions.keys()):
8 %for section in sorted(permissions.keys()):
10 <div class="panel panel-default">
9 <div class="panel panel-default">
@@ -134,7 +133,15 b''
134 %endif
133 %endif
135 </td>
134 </td>
136 <td class="td-tags">
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 <span class="perm_tag ${section_perm.split('.')[-1]}">${section_perm}</span>
143 <span class="perm_tag ${section_perm.split('.')[-1]}">${section_perm}</span>
144 %endif
138 </td>
145 </td>
139 %if actions:
146 %if actions:
140 <td class="td-action">
147 <td class="td-action">
@@ -154,7 +161,7 b''
154 <tr id="empty_${section}" class="noborder" style="display:none;">
161 <tr id="empty_${section}" class="noborder" style="display:none;">
155 <td colspan="6">${_('No permission defined')}</td>
162 <td colspan="6">${_('No permission defined')}</td>
156 </tr>
163 </tr>
157
164
158 </tbody>
165 </tbody>
159 %endif
166 %endif
160 </table>
167 </table>
@@ -36,7 +36,7 b' class TestAdminUsersGroupsController(Tes'
36 def test_index(self):
36 def test_index(self):
37 self.log_user()
37 self.log_user()
38 response = self.app.get(url('users_groups'))
38 response = self.app.get(url('users_groups'))
39 response.mustcontain('No members yet')
39 response.status_int == 200
40
40
41 def test_create(self):
41 def test_create(self):
42 self.log_user()
42 self.log_user()
@@ -32,6 +32,36 b' from rhodecode.model.user import UserMod'
32 from rhodecode.model.user_group import UserGroupModel
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 def test_cached_perms_data(user_regular, backend_random):
65 def test_cached_perms_data(user_regular, backend_random):
36 permissions = get_permissions(user_regular)
66 permissions = get_permissions(user_regular)
37 repo_name = backend_random.repo.repo_name
67 repo_name = backend_random.repo.repo_name
General Comments 0
You need to be logged in to leave comments. Login now