Commit 04013f09 authored by Etienne Baqué's avatar Etienne Baqué

Merge branch 'id-restrict-protected-rules' into 'master'

Most restrictive protected ref rule takes precedence

See merge request gitlab-org/gitlab!52319
parents fa0da1ee 7243ec02
......@@ -40,20 +40,26 @@ module ProtectedRef
end
def protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil)
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level|
access_level.check_access(user)
end
end
def developers_can?(action, ref, protected_refs: nil)
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
all_matching_rules_allow?(ref, action: action, protected_refs: protected_refs) do |access_level|
access_level.access_level == Gitlab::Access::DEVELOPER
end
end
def access_levels_for_ref(ref, action:, protected_refs: nil)
self.matching(ref, protected_refs: protected_refs)
.flat_map(&:"#{action}_access_levels")
def all_matching_rules_allow?(ref, action:, protected_refs: nil, &block)
access_levels_groups =
self.matching(ref, protected_refs: protected_refs).map(&:"#{action}_access_levels")
return false if access_levels_groups.blank?
access_levels_groups.all? do |access_levels|
access_levels.any?(&block)
end
end
# Returns all protected refs that match the given ref name.
......
---
title: Most restrictive protected branch rule takes precedence
merge_request: 52319
author:
type: fixed
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ProtectedRef do
using RSpec::Parameterized::TableSyntax
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, maintainer_projects: [project]) }
where(:klass, :factory, :action) do
ProtectedBranch | :protected_branch | :push
ProtectedTag | :protected_tag | :create
end
with_them do
describe '#protected_ref_accessible_to?' do
subject do
klass.protected_ref_accessible_to?('release', user, project: project, action: action)
end
it 'user cannot do action if rules do not exist' do
is_expected.to be_falsy
end
context 'the ref is protected' do
let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') }
context 'all rules permit action' do
let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') }
it 'user can do action' do
is_expected.to be_truthy
end
end
context 'one of the rules forbids action' do
let!(:no_one_can) { create(factory, :"no_one_can_#{action}", project: project, name: 'release*') }
it 'user cannot do action' do
is_expected.to be_falsy
end
end
end
end
describe '#developers_can?' do
subject do
klass.developers_can?(action, 'release')
end
it 'developers cannot do action if rules do not exist' do
is_expected.to be_falsy
end
context 'the ref is protected' do
let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') }
context 'all rules permit developers to do action' do
let!(:developers_can) { create(factory, :"developers_can_#{action}", project: project, name: 'release*') }
it 'developers can do action' do
is_expected.to be_truthy
end
end
context 'one of the rules forbids developers to do action' do
let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') }
it 'developers cannot do action' do
is_expected.to be_falsy
end
end
end
end
end
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