diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 3f702b0af976fd95206c7d5e9d1de0ac6c97fd6f..912f9eb5b6b0be6e5fa920208860073ecb18e2fc 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -233,13 +233,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def allowed_to_push_code?(project, branch) - action = if project.protected_branch?(branch) - :push_code_to_protected_branches - else - :push_code - end - - can?(current_user, action, project) + ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, branch) end def merge_request_params diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index 2ec2cc961578c88d850cbf210114788c41c39f9a..4a5edf6d101ee6205d2482121d0faed618f1ecb7 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -11,12 +11,7 @@ module BranchesHelper def can_push_branch?(project, branch_name) return false unless project.repository.branch_names.include?(branch_name) - action = if project.protected_branch?(branch_name) - :push_code_to_protected_branches - else - :push_code - end - - current_user.can?(action, project) + + ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, branch_name) end end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index d316213b1fd317d385cc630e66418396887b76e6..133b0dfae9b7ebcb62173c01960c0ec42dd1fbaf 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -58,11 +58,7 @@ module TreeHelper ref ||= @ref return false unless project.repository.branch_names.include?(ref) - if project.protected_branch? ref - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end + ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref) end def edit_blob_link(project, ref, path, options = {}) diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb index 82e4d7b684f11dd445566e61107fe182e267077f..b90adeef00a291054d3eb38eb1393605415bce16 100644 --- a/app/services/files/create_service.rb +++ b/app/services/files/create_service.rb @@ -3,11 +3,7 @@ require_relative "base_service" module Files class CreateService < BaseService def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end + allowed = Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref) unless allowed return error("You are not allowed to create file in this branch") diff --git a/app/services/files/delete_service.rb b/app/services/files/delete_service.rb index ff5dc6ef34c5d0c7eefb8be8b46363109c54a504..8e73c2e272751893dde0d2cb5835e3e334b227ed 100644 --- a/app/services/files/delete_service.rb +++ b/app/services/files/delete_service.rb @@ -3,11 +3,7 @@ require_relative "base_service" module Files class DeleteService < BaseService def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end + allowed = ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref) unless allowed return error("You are not allowed to push into this branch") diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb index a0f40154db02e28a32e83ac157043b08cc287748..b4986e1c5c63df74e2db3ea9543e529e57b0e30b 100644 --- a/app/services/files/update_service.rb +++ b/app/services/files/update_service.rb @@ -3,11 +3,7 @@ require_relative "base_service" module Files class UpdateService < BaseService def execute - allowed = if project.protected_branch?(ref) - can?(current_user, :push_code_to_protected_branches, project) - else - can?(current_user, :push_code, project) - end + allowed = ::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref) unless allowed return error("You are not allowed to push into this branch") diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 81038d05f121cf003ef3a2d4ef139b3f350ccf92..2a5b10c6f5248f969f585ebaffde03dd46955b5c 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -167,13 +167,9 @@ module API put ":id/merge_request/:merge_request_id/merge" do merge_request = user_project.merge_requests.find(params[:merge_request_id]) - action = if user_project.protected_branch?(merge_request.target_branch) - :push_code_to_protected_branches - else - :push_code - end + allowed = ::Gitlab::GitAccess.can_push_to_branch?(current_user, user_project, merge_request.target_branch) - if can?(current_user, action, user_project) + if allowed if merge_request.unchecked? merge_request.check_if_can_be_merged end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index d47ef61fd1177cf6ef7c676b449582e8937f6ec2..c7bf2efc6280d72d5df3144f6ebb3b96270c7f10 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -5,6 +5,15 @@ module Gitlab attr_reader :params, :project, :git_cmd, :user + def self.can_push_to_branch?(user, project, ref) + if project.protected_branch?(ref) && + !(project.developers_can_push_to_protected_branch?(ref) && project.team.developer?(user)) + user.can?(:push_code_to_protected_branches, project) + else + user.can?(:push_code, project) + end + end + def check(actor, cmd, project, changes = nil) case cmd when *DOWNLOAD_COMMANDS diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 8561fd89ba75fa812967de15a240502ff73d280b..fbcaa405f8d0ba82457caf0ff625165d708207a8 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -5,6 +5,68 @@ describe Gitlab::GitAccess do let(:project) { create(:project) } let(:user) { create(:user) } + describe 'can_push_to_branch?' do + describe 'push to none protected branch' do + it "returns true if user is a master" do + project.team << [user, :master] + Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch").should be_true + end + + it "returns true if user is a developer" do + project.team << [user, :developer] + Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch").should be_true + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch").should be_false + end + end + + describe 'push to protected branch' do + before do + @branch = create :protected_branch, project: project + end + + it "returns true if user is a master" do + project.team << [user, :master] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_true + end + + it "returns false if user is a developer" do + project.team << [user, :developer] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_false + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_false + end + end + + describe 'push to protected branch if allowed for developers' do + before do + @branch = create :protected_branch, project: project, developers_can_push: true + end + + it "returns true if user is a master" do + project.team << [user, :master] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_true + end + + it "returns true if user is a developer" do + project.team << [user, :developer] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_true + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name).should be_false + end + end + + end + describe 'download_access_check' do describe 'master permissions' do before { project.team << [user, :master] }