Commit 6df4db1f authored by GitLab Release Tools Bot's avatar GitLab Release Tools Bot

Merge branch 'security-developer-transfer-project-12-4' into '12-4-stable'

Require Maintainer permission on group where project is transferred to

See merge request gitlab/gitlabhq!3486
parents b3490cf1 f1320e4f
...@@ -131,6 +131,8 @@ class GroupPolicy < BasePolicy ...@@ -131,6 +131,8 @@ class GroupPolicy < BasePolicy
rule { owner | admin }.enable :read_statistics rule { owner | admin }.enable :read_statistics
rule { maintainer & can?(:create_projects) }.enable :transfer_projects
def access_level def access_level
return GroupMember::NO_ACCESS if @user.nil? return GroupMember::NO_ACCESS if @user.nil?
......
...@@ -15,6 +15,8 @@ class NamespacePolicy < BasePolicy ...@@ -15,6 +15,8 @@ class NamespacePolicy < BasePolicy
end end
rule { personal_project & ~can_create_personal_project }.prevent :create_projects rule { personal_project & ~can_create_personal_project }.prevent :create_projects
rule { (owner | admin) & can?(:create_projects) }.enable :transfer_projects
end end
NamespacePolicy.prepend_if_ee('EE::NamespacePolicy') NamespacePolicy.prepend_if_ee('EE::NamespacePolicy')
...@@ -98,7 +98,7 @@ module Projects ...@@ -98,7 +98,7 @@ module Projects
@new_namespace && @new_namespace &&
can?(current_user, :change_namespace, project) && can?(current_user, :change_namespace, project) &&
@new_namespace.id != project.namespace_id && @new_namespace.id != project.namespace_id &&
current_user.can?(:create_projects, @new_namespace) current_user.can?(:transfer_projects, @new_namespace)
end end
def update_namespace_and_visibility(to_namespace) def update_namespace_and_visibility(to_namespace)
......
---
title: Require Maintainer permission on group where project is transferred to
merge_request:
author:
type: security
...@@ -354,6 +354,88 @@ describe GroupPolicy do ...@@ -354,6 +354,88 @@ describe GroupPolicy do
end end
end end
context 'transfer_projects' do
shared_examples_for 'allowed to transfer projects' do
before do
group.update(project_creation_level: project_creation_level)
end
it { is_expected.to be_allowed(:transfer_projects) }
end
shared_examples_for 'not allowed to transfer projects' do
before do
group.update(project_creation_level: project_creation_level)
end
it { is_expected.to be_disallowed(:transfer_projects) }
end
context 'reporter' do
let(:current_user) { reporter }
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
end
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
end
end
context 'developer' do
let(:current_user) { developer }
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
end
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
end
end
context 'maintainer' do
let(:current_user) { maintainer }
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end
it_behaves_like 'allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
end
it_behaves_like 'allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
end
end
context 'owner' do
let(:current_user) { owner }
it_behaves_like 'not allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
end
it_behaves_like 'allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
end
it_behaves_like 'allowed to transfer projects' do
let(:project_creation_level) { ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
end
end
end
context "create_projects" do context "create_projects" do
context 'when group has no project creation level set' do context 'when group has no project creation level set' do
before_all do before_all do
......
...@@ -6,7 +6,7 @@ describe NamespacePolicy do ...@@ -6,7 +6,7 @@ describe NamespacePolicy do
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, owner: owner) } let(:namespace) { create(:namespace, owner: owner) }
let(:owner_permissions) { [:create_projects, :admin_namespace, :read_namespace, :read_statistics] } let(:owner_permissions) { [:create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects] }
subject { described_class.new(current_user, namespace) } subject { described_class.new(current_user, namespace) }
...@@ -31,6 +31,7 @@ describe NamespacePolicy do ...@@ -31,6 +31,7 @@ describe NamespacePolicy do
let(:owner) { create(:user, projects_limit: 0) } let(:owner) { create(:user, projects_limit: 0) }
it { is_expected.to be_disallowed(:create_projects) } it { is_expected.to be_disallowed(:create_projects) }
it { is_expected.to be_disallowed(:transfer_projects) }
end end
end end
......
...@@ -2648,6 +2648,22 @@ describe API::Projects do ...@@ -2648,6 +2648,22 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
end end
context 'when authenticated as developer' do
before do
group.add_developer(user)
end
context 'target namespace allows developers to create projects' do
let(:group) { create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
it 'fails transferring the project to the target namespace' do
put api("/projects/#{project.id}/transfer", user), params: { namespace: group.id }
expect(response).to have_gitlab_http_status(400)
end
end
end
end end
it_behaves_like 'custom attributes endpoints', 'projects' do it_behaves_like 'custom attributes endpoints', 'projects' do
......
...@@ -222,6 +222,24 @@ describe Projects::TransferService do ...@@ -222,6 +222,24 @@ describe Projects::TransferService do
it { expect(project.errors[:new_namespace]).to include('Project with same name or path in target namespace already exists') } it { expect(project.errors[:new_namespace]).to include('Project with same name or path in target namespace already exists') }
end end
context 'target namespace allows developers to create projects' do
let(:group) { create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS) }
context 'the user is a member of the target namespace with developer permissions' do
subject(:transfer_project_result) { transfer_project(project, user, group) }
before do
group.add_developer(user)
end
it 'does not allow project transfer to the target namespace' do
expect(transfer_project_result).to eq false
expect(project.namespace).to eq(user.namespace)
expect(project.errors[:new_namespace]).to include('Transfer failed, please contact an admin.')
end
end
end
def transfer_project(project, user, new_namespace) def transfer_project(project, user, new_namespace)
service = Projects::TransferService.new(project, user) service = Projects::TransferService.new(project, user)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment