diff options
author | Robert Speicher <rspeicher@gmail.com> | 2016-07-13 13:57:30 -0500 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2016-07-13 13:57:30 -0500 |
commit | 530f5158e297f3cde27f3566cfe13bad74ba3b50 (patch) | |
tree | 270507d396bacdae8a4aa3489edfff0f47b718ca /lib/gitlab | |
parent | 9b0ef1559f78e58b398e428763ff97dfdc53e186 (diff) | |
download | gitlab-ce-530f5158e297f3cde27f3566cfe13bad74ba3b50.tar.gz |
Revert "Merge branch '18193-developers-can-merge' into 'master'
"
This reverts commit 9ca633eb4c62231e4ddff5466c723cf8e2bdb25d, reversing
changes made to fb229bbf7970ba908962b837b270adf56f14098f.
Diffstat (limited to 'lib/gitlab')
-rw-r--r-- | lib/gitlab/access.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/checks/change_access.rb | 96 | ||||
-rw-r--r-- | lib/gitlab/checks/force_push.rb | 17 | ||||
-rw-r--r-- | lib/gitlab/checks/matching_merge_request.rb | 18 | ||||
-rw-r--r-- | lib/gitlab/force_push_check.rb | 15 | ||||
-rw-r--r-- | lib/gitlab/git_access.rb | 143 | ||||
-rw-r--r-- | lib/gitlab/git_access_wiki.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/user_access.rb | 48 |
8 files changed, 135 insertions, 212 deletions
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index de41ea415a6..831f1e635ba 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -14,10 +14,9 @@ module Gitlab OWNER = 50 # Branch protection settings - PROTECTION_NONE = 0 - PROTECTION_DEV_CAN_PUSH = 1 - PROTECTION_FULL = 2 - PROTECTION_DEV_CAN_MERGE = 3 + PROTECTION_NONE = 0 + PROTECTION_DEV_CAN_PUSH = 1 + PROTECTION_FULL = 2 class << self def values @@ -55,7 +54,6 @@ module Gitlab def protection_options { "Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE, - "Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch." => PROTECTION_DEV_CAN_MERGE, "Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH, "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL, } diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb deleted file mode 100644 index 5551fac4b8b..00000000000 --- a/lib/gitlab/checks/change_access.rb +++ /dev/null @@ -1,96 +0,0 @@ -module Gitlab - module Checks - class ChangeAccess - attr_reader :user_access, :project - - def initialize(change, user_access:, project:) - @oldrev, @newrev, @ref = change.split(' ') - @branch_name = branch_name(@ref) - @user_access = user_access - @project = project - end - - def exec - error = protected_branch_checks || tag_checks || push_checks - - if error - GitAccessStatus.new(false, error) - else - GitAccessStatus.new(true) - end - end - - protected - - def protected_branch_checks - return unless project.protected_branch?(@branch_name) - - if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches) - return "You are not allowed to force push code to a protected branch on this project." - elsif Gitlab::Git.blank_ref?(@newrev) && user_access.cannot_do_action?(:remove_protected_branches) - return "You are not allowed to delete protected branches from this project." - end - - if matching_merge_request? - if user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name) - return - else - "You are not allowed to merge code into protected branches on this project." - end - else - if user_access.can_push_to_branch?(@branch_name) - return - else - "You are not allowed to push code to protected branches on this project." - end - end - end - - def tag_checks - tag_ref = tag_name(@ref) - - if tag_ref && protected_tag?(tag_ref) && user_access.cannot_do_action?(:admin_project) - "You are not allowed to change existing tags on this project." - end - end - - def push_checks - if user_access.cannot_do_action?(:push_code) - "You are not allowed to push code to this project." - end - end - - private - - def protected_tag?(tag_name) - project.repository.tag_exists?(tag_name) - end - - def forced_push? - Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev) - end - - def matching_merge_request? - Checks::MatchingMergeRequest.new(@newrev, @branch_name, @project).match? - end - - def branch_name(ref) - ref = @ref.to_s - if Gitlab::Git.branch_ref?(ref) - Gitlab::Git.ref_name(ref) - else - nil - end - end - - def tag_name(ref) - ref = @ref.to_s - if Gitlab::Git.tag_ref?(ref) - Gitlab::Git.ref_name(ref) - else - nil - end - end - end - end -end diff --git a/lib/gitlab/checks/force_push.rb b/lib/gitlab/checks/force_push.rb deleted file mode 100644 index dfa83a0eab3..00000000000 --- a/lib/gitlab/checks/force_push.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Gitlab - module Checks - class ForcePush - def self.force_push?(project, oldrev, newrev) - return false if project.empty_repo? - - # Created or deleted branch - if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev) - false - else - missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})) - missed_refs.split("\n").size > 0 - end - end - end - end -end diff --git a/lib/gitlab/checks/matching_merge_request.rb b/lib/gitlab/checks/matching_merge_request.rb deleted file mode 100644 index 849848515da..00000000000 --- a/lib/gitlab/checks/matching_merge_request.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Gitlab - module Checks - class MatchingMergeRequest - def initialize(newrev, branch_name, project) - @newrev = newrev - @branch_name = branch_name - @project = project - end - - def match? - @project.merge_requests - .with_state(:locked) - .where(in_progress_merge_commit_sha: @newrev, target_branch: @branch_name) - .exists? - end - end - end -end diff --git a/lib/gitlab/force_push_check.rb b/lib/gitlab/force_push_check.rb new file mode 100644 index 00000000000..93c6a5bb7f5 --- /dev/null +++ b/lib/gitlab/force_push_check.rb @@ -0,0 +1,15 @@ +module Gitlab + class ForcePushCheck + def self.force_push?(project, oldrev, newrev) + return false if project.empty_repo? + + # Created or deleted branch + if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev) + false + else + missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})) + missed_refs.split("\n").size > 0 + end + end + end +end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 308f23bc9bc..7679c7e4bb8 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -1,17 +1,52 @@ -# Check a user's access to perform a git action. All public methods in this -# class return an instance of `GitlabAccessStatus` module Gitlab class GitAccess DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive } PUSH_COMMANDS = %w{ git-receive-pack } - attr_reader :actor, :project, :protocol, :user_access + attr_reader :actor, :project, :protocol def initialize(actor, project, protocol) @actor = actor @project = project @protocol = protocol - @user_access = UserAccess.new(user, project: project) + end + + def user + return @user if defined?(@user) + + @user = + case actor + when User + actor + when DeployKey + nil + when Key + actor.user + end + end + + def deploy_key + actor if actor.is_a?(DeployKey) + end + + def can_push_to_branch?(ref) + return false unless user + + if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref) + user.can?(:push_code_to_protected_branches, project) + else + user.can?(:push_code, project) + end + end + + def can_read_project? + if user + user.can?(:read_project, project) + elsif deploy_key + deploy_key.projects.include?(project) + else + false + end end def check(cmd, changes = nil) @@ -21,11 +56,11 @@ module Gitlab return build_status_object(false, "No user or key was provided.") end - if user && !user_access.allowed? + if user && !user_allowed? return build_status_object(false, "Your account has been blocked.") end - unless project && (user_access.can_read_project? || deploy_key_can_read_project?) + unless project && can_read_project? return build_status_object(false, 'The project you were looking for could not be found.') end @@ -60,7 +95,7 @@ module Gitlab end def user_download_access_check - unless user_access.can_do_action?(:download_code) + unless user.can?(:download_code, project) return build_status_object(false, "You are not allowed to download code from this project.") end @@ -90,8 +125,46 @@ module Gitlab build_status_object(true) end + def can_user_do_action?(action) + @permission_cache ||= {} + @permission_cache[action] ||= user.can?(action, project) + end + def change_access_check(change) - Checks::ChangeAccess.new(change, user_access: user_access, project: project).exec + oldrev, newrev, ref = change.split(' ') + + action = + if project.protected_branch?(branch_name(ref)) + protected_branch_action(oldrev, newrev, branch_name(ref)) + elsif (tag_ref = tag_name(ref)) && protected_tag?(tag_ref) + # Prevent any changes to existing git tag unless user has permissions + :admin_project + else + :push_code + end + + unless can_user_do_action?(action) + status = + case action + when :force_push_code_to_protected_branches + build_status_object(false, "You are not allowed to force push code to a protected branch on this project.") + when :remove_protected_branches + build_status_object(false, "You are not allowed to deleted protected branches from this project.") + when :push_code_to_protected_branches + build_status_object(false, "You are not allowed to push code to protected branches on this project.") + when :admin_project + build_status_object(false, "You are not allowed to change existing tags on this project.") + else # :push_code + build_status_object(false, "You are not allowed to push code to this project.") + end + return status + end + + build_status_object(true) + end + + def forced_push?(oldrev, newrev) + Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev) end def protocol_allowed? @@ -100,38 +173,48 @@ module Gitlab private - def matching_merge_request?(newrev, branch_name) - Checks::MatchingMergeRequest.new(newrev, branch_name, project).match? + def protected_branch_action(oldrev, newrev, branch_name) + # we dont allow force push to protected branch + if forced_push?(oldrev, newrev) + :force_push_code_to_protected_branches + elsif Gitlab::Git.blank_ref?(newrev) + # and we dont allow remove of protected branch + :remove_protected_branches + elsif project.developers_can_push_to_protected_branch?(branch_name) + :push_code + else + :push_code_to_protected_branches + end end - def deploy_key - actor if actor.is_a?(DeployKey) + def protected_tag?(tag_name) + project.repository.tag_exists?(tag_name) end - def deploy_key_can_read_project? - if deploy_key - deploy_key.projects.include?(project) + def user_allowed? + Gitlab::UserAccess.allowed?(user) + end + + def branch_name(ref) + ref = ref.to_s + if Gitlab::Git.branch_ref?(ref) + Gitlab::Git.ref_name(ref) else - false + nil end end - protected - - def user - return @user if defined?(@user) - - @user = - case actor - when User - actor - when DeployKey - nil - when Key - actor.user - end + def tag_name(ref) + ref = ref.to_s + if Gitlab::Git.tag_ref?(ref) + Gitlab::Git.ref_name(ref) + else + nil + end end + protected + def build_status_object(status, message = '') GitAccessStatus.new(status, message) end diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb index f71d3575909..8672cbc0ec4 100644 --- a/lib/gitlab/git_access_wiki.rb +++ b/lib/gitlab/git_access_wiki.rb @@ -1,7 +1,7 @@ module Gitlab class GitAccessWiki < GitAccess def change_access_check(change) - if user_access.can_do_action?(:create_wiki) + if user.can?(:create_wiki, project) build_status_object(true) else build_status_object(false, "You are not allowed to write to this project's wiki.") diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb index c0f85e9b3a8..d1b42c1f9b9 100644 --- a/lib/gitlab/user_access.rb +++ b/lib/gitlab/user_access.rb @@ -1,23 +1,7 @@ module Gitlab - class UserAccess - attr_reader :user, :project - - def initialize(user, project: nil) - @user = user - @project = project - end - - def can_do_action?(action) - @permission_cache ||= {} - @permission_cache[action] ||= user.can?(action, project) - end - - def cannot_do_action?(action) - !can_do_action?(action) - end - - def allowed? - return false if user.blank? || user.blocked? + module UserAccess + def self.allowed?(user) + return false if user.blocked? if user.requires_ldap_check? && user.try_obtain_ldap_lease return false unless Gitlab::LDAP::Access.allowed?(user) @@ -25,31 +9,5 @@ module Gitlab true end - - def can_push_to_branch?(ref) - return false unless user - - if project.protected_branch?(ref) && !project.developers_can_push_to_protected_branch?(ref) - user.can?(:push_code_to_protected_branches, project) - else - user.can?(:push_code, project) - end - end - - def can_merge_to_branch?(ref) - return false unless user - - if project.protected_branch?(ref) && !project.developers_can_merge_to_protected_branch?(ref) - user.can?(:push_code_to_protected_branches, project) - else - user.can?(:push_code, project) - end - end - - def can_read_project? - return false unless user - - user.can?(:read_project, project) - end end end |