Commit 6aa77991 authored by manojmj's avatar manojmj

Introduce policies around setting “default branch protection” in groups

This change introuduces new policies around setting
“default branch protection” in groups.

Namely:

`create_group_with_default_branch_protection `:
this permission determines whether a user can specify the value
of `default_branch_protection` when creating a new group.

`update_default_branch_protection `: this permission determines
whether a user can update the value of `default_branch_protection`
of a group.
parent 284428a4
......@@ -49,6 +49,10 @@ module GroupsHelper
can?(current_user, :change_visibility_level, group)
end
def can_update_default_branch_protection?(group)
can?(current_user, :update_default_branch_protection, group)
end
def can_change_share_with_group_lock?(group)
can?(current_user, :change_share_with_group_lock, group)
end
......
......@@ -74,6 +74,10 @@ class GlobalPolicy < BasePolicy
enable :create_group
end
rule { can?(:create_group) }.policy do
enable :create_group_with_default_branch_protection
end
rule { can_create_fork }.policy do
enable :create_fork
end
......
......@@ -123,6 +123,7 @@ class GroupPolicy < BasePolicy
enable :set_note_created_at
enable :set_emails_disabled
enable :update_default_branch_protection
end
rule { can?(:read_nested_project_resources) }.policy do
......
......@@ -38,6 +38,10 @@ module Groups
# overridden in EE
end
def remove_unallowed_params
params.delete(:default_branch_protection) unless can?(current_user, :create_group_with_default_branch_protection)
end
def create_chat_team?
Gitlab.config.mattermost.enabled && @chat_team && group.chat_team.nil?
end
......
......@@ -66,6 +66,7 @@ module Groups
# overridden in EE
def remove_unallowed_params
params.delete(:emails_disabled) unless can?(current_user, :set_emails_disabled, group)
params.delete(:default_branch_protection) unless can?(current_user, :update_default_branch_protection, group)
end
def valid_share_with_group_lock_change?
......
- return unless can_update_default_branch_protection?(group)
= render 'shared/default_branch_protection', f: f, selected_level: group.default_branch_protection
......@@ -33,7 +33,7 @@
= render_if_exists 'groups/settings/ip_restriction', f: f, group: @group
= render_if_exists 'groups/settings/allowed_email_domain', f: f, group: @group
= render 'groups/settings/lfs', f: f
= render 'shared/default_branch_protection', f: f, selected_level: @group.default_branch_protection
= render 'groups/settings/default_branch_protection', f: f, group: @group
= render 'groups/settings/project_creation_level', f: f, group: @group
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
= render 'groups/settings/two_factor_auth', f: f
......
......@@ -25,6 +25,8 @@ module EE
params.delete(:shared_runners_minutes_limit)
params.delete(:extra_shared_runners_minutes_limit)
end
super
end
def log_audit_event
......
......@@ -270,6 +270,39 @@ describe GroupsController do
it { expect(subject).to render_template(:new) }
end
context 'when creating a group with `default_branch_protection` attribute' do
before do
sign_in(user)
end
subject do
post :create, params: { group: { name: 'new_group', path: 'new_group', default_branch_protection: Gitlab::Access::PROTECTION_NONE } }
end
context 'for users who have the ability to create a group with `default_branch_protection`' do
it 'creates group with the specified branch protection level' do
subject
expect(response).to have_gitlab_http_status(:found)
expect(Group.last.default_branch_protection).to eq(Gitlab::Access::PROTECTION_NONE)
end
end
context 'for users who do not have the ability to create a group with `default_branch_protection`' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :create_group_with_default_branch_protection) { false }
end
it 'does not create the group with the specified branch protection level' do
subject
expect(response).to have_gitlab_http_status(:found)
expect(Group.last.default_branch_protection).not_to eq(Gitlab::Access::PROTECTION_NONE)
end
end
end
end
describe 'GET #index' do
......@@ -423,12 +456,34 @@ describe GroupsController do
expect(group.reload.project_creation_level).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
end
it 'updates the default_branch_protection successfully' do
post :update, params: { id: group.to_param, group: { default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE } }
context 'updating default_branch_protection' do
subject do
put :update, params: { id: group.to_param, group: { default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE } }
end
context 'for users who have the ability to update default_branch_protection' do
it 'updates the attribute' do
subject
expect(response).to have_gitlab_http_status(:found)
expect(group.reload.default_branch_protection).to eq(::Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
end
end
context 'for users who do not have the ability to update default_branch_protection' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :update_default_branch_protection, group) { false }
end
it 'does not update the attribute' do
subject
expect(response).to have_gitlab_http_status(:found)
expect(group.reload.default_branch_protection).not_to eq(::Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
end
end
end
context 'when a project inside the group has container repositories' do
before do
......
......@@ -340,4 +340,31 @@ describe GroupsHelper do
end
end
end
describe '#can_update_default_branch_protection?' do
let(:current_user) { create(:user) }
let(:group) { create(:group) }
subject { helper.can_update_default_branch_protection?(group) }
before do
allow(helper).to receive(:current_user) { current_user }
end
context 'for users who can update default branch protection of the group' do
before do
allow(helper).to receive(:can?).with(current_user, :update_default_branch_protection, group) { true }
end
it { is_expected.to be_truthy }
end
context 'for users who cannot update default branch protection of the group' do
before do
allow(helper).to receive(:can?).with(current_user, :update_default_branch_protection, group) { false }
end
it { is_expected.to be_falsey }
end
end
end
......@@ -80,6 +80,34 @@ describe GlobalPolicy do
end
end
describe 'create group' do
context 'when user has the ability to create group' do
let(:current_user) { create(:user, can_create_group: true) }
it { is_expected.to be_allowed(:create_group) }
end
context 'when user does not have the ability to create group' do
let(:current_user) { create(:user, can_create_group: false) }
it { is_expected.not_to be_allowed(:create_group) }
end
end
describe 'create group with default branch protection' do
context 'when user has the ability to create group' do
let(:current_user) { create(:user, can_create_group: true) }
it { is_expected.to be_allowed(:create_group_with_default_branch_protection) }
end
context 'when user does not have the ability to create group' do
let(:current_user) { create(:user, can_create_group: false) }
it { is_expected.not_to be_allowed(:create_group_with_default_branch_protection) }
end
end
describe 'custom attributes' do
context 'regular user' do
it { is_expected.not_to be_allowed(:read_custom_attribute) }
......
......@@ -642,6 +642,35 @@ describe API::Groups do
expect(json_response['default_branch_protection']).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
end
context 'updating the `default_branch_protection` attribute' do
subject do
put api("/groups/#{group1.id}", user1), params: { default_branch_protection: ::Gitlab::Access::PROTECTION_NONE }
end
context 'for users who have the ability to update default_branch_protection' do
it 'updates the attribute' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_NONE)
end
end
context 'for users who does not have the ability to update default_branch_protection`' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user1, :update_default_branch_protection, group1) { false }
end
it 'does not update the attribute' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['default_branch_protection']).not_to eq(Gitlab::Access::PROTECTION_NONE)
end
end
end
context 'malicious group name' do
subject { put api("/groups/#{group1.id}", user1), params: { name: "<SCRIPT>alert('DOUBLE-ATTACK!')</SCRIPT>" } }
......@@ -1111,6 +1140,35 @@ describe API::Groups do
it { expect { subject }.not_to change { Group.count } }
end
context 'when creating a group with `default_branch_protection` attribute' do
let(:params) { attributes_for_group_api default_branch_protection: Gitlab::Access::PROTECTION_NONE }
subject { post api("/groups", user3), params: params }
context 'for users who have the ability to create a group with `default_branch_protection`' do
it 'creates group with the specified branch protection level' do
subject
expect(response).to have_gitlab_http_status(:created)
expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_NONE)
end
end
context 'for users who do not have the ability to create a group with `default_branch_protection`' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user3, :create_group_with_default_branch_protection) { false }
end
it 'does not create the group with the specified branch protection level' do
subject
expect(response).to have_gitlab_http_status(:created)
expect(json_response['default_branch_protection']).not_to eq(Gitlab::Access::PROTECTION_NONE)
end
end
end
it "does not create group, duplicate" do
post api("/groups", user3), params: { name: 'Duplicate Test', path: group2.path }
......
......@@ -24,6 +24,32 @@ describe Groups::CreateService, '#execute' do
end
end
context 'creating a group with `default_branch_protection` attribute' do
let(:params) { group_params.merge(default_branch_protection: Gitlab::Access::PROTECTION_NONE) }
let(:service) { described_class.new(user, params) }
let(:created_group) { service.execute }
before do
end
context 'for users who have the ability to create a group with `default_branch_protection`' do
it 'creates group with the specified branch protection level' do
expect(created_group.default_branch_protection).to eq(Gitlab::Access::PROTECTION_NONE)
end
end
context 'for users who do not have the ability to create a group with `default_branch_protection`' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :create_group_with_default_branch_protection) { false }
end
it 'does not create the group with the specified branch protection level' do
expect(created_group.default_branch_protection).not_to eq(Gitlab::Access::PROTECTION_NONE)
end
end
end
describe 'creating a top level group' do
let(:service) { described_class.new(user, group_params) }
......
......@@ -148,6 +148,28 @@ describe Groups::UpdateService do
end
end
context 'updating default_branch_protection' do
let(:service) do
described_class.new(internal_group, user, default_branch_protection: Gitlab::Access::PROTECTION_NONE)
end
context 'for users who have the ability to update default_branch_protection' do
before do
internal_group.add_owner(user)
end
it 'updates the attribute' do
expect { service.execute }.to change { internal_group.default_branch_protection }.to(Gitlab::Access::PROTECTION_NONE)
end
end
context 'for users who do not have the ability to update default_branch_protection' do
it 'does not update the attribute' do
expect { service.execute }.not_to change { internal_group.default_branch_protection }
end
end
end
context 'rename group' do
let!(:service) { described_class.new(internal_group, user, path: SecureRandom.hex) }
......
......@@ -35,7 +35,8 @@ RSpec.shared_context 'GroupPolicy context' do
:change_visibility_level,
:set_note_created_at,
:create_subgroup,
:read_statistics
:read_statistics,
:update_default_branch_protection
].compact
end
......
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