summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2015-04-14 16:04:37 -0400
committerRobert Speicher <rspeicher@gmail.com>2015-04-20 13:01:44 -0400
commita803cd51eb3c5b98b14eeea56ec4cc363823c2c2 (patch)
tree6193bec52d11c175b81b1fe221577fcec35da7ae
parent470b0c2508e792e93a9e7db7ba605475edfa2de4 (diff)
downloadgitlab-ce-a803cd51eb3c5b98b14eeea56ec4cc363823c2c2.tar.gz
Check for project read permissions in cross-references
-rw-r--r--lib/gitlab/markdown/cross_project_reference.rb16
-rw-r--r--spec/lib/gitlab/markdown/cross_project_reference_spec.rb45
2 files changed, 49 insertions, 12 deletions
diff --git a/lib/gitlab/markdown/cross_project_reference.rb b/lib/gitlab/markdown/cross_project_reference.rb
index 114247d0a33..b2197432caa 100644
--- a/lib/gitlab/markdown/cross_project_reference.rb
+++ b/lib/gitlab/markdown/cross_project_reference.rb
@@ -8,19 +8,29 @@ module Gitlab
# Given a cross-project reference string, get the Project record
#
- # If no valid reference is given, returns the `:project` value for the
- # current context.
+ # Defaults to value of `context[:project]` if:
+ # - No reference is given
+ # - Reference given doesn't exist
+ # - Reference given can't be read by the current user
#
# ref - String reference.
#
# Returns a Project
def project_from_ref(ref)
if ref && other = Project.find_with_namespace(ref)
- other
+ if user_can_reference_project?(other)
+ other
+ else
+ context[:project]
+ end
else
context[:project]
end
end
+
+ def user_can_reference_project?(project, user = context[:current_user])
+ user && Ability.abilities.allowed?(user, :read_project, project)
+ end
end
end
end
diff --git a/spec/lib/gitlab/markdown/cross_project_reference_spec.rb b/spec/lib/gitlab/markdown/cross_project_reference_spec.rb
index 2a3814c8499..0632c1c71e9 100644
--- a/spec/lib/gitlab/markdown/cross_project_reference_spec.rb
+++ b/spec/lib/gitlab/markdown/cross_project_reference_spec.rb
@@ -2,21 +2,48 @@ require 'spec_helper'
module Gitlab::Markdown
describe CrossProjectReference do
- include CrossProjectReference
+ # context in the html-pipeline sense, not in the rspec sense
+ let(:context) do
+ {
+ current_user: double('user'),
+ project: double('project')
+ }
+ end
+
+ include described_class
describe '#project_from_ref' do
- let(:project) { double('project') }
+ context 'when referenced project does not exist' do
+ it 'returns the project from context' do
+ expect(project_from_ref('invalid/reference')).to eq context[:project]
+ end
+ end
- it 'returns a project from a valid reference' do
- expect(Project).to receive(:find_with_namespace).with('cross-reference/foo').and_return(project)
+ context 'when referenced project exists' do
+ let(:project2) { double('referenced project') }
- expect(project_from_ref('cross-reference/foo')).to eq project
- end
+ before do
+ expect(Project).to receive(:find_with_namespace).
+ with('cross/reference').and_return(project2)
+ end
+
+ context 'and the user has permission to read it' do
+ it 'returns the referenced project' do
+ expect(self).to receive(:user_can_reference_project?).
+ with(project2).and_return(true)
+
+ expect(project_from_ref('cross/reference')).to eq project2
+ end
+ end
- it 'returns the project from context when reference is invalid' do
- expect(self).to receive(:context).and_return({project: project})
+ context 'and the user does not have permission to read it' do
+ it 'returns the project from context' do
+ expect(self).to receive(:user_can_reference_project?).
+ with(project2).and_return(false)
- expect(project_from_ref('invalid/reference')).to eq project
+ expect(project_from_ref('cross/reference')).to eq context[:project]
+ end
+ end
end
end
end