Commit 53bf52f1 authored by Valery Sizov's avatar Valery Sizov

Better message for failed pushes because of git hooks

Conflicts:
	lib/gitlab/git_access.rb
	spec/lib/gitlab/git_access_spec.rb
parent a4e98f0e
......@@ -43,7 +43,7 @@ module API
return false unless actor
access.allowed?(
access.check(
actor,
params[:action],
project,
......
......@@ -80,7 +80,7 @@ module Grack
case git_cmd
when *Gitlab::GitAccess::DOWNLOAD_COMMANDS
if user
Gitlab::GitAccess.new.download_allowed?(user, project)
Gitlab::GitAccess.new.download_access_check(user, project).allowed?
elsif project.public?
# Allow clone/fetch for public projects
true
......
......@@ -5,61 +5,60 @@ 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
if actor.is_a? User
download_allowed?(actor, project)
download_access_check(actor, project)
elsif actor.is_a? DeployKey
actor.projects.include?(project)
elsif actor.is_a? Key
download_allowed?(actor.user, project)
download_access_check(actor.user, project)
else
raise 'Wrong actor'
end
when *PUSH_COMMANDS
if actor.is_a? User
push_allowed?(actor, project, changes)
push_access_check(actor, project, changes)
elsif actor.is_a? DeployKey
# Deploy key not allowed to push
return false
return build_status_object(false, "Deploy key not allowed to push")
elsif actor.is_a? Key
push_allowed?(actor.user, project, changes)
push_access_check(actor.user, project, changes)
else
raise 'Wrong actor'
end
else
false
return build_status_object(false, "Wrong command")
end
end
def download_allowed?(user, project)
if user && user_allowed?(user)
user.can?(:download_code, project)
def 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)
return build_status_object(false, "You don't have access") unless user && user_allowed?(user)
return build_status_object(true) if changes.blank?
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))
......@@ -79,7 +78,11 @@ module Gitlab
: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)
......@@ -116,5 +119,11 @@ module Gitlab
nil
end
end
protected
def build_status_object(status, message = '')
GitAccessStatus.new(status, message)
end
end
end
module Gitlab
class GitAccessStatus
attr_accessor :status, :message
alias_method :allowed?, :status
def initialize(status, message = '')
@status = status
@message = message
end
def to_json
{status: @status, message: @message}.to_json
end
end
end
\ No newline at end of file
module Gitlab
class GitAccessWiki < GitAccess
def change_allowed?(user, project, change)
user.can?(:write_wiki, project)
def change_allowed_check(user, project, change)
if user.can?(:write_wiki, project)
build_status_object(true)
else
build_status_object(false, "You don't have access")
end
end
end
end
......@@ -5,14 +5,14 @@ describe Gitlab::GitAccess do
let(:project) { create(:project) }
let(:user) { create(:user) }
describe 'download_allowed?' do
describe 'download_access_check' do
describe 'master permissions' do
before { project.team << [user, :master] }
context 'pull code' do
subject { access.download_allowed?(user, project) }
subject { access.download_access_check(user, project) }
it { should be_true }
it { subject.allowed?.should be_true }
end
end
......@@ -20,9 +20,9 @@ describe Gitlab::GitAccess do
before { project.team << [user, :guest] }
context 'pull code' do
subject { access.download_allowed?(user, project) }
subject { access.download_access_check(user, project) }
it { should be_false }
it { subject.allowed?.should be_false }
end
end
......@@ -33,22 +33,22 @@ describe Gitlab::GitAccess do
end
context 'pull code' do
subject { access.download_allowed?(user, project) }
subject { access.download_access_check(user, project) }
it { should be_false }
it { subject.allowed?.should be_false }
end
end
describe 'without acccess to project' do
context 'pull code' do
subject { access.download_allowed?(user, project) }
subject { access.download_access_check(user, project) }
it { should be_false }
it { subject.allowed?.should be_false }
end
end
end
describe 'push_allowed?' do
describe 'push_access_check' do
def protect_feature_branch
create(:protected_branch, name: 'feature', project: project)
end
......@@ -117,9 +117,9 @@ describe Gitlab::GitAccess do
permissions_matrix[role].each do |action, allowed|
context action do
subject { access.push_allowed?(user, project, changes[action]) }
subject { access.push_access_check(user, project, changes[action]) }
it { should allowed ? be_true : be_false }
it { subject.allowed?.should allowed ? be_true : be_false }
end
end
end
......
......@@ -11,9 +11,9 @@ describe Gitlab::GitAccessWiki do
project.team << [user, :developer]
end
subject { access.push_allowed?(user, project, changes) }
subject { access.push_access_check(user, project, changes) }
it { should be_true }
it { subject.should be_true }
end
def changes
......
......@@ -37,7 +37,7 @@ describe API::API, api: true do
pull(key, project)
response.status.should == 200
response.body.should == 'true'
JSON.parse(response.body)["status"].should be_true
end
end
......@@ -46,7 +46,7 @@ describe API::API, api: true do
push(key, project)
response.status.should == 200
response.body.should == 'true'
JSON.parse(response.body)["status"].should be_true
end
end
end
......@@ -61,7 +61,7 @@ describe API::API, api: true do
pull(key, project)
response.status.should == 200
response.body.should == 'false'
JSON.parse(response.body)["status"].should be_false
end
end
......@@ -70,7 +70,7 @@ describe API::API, api: true do
push(key, project)
response.status.should == 200
response.body.should == 'false'
JSON.parse(response.body)["status"].should be_false
end
end
end
......@@ -87,7 +87,7 @@ describe API::API, api: true do
pull(key, personal_project)
response.status.should == 200
response.body.should == 'false'
JSON.parse(response.body)["status"].should be_false
end
end
......@@ -96,7 +96,7 @@ describe API::API, api: true do
push(key, personal_project)
response.status.should == 200
response.body.should == 'false'
JSON.parse(response.body)["status"].should be_false
end
end
end
......@@ -114,7 +114,7 @@ describe API::API, api: true do
pull(key, project)
response.status.should == 200
response.body.should == 'true'
JSON.parse(response.body)["status"].should be_true
end
end
......@@ -123,7 +123,7 @@ describe API::API, api: true do
push(key, project)
response.status.should == 200
response.body.should == 'false'
JSON.parse(response.body)["status"].should be_false
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