summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Edwards-Jones <jedwardsjones@gitlab.com>2018-03-23 18:24:06 +0000
committerJames Edwards-Jones <jedwardsjones@gitlab.com>2018-03-26 01:17:27 +0100
commit1f7328f8ee6a86b1c8e50b7451450e90d78b9424 (patch)
treef40b736e3e1306df58ff40cd84bead8a0937a8e2
parent391732a2c1b04baf565c77f2788a1ec035b1d85e (diff)
downloadgitlab-ce-1f7328f8ee6a86b1c8e50b7451450e90d78b9424.tar.gz
Branch unprotection restriction starting point
Explored Policy framework to create something I can use as a starting point.
-rw-r--r--app/policies/protected_branch_policy.rb15
-rw-r--r--app/services/protected_branches/update_service.rb2
-rw-r--r--spec/policies/protected_branch_policy_spec.rb60
3 files changed, 76 insertions, 1 deletions
diff --git a/app/policies/protected_branch_policy.rb b/app/policies/protected_branch_policy.rb
new file mode 100644
index 00000000000..8d44cff1b42
--- /dev/null
+++ b/app/policies/protected_branch_policy.rb
@@ -0,0 +1,15 @@
+class ProtectedBranchPolicy < BasePolicy
+ delegate { @subject.project }
+
+ condition(:requires_admin_to_unprotect?, scope: :subject) do
+ @subject.name == 'master' && Gitlab::CurrentSettings.only_admins_can_unprotect_master_branch?
+ end
+
+ rule { can?(:admin_project) }.policy do
+ enable :update_protected_branch
+ end
+
+ rule { requires_admin_to_unprotect? & ~admin }.policy do
+ prevent :update_protected_branch
+ end
+end
diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb
index 4b3337a5c9d..95e46645374 100644
--- a/app/services/protected_branches/update_service.rb
+++ b/app/services/protected_branches/update_service.rb
@@ -1,7 +1,7 @@
module ProtectedBranches
class UpdateService < BaseService
def execute(protected_branch)
- raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :update_protected_branch, protected_branch)
protected_branch.update(params)
protected_branch
diff --git a/spec/policies/protected_branch_policy_spec.rb b/spec/policies/protected_branch_policy_spec.rb
new file mode 100644
index 00000000000..00a7d8153ae
--- /dev/null
+++ b/spec/policies/protected_branch_policy_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe ProtectedBranchPolicy do
+ let(:user) { create(:user) }
+ let(:name) { 'feature' }
+ let(:protected_branch) { create(:protected_branch, name: name) }
+ let(:project) { protected_branch.project }
+
+ subject { described_class.new(user, protected_branch) }
+
+ context 'when unprotection restriction feature is disabled' do
+ it "branches can't be updated by guests" do
+ project.add_guest(user)
+
+ is_expected.to be_disallowed(:update_protected_branch)
+ end
+
+ it 'branches can be updated via access to project settings' do
+ project.add_master(user)
+
+ is_expected.to be_allowed(:update_protected_branch)
+ end
+ end
+
+ context 'when unprotection restriction feature is enabled' do
+ before do
+ # stub_licensed_features(unprotection_restrictions: true)
+ end
+
+ context 'and unprotection is limited to admins' do #TODO: remove this is temporary exploration
+ before do
+ stub_ee_application_setting(only_admins_can_unprotect_master_branch: true)
+ end
+
+ context 'and the protection is for master' do
+ let(:name) { 'master' }
+
+ it 'project owners cannot remove protections' do
+ project.add_master(user)
+
+ is_expected.not_to be_allowed(:update_protected_branch)
+ end
+
+ it 'admins can remove protections' do
+ user.update!(admin: true)
+
+ is_expected.to be_allowed(:update_protected_branch)
+ end
+ end
+
+ context "and the protection isn't for master" do
+ it 'project owners can remove protections' do
+ project.add_master(user)
+
+ is_expected.to be_allowed(:update_protected_branch)
+ end
+ end
+ end
+ end
+end