Commit bf3cc824 authored by James Edwards-Jones's avatar James Edwards-Jones

Moved Project#protected_branch? to ProtectedBranch, similar for tags

parent b8c7bef5
module BranchesHelper module BranchesHelper
def can_remove_branch?(project, branch_name) def can_remove_branch?(project, branch_name)
if project.protected_branch? branch_name if ProtectedBranch.protected?(project, branch_name)
false false
elsif branch_name == project.repository.root_ref elsif branch_name == project.repository.root_ref
false false
......
...@@ -23,6 +23,6 @@ module TagsHelper ...@@ -23,6 +23,6 @@ module TagsHelper
end end
def protected_tag?(project, tag) def protected_tag?(project, tag)
project.protected_tag?(tag.name) ProtectedTag.protected?(project, tag.name)
end end
end end
...@@ -442,7 +442,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -442,7 +442,7 @@ class MergeRequest < ActiveRecord::Base
end end
def can_remove_source_branch?(current_user) def can_remove_source_branch?(current_user)
!source_project.protected_branch?(source_branch) && !ProtectedBranch.protected?(source_project, source_branch) &&
!source_project.root_ref?(source_branch) && !source_project.root_ref?(source_branch) &&
Ability.allowed?(current_user, :push_code, source_project) && Ability.allowed?(current_user, :push_code, source_project) &&
diff_head_commit == source_branch_head diff_head_commit == source_branch_head
......
...@@ -883,20 +883,19 @@ class Project < ActiveRecord::Base ...@@ -883,20 +883,19 @@ class Project < ActiveRecord::Base
"#{url}.git" "#{url}.git"
end end
# Check if current branch name is marked as protected in the system
#TODO: Move elsewhere
def protected_branch?(branch_name)
return true if empty_repo? && default_branch_protected?
@protected_branches ||= self.protected_branches.to_a def empty_and_default_branch_protected?
ProtectedBranch.matching(branch_name, protected_refs: @protected_branches).present? empty_repo? && default_branch_protected?
end end
#TODO: Move elsewhere #TODO: Check with if this is still needed, maybe because of `.select {` in ProtectedRefsMatcher
def protected_tag?(tag_name) #Either with tests or by asking Tim
#TODO: Check if memoization necessary, find way to have it work elsewhere def protected_tags_array
@protected_tags ||= self.protected_tags.to_a @protected_tags_array ||= self.protected_tags.to_a
ProtectedTag.matching(tag_name, protected_refs: @protected_tags).present? end
def protected_branches_array
@protected_branches_array ||= self.protected_branches.to_a
end end
def user_can_push_to_empty_repo?(user) def user_can_push_to_empty_repo?(user)
...@@ -1367,6 +1366,7 @@ class Project < ActiveRecord::Base ...@@ -1367,6 +1366,7 @@ class Project < ActiveRecord::Base
"projects/#{id}/pushes_since_gc" "projects/#{id}/pushes_since_gc"
end end
#TODO: Move this and methods which depend upon it
def default_branch_protected? def default_branch_protected?
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL || current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
......
...@@ -10,4 +10,12 @@ class ProtectedBranch < ActiveRecord::Base ...@@ -10,4 +10,12 @@ class ProtectedBranch < ActiveRecord::Base
accepts_nested_attributes_for :push_access_levels accepts_nested_attributes_for :push_access_levels
accepts_nested_attributes_for :merge_access_levels accepts_nested_attributes_for :merge_access_levels
# Check if branch name is marked as protected in the system
def self.protected?(project, ref_name)
return true if project.empty_and_default_branch_protected?
protected_refs = project.protected_branches_array
self.matching(ref_name, protected_refs: protected_refs).present?
end
end end
...@@ -7,4 +7,9 @@ class ProtectedTag < ActiveRecord::Base ...@@ -7,4 +7,9 @@ class ProtectedTag < ActiveRecord::Base
validates :push_access_levels, length: { is: 1, message: "are restricted to a single instance per protected tag." } validates :push_access_levels, length: { is: 1, message: "are restricted to a single instance per protected tag." }
accepts_nested_attributes_for :push_access_levels accepts_nested_attributes_for :push_access_levels
def self.protected?(project, ref_name)
protected_refs = project.protected_tags_array
self.matching(ref_name, protected_refs: protected_refs).present?
end
end end
...@@ -11,7 +11,7 @@ class DeleteBranchService < BaseService ...@@ -11,7 +11,7 @@ class DeleteBranchService < BaseService
return error('Cannot remove HEAD branch', 405) return error('Cannot remove HEAD branch', 405)
end end
if project.protected_branch?(branch_name) if ProtectedBranch.protected?(project, branch_name)
return error('Protected branch cant be removed', 405) return error('Protected branch cant be removed', 405)
end end
......
...@@ -127,7 +127,7 @@ class GitPushService < BaseService ...@@ -127,7 +127,7 @@ class GitPushService < BaseService
project.change_head(branch_name) project.change_head(branch_name)
# Set protection on the default branch if configured # Set protection on the default branch if configured
if current_application_settings.default_branch_protection != PROTECTION_NONE && !@project.protected_branch?(@project.default_branch) if current_application_settings.default_branch_protection != PROTECTION_NONE && !ProtectedBranch.protected?(@project, @project.default_branch)
params = { params = {
name: @project.default_branch, name: @project.default_branch,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
%span.label.label-info.has-tooltip{ title: "Merged into #{@repository.root_ref}" } %span.label.label-info.has-tooltip{ title: "Merged into #{@repository.root_ref}" }
merged merged
- if @project.protected_branch? branch.name - if ProtectedBranch.protected?(@project, branch.name)
%span.label.label-success %span.label.label-success
protected protected
.controls.hidden-xs< .controls.hidden-xs<
......
...@@ -184,7 +184,7 @@ module API ...@@ -184,7 +184,7 @@ module API
end end
expose :protected do |repo_branch, options| expose :protected do |repo_branch, options|
options[:project].protected_branch?(repo_branch.name) ProtectedBranch.protected?(options[:project], repo_branch.name)
end end
expose :developers_can_push do |repo_branch, options| expose :developers_can_push do |repo_branch, options|
......
...@@ -33,7 +33,7 @@ module Gitlab ...@@ -33,7 +33,7 @@ module Gitlab
def protected_branch_checks def protected_branch_checks
return if skip_authorization return if skip_authorization
return unless @branch_name return unless @branch_name
return unless project.protected_branch?(@branch_name) return unless ProtectedBranch.protected?(project, @branch_name)
if forced_push? if forced_push?
return "You are not allowed to force push code to a protected branch on this project." return "You are not allowed to force push code to a protected branch on this project."
...@@ -85,7 +85,7 @@ module Gitlab ...@@ -85,7 +85,7 @@ module Gitlab
end end
def tag_protected? def tag_protected?
project.protected_tag?(@tag_name) ProtectedTag.protected?(project, @tag_name)
end end
def push_checks def push_checks
......
...@@ -34,7 +34,7 @@ module Gitlab ...@@ -34,7 +34,7 @@ module Gitlab
def can_push_tag?(ref) def can_push_tag?(ref)
return false unless can_access_git? return false unless can_access_git?
if project.protected_tag?(ref) if ProtectedTag.protected?(project, ref)
project.protected_tags.matching_refs_accesible_to(ref, user) project.protected_tags.matching_refs_accesible_to(ref, user)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
...@@ -44,7 +44,7 @@ module Gitlab ...@@ -44,7 +44,7 @@ module Gitlab
def can_push_to_branch?(ref) def can_push_to_branch?(ref)
return false unless can_access_git? return false unless can_access_git?
if project.protected_branch?(ref) if ProtectedBranch.protected?(project, ref)
return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user) return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
has_access = project.protected_branches.matching_refs_accesible_to(ref, user, action: :push) has_access = project.protected_branches.matching_refs_accesible_to(ref, user, action: :push)
...@@ -58,7 +58,7 @@ module Gitlab ...@@ -58,7 +58,7 @@ module Gitlab
def can_merge_to_branch?(ref) def can_merge_to_branch?(ref)
return false unless can_access_git? return false unless can_access_git?
if project.protected_branch?(ref) if ProtectedBranch.protected?(project, ref)
project.protected_branches.matching_refs_accesible_to(ref, user, action: :merge) project.protected_branches.matching_refs_accesible_to(ref, user, action: :merge)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
......
...@@ -99,7 +99,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do ...@@ -99,7 +99,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
context 'protected branches check' do context 'protected branches check' do
before do before do
allow(project).to receive(:protected_branch?).with('master').and_return(true) allow(ProtectedBranch).to receive(:protected?).with(project, 'master').and_return(true)
end end
it 'returns an error if the user is not allowed to do forced pushes to protected branches' do it 'returns an error if the user is not allowed to do forced pushes to protected branches' do
......
...@@ -441,7 +441,7 @@ describe MergeRequest, models: true do ...@@ -441,7 +441,7 @@ describe MergeRequest, models: true do
end end
it "can't be removed when its a protected branch" do it "can't be removed when its a protected branch" do
allow(subject.source_project).to receive(:protected_branch?).and_return(true) allow(ProtectedBranch).to receive(:protected?).and_return(true)
expect(subject.can_remove_source_branch?(user)).to be_falsey expect(subject.can_remove_source_branch?(user)).to be_falsey
end end
......
...@@ -1272,62 +1272,6 @@ describe Project, models: true do ...@@ -1272,62 +1272,6 @@ describe Project, models: true do
end end
end end
describe '#protected_branch?' do
context 'existing project' do
let(:project) { create(:project, :repository) }
it 'returns true when the branch matches a protected branch via direct match' do
create(:protected_branch, project: project, name: "foo")
expect(project.protected_branch?('foo')).to eq(true)
end
it 'returns true when the branch matches a protected branch via wildcard match' do
create(:protected_branch, project: project, name: "production/*")
expect(project.protected_branch?('production/some-branch')).to eq(true)
end
it 'returns false when the branch does not match a protected branch via direct match' do
expect(project.protected_branch?('foo')).to eq(false)
end
it 'returns false when the branch does not match a protected branch via wildcard match' do
create(:protected_branch, project: project, name: "production/*")
expect(project.protected_branch?('staging/some-branch')).to eq(false)
end
end
context "new project" do
let(:project) { create(:empty_project) }
it 'returns false when default_protected_branch is unprotected' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
expect(project.protected_branch?('master')).to be false
end
it 'returns false when default_protected_branch lets developers push' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
expect(project.protected_branch?('master')).to be false
end
it 'returns true when default_branch_protection does not let developers push but let developer merge branches' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
expect(project.protected_branch?('master')).to be true
end
it 'returns true when default_branch_protection is in full protection' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_FULL)
expect(project.protected_branch?('master')).to be true
end
end
end
describe '#user_can_push_to_empty_repo?' do describe '#user_can_push_to_empty_repo?' do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -137,4 +137,60 @@ describe ProtectedBranch, models: true do ...@@ -137,4 +137,60 @@ describe ProtectedBranch, models: true do
end end
end end
end end
describe '#protected?' do
context 'existing project' do
let(:project) { create(:project, :repository) }
it 'returns true when the branch matches a protected branch via direct match' do
create(:protected_branch, project: project, name: "foo")
expect(ProtectedBranch.protected?(project, 'foo')).to eq(true)
end
it 'returns true when the branch matches a protected branch via wildcard match' do
create(:protected_branch, project: project, name: "production/*")
expect(ProtectedBranch.protected?(project, 'production/some-branch')).to eq(true)
end
it 'returns false when the branch does not match a protected branch via direct match' do
expect(ProtectedBranch.protected?(project, 'foo')).to eq(false)
end
it 'returns false when the branch does not match a protected branch via wildcard match' do
create(:protected_branch, project: project, name: "production/*")
expect(ProtectedBranch.protected?(project, 'staging/some-branch')).to eq(false)
end
end
context "new project" do
let(:project) { create(:empty_project) }
it 'returns false when default_protected_branch is unprotected' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
expect(ProtectedBranch.protected?(project, 'master')).to be false
end
it 'returns false when default_protected_branch lets developers push' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_PUSH)
expect(ProtectedBranch.protected?(project, 'master')).to be false
end
it 'returns true when default_branch_protection does not let developers push but let developer merge branches' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
expect(ProtectedBranch.protected?(project, 'master')).to be true
end
it 'returns true when default_branch_protection is in full protection' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_FULL)
expect(ProtectedBranch.protected?(project, 'master')).to be true
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