summaryrefslogtreecommitdiff
path: root/lib/gitlab/git_access.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/git_access.rb')
-rw-r--r--lib/gitlab/git_access.rb93
1 files changed, 56 insertions, 37 deletions
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index b768a99a0e8..875f8d8b3a3 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -5,61 +5,77 @@ module Gitlab
attr_reader :params, :project, :git_cmd, :user
- def allowed?(actor, cmd, project, changes = nil)
+ def check(actor, cmd, project, changes = nil)
case cmd
when *DOWNLOAD_COMMANDS
+ download_access_check(actor, project)
+ when *PUSH_COMMANDS
if actor.is_a? User
- download_allowed?(actor, project)
+ push_access_check(actor, project, changes)
elsif actor.is_a? DeployKey
- actor.projects.include?(project)
+ return build_status_object(false, "Deploy key not allowed to push")
elsif actor.is_a? Key
- download_allowed?(actor.user, project)
+ push_access_check(actor.user, project, changes)
else
raise 'Wrong actor'
end
- when *PUSH_COMMANDS
- if actor.is_a? User
- push_allowed?(actor, project, changes)
- elsif actor.is_a? DeployKey
- # Deploy key not allowed to push
- return false
- elsif actor.is_a? Key
- push_allowed?(actor.user, project, changes)
+ else
+ return build_status_object(false, "Wrong command")
+ end
+ end
+
+ def download_access_check(actor, project)
+ if actor.is_a?(User)
+ user_download_access_check(actor, project)
+ elsif actor.is_a?(DeployKey)
+ if actor.projects.include?(project)
+ build_status_object(true)
else
- raise 'Wrong actor'
+ build_status_object(false, "Deploy key not allowed to access this project")
end
+ elsif actor.is_a? Key
+ user_download_access_check(actor.user, project)
else
- false
+ raise 'Wrong actor'
end
end
- def download_allowed?(user, project)
- if user && user_allowed?(user)
- user.can?(:download_code, project)
+ def user_download_access_check(user, project)
+ if user && user_allowed?(user) && user.can?(:download_code, project)
+ build_status_object(true)
else
- false
+ build_status_object(false, "You don't have access")
end
end
- def push_allowed?(user, project, changes)
- return false unless user && user_allowed?(user)
- return true if changes.blank?
+ def push_access_check(user, project, changes)
+ unless user && user_allowed?(user)
+ return build_status_object(false, "You don't have access")
+ end
+
+ if changes.blank?
+ return build_status_object(true)
+ end
+
+ unless project.repository.exists?
+ return build_status_object(false, "Repository does not exist")
+ end
changes = changes.lines if changes.kind_of?(String)
# Iterate over all changes to find if user allowed all of them to be applied
changes.each do |change|
- unless change_allowed?(user, project, change)
+ status = change_access_check(user, project, change)
+ unless status.allowed?
# If user does not have access to make at least one change - cancel all push
- return false
+ return status
end
end
- # If user has access to make all changes
- true
+ return build_status_object(true)
end
- def change_allowed?(user, project, change)
+ def change_access_check(user, project, change)
oldrev, newrev, ref = change.split(' ')
action = if project.protected_branch?(branch_name(ref))
@@ -67,30 +83,27 @@ module Gitlab
if forced_push?(project, oldrev, newrev)
:force_push_code_to_protected_branches
# and we dont allow remove of protected branch
- elsif newrev =~ /0000000/
+ elsif newrev == Gitlab::Git::BLANK_SHA
:remove_protected_branches
else
:push_code_to_protected_branches
end
- elsif project.repository && project.repository.tag_names.include?(tag_name(ref))
+ elsif project.repository.tag_names.include?(tag_name(ref))
# Prevent any changes to existing git tag unless user has permissions
:admin_project
else
:push_code
end
- user.can?(action, project)
+ if user.can?(action, project)
+ build_status_object(true)
+ else
+ build_status_object(false, "You don't have permission")
+ end
end
def forced_push?(project, oldrev, newrev)
- return false if project.empty_repo?
-
- if oldrev !~ /00000000/ && newrev !~ /00000000/
- missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
- missed_refs.split("\n").size > 0
- else
- false
- end
+ Gitlab::ForcePushCheck.force_push?(project, oldrev, newrev)
end
private
@@ -116,5 +129,11 @@ module Gitlab
nil
end
end
+
+ protected
+
+ def build_status_object(status, message = '')
+ GitAccessStatus.new(status, message)
+ end
end
end