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 |
|
|
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