diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -571,8 +571,14 @@ class PermissionCalculator(object): # on given user group for perm in self.default_user_group_perms: u_k = perm.UserUserGroupToPerm.user_group.users_group_name - p = perm.Permission.permission_name o = PermOrigin.USERGROUP_DEFAULT + if perm.UserGroup.user_id == self.user_id: + # set admin if owner + p = 'usergroup.admin' + o = PermOrigin.USERGROUP_OWNER + else: + p = perm.Permission.permission_name + # if we decide this user isn't inheriting permissions from default # user we set him to .none so only explicit permissions work if not user_inherit_object_permissions: @@ -651,7 +657,7 @@ class PermissionCalculator(object): multiple_counter[g_k] += 1 p = perm.Permission.permission_name if perm.RepoGroup.user_id == self.user_id: - # set admin if owner + # set admin if owner, even for member of other user group p = 'group.admin' o = PermOrigin.REPOGROUP_OWNER else: @@ -687,7 +693,7 @@ class PermissionCalculator(object): # user group for user group permissions user_group_from_user_group = Permission\ .get_default_user_group_perms_from_user_group( - self.user_id, self.scope_repo_group_id) + self.user_id, self.scope_user_group_id) multiple_counter = collections.defaultdict(int) for perm in user_group_from_user_group: @@ -698,9 +704,15 @@ class PermissionCalculator(object): o = PermOrigin.USERGROUP_USERGROUP % u_k multiple_counter[g_k] += 1 p = perm.Permission.permission_name - if multiple_counter[g_k] > 1: - cur_perm = self.permissions_user_groups[g_k] - p = self._choose_permission(p, cur_perm) + + if perm.UserGroup.user_id == self.user_id: + # set admin if owner, even for member of other user group + p = 'usergroup.admin' + o = PermOrigin.USERGROUP_OWNER + else: + if multiple_counter[g_k] > 1: + cur_perm = self.permissions_user_groups[g_k] + p = self._choose_permission(p, cur_perm) self.permissions_user_groups[g_k] = p, o # user explicit permission for user groups @@ -709,12 +721,18 @@ class PermissionCalculator(object): for perm in user_user_groups_perms: ug_k = perm.UserUserGroupToPerm.user_group.users_group_name u_k = perm.UserUserGroupToPerm.user.username - p = perm.Permission.permission_name o = PermOrigin.USERGROUP_USER % u_k - if not self.explicit: - cur_perm = self.permissions_user_groups.get( - ug_k, 'usergroup.none') - p = self._choose_permission(p, cur_perm) + + if perm.UserGroup.user_id == self.user_id: + # set admin if owner + p = 'usergroup.admin' + o = PermOrigin.USERGROUP_OWNER + else: + p = perm.Permission.permission_name + if not self.explicit: + cur_perm = self.permissions_user_groups.get( + ug_k, 'usergroup.none') + p = self._choose_permission(p, cur_perm) self.permissions_user_groups[ug_k] = p, o def _choose_permission(self, new_perm, cur_perm): @@ -942,25 +960,27 @@ class AuthUser(object): """ Returns list of repositories you're an admin of """ - return [x[0] for x in self.permissions['repositories'].iteritems() - if x[1] == 'repository.admin'] + return [ + x[0] for x in self.permissions['repositories'].iteritems() + if x[1] == 'repository.admin'] @property def repository_groups_admin(self): """ Returns list of repository groups you're an admin of """ - return [x[0] - for x in self.permissions['repositories_groups'].iteritems() - if x[1] == 'group.admin'] + return [ + x[0] for x in self.permissions['repositories_groups'].iteritems() + if x[1] == 'group.admin'] @property def user_groups_admin(self): """ Returns list of user groups you're an admin of """ - return [x[0] for x in self.permissions['user_groups'].iteritems() - if x[1] == 'usergroup.admin'] + return [ + x[0] for x in self.permissions['user_groups'].iteritems() + if x[1] == 'usergroup.admin'] @property def ip_allowed(self): diff --git a/rhodecode/templates/base/base.mako b/rhodecode/templates/base/base.mako --- a/rhodecode/templates/base/base.mako +++ b/rhodecode/templates/base/base.mako @@ -142,13 +142,13 @@ <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)"> diff --git a/rhodecode/tests/functional/test_admin_repo_groups.py b/rhodecode/tests/functional/test_admin_repo_groups.py --- a/rhodecode/tests/functional/test_admin_repo_groups.py +++ b/rhodecode/tests/functional/test_admin_repo_groups.py @@ -137,8 +137,7 @@ class _BaseTest(TestController): assert new_repo_group.group_name == repo_group_name_unicode assert new_repo_group.group_description == description - # - # # test if the repository is visible in the list ? + # test if the repository is visible in the list ? response = self.app.get( url('repo_group_home', group_name=repo_group_name)) response.mustcontain(repo_group_name) diff --git a/rhodecode/tests/functional/test_delegated_admin.py b/rhodecode/tests/functional/test_delegated_admin.py new file mode 100644 --- /dev/null +++ b/rhodecode/tests/functional/test_delegated_admin.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2016-2017 RhodeCode GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3 +# (only), as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# This program is dual-licensed. If you wish to learn more about the +# RhodeCode Enterprise Edition, including its added features, Support services, +# and proprietary license terms, please see https://rhodecode.com/licenses/ + +import pytest + +from rhodecode.tests import ( + TestController, url, assert_session_flash, link_to) +from rhodecode.model.db import User, UserGroup +from rhodecode.model.meta import Session +from rhodecode.tests.fixture import Fixture + + +fixture = Fixture() + + +class TestAdminUsersGroupsController(TestController): + + def test_regular_user_cannot_see_admin_interfaces(self, user_util): + user = user_util.create_user(password='qweqwe') + self.log_user(user.username, 'qweqwe') + + # check if in home view, such user doesn't see the "admin" menus + response = self.app.get(url('home')) + + assert_response = response.assert_response() + + assert_response.no_element_exists('li.local-admin-repos') + assert_response.no_element_exists('li.local-admin-repo-groups') + assert_response.no_element_exists('li.local-admin-user-groups') + + response = self.app.get(url('repos'), status=200) + response.mustcontain('data: []') + + response = self.app.get(url('repo_groups'), status=200) + response.mustcontain('data: []') + + response = self.app.get(url('users_groups'), status=200) + response.mustcontain('data: []') + + def test_regular_user_can_see_admin_interfaces_if_owner(self, user_util): + user = user_util.create_user(password='qweqwe') + username = user.username + + repo = user_util.create_repo(owner=username) + repo_name = repo.repo_name + + repo_group = user_util.create_repo_group(owner=username) + repo_group_name = repo_group.group_name + + user_group = user_util.create_user_group(owner=username) + user_group_name = user_group.users_group_name + + self.log_user(username, 'qweqwe') + # check if in home view, such user doesn't see the "admin" menus + response = self.app.get(url('home')) + + assert_response = response.assert_response() + + assert_response.one_element_exists('li.local-admin-repos') + assert_response.one_element_exists('li.local-admin-repo-groups') + assert_response.one_element_exists('li.local-admin-user-groups') + + # admin interfaces have visible elements + response = self.app.get(url('repos'), status=200) + response.mustcontain('"name_raw": "{}"'.format(repo_name)) + + response = self.app.get(url('repo_groups'), status=200) + response.mustcontain('"name_raw": "{}"'.format(repo_group_name)) + + response = self.app.get(url('users_groups'), status=200) + response.mustcontain('"group_name_raw": "{}"'.format(user_group_name)) + + def test_regular_user_can_see_admin_interfaces_if_admin_perm(self, user_util): + user = user_util.create_user(password='qweqwe') + username = user.username + + repo = user_util.create_repo() + repo_name = repo.repo_name + + repo_group = user_util.create_repo_group() + repo_group_name = repo_group.group_name + + user_group = user_util.create_user_group() + user_group_name = user_group.users_group_name + + user_util.grant_user_permission_to_repo( + repo, user, 'repository.admin') + user_util.grant_user_permission_to_repo_group( + repo_group, user, 'group.admin') + user_util.grant_user_permission_to_user_group( + user_group, user, 'usergroup.admin') + + self.log_user(username, 'qweqwe') + # check if in home view, such user doesn't see the "admin" menus + response = self.app.get(url('home')) + + assert_response = response.assert_response() + + assert_response.one_element_exists('li.local-admin-repos') + assert_response.one_element_exists('li.local-admin-repo-groups') + assert_response.one_element_exists('li.local-admin-user-groups') + + # admin interfaces have visible elements + response = self.app.get(url('repos'), status=200) + response.mustcontain('"name_raw": "{}"'.format(repo_name)) + + response = self.app.get(url('repo_groups'), status=200) + response.mustcontain('"name_raw": "{}"'.format(repo_group_name)) + + response = self.app.get(url('users_groups'), status=200) + response.mustcontain('"group_name_raw": "{}"'.format(user_group_name)) diff --git a/rhodecode/tests/models/test_permissions.py b/rhodecode/tests/models/test_permissions.py --- a/rhodecode/tests/models/test_permissions.py +++ b/rhodecode/tests/models/test_permissions.py @@ -130,14 +130,36 @@ class TestPermissions(object): assert group_perms(self.a1) == { 'test1': 'group.admin', 'test2': 'group.admin'} - def test_default_owner_group_perms(self): - # "u1" shall be owner without any special permission assigned - self.g1 = fixture.create_repo_group('test1') - assert group_perms(self.u1) == {'test1': 'group.read'} + def test_default_owner_repo_perms(self, backend, user_util, test_repo): + user = user_util.create_user() + repo = test_repo('minimal', backend.alias) + org_owner = repo.user + assert repo_perms(user)[repo.repo_name] == 'repository.read' + + repo.user = user + assert repo_perms(user)[repo.repo_name] == 'repository.admin' + repo.user = org_owner + + def test_default_owner_repo_group_perms(self, user_util, test_repo_group): + user = user_util.create_user() + org_owner = test_repo_group.user - # Make him owner, but do not add any special permissions - self.g1.user = self.u1 - assert group_perms(self.u1) == {'test1': 'group.admin'} + assert group_perms(user)[test_repo_group.group_name] == 'group.read' + + test_repo_group.user = user + assert group_perms(user)[test_repo_group.group_name] == 'group.admin' + test_repo_group.user = org_owner + + def test_default_owner_user_group_perms(self, user_util, test_user_group): + user = user_util.create_user() + org_owner = test_user_group.user + + assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.read' + + test_user_group.user = user + assert user_group_perms(user)[test_user_group.users_group_name] == 'usergroup.admin' + + test_user_group.user = org_owner def test_propagated_permission_from_users_group_by_explicit_perms_exist( self, repo_name):