Skip to content
Snippets Groups Projects
Commit ae6adf16 authored by DJ Mountney's avatar DJ Mountney
Browse files

Merge branch '25934-project-snippet-vis' into 'security-9-2'

Fix visibility when referencing snippets

See merge request !2101
parent e1d1a524
No related branches found
No related tags found
No related merge requests found
Showing
with 206 additions and 18 deletions
class ProjectSnippetPolicy < BasePolicy
def rules
# We have to check both project feature visibility and a snippet visibility and take the stricter one
# This will be simplified - check https://gitlab.com/gitlab-org/gitlab-ce/issues/27573
return unless @subject.project.feature_available?(:snippets, @user)
return unless Ability.allowed?(@user, :read_project, @subject.project)
can! :read_project_snippet if @subject.public?
return unless @user
 
Loading
Loading
Loading
Loading
@@ -62,7 +62,7 @@ module Banzai
 
nodes.select do |node|
if node.has_attribute?(project_attr)
can_read_reference?(user, projects[node])
can_read_reference?(user, projects[node], node)
else
true
end
Loading
Loading
@@ -231,7 +231,7 @@ module Banzai
# see reference comments.
# Override this method on subclasses
# to check if user can read resource
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
raise NotImplementedError
end
 
Loading
Loading
Loading
Loading
@@ -32,7 +32,7 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :download_code, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -36,7 +36,7 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :download_code, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -23,7 +23,7 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :read_issue, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -9,7 +9,7 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :read_label, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -40,6 +40,10 @@ module Banzai
self.class.data_attribute
)
end
def can_read_reference?(user, ref_project, node)
can?(user, :read_merge_request, ref_project)
end
end
end
end
Loading
Loading
@@ -9,7 +9,7 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :read_milestone, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -9,8 +9,8 @@ module Banzai
 
private
 
def can_read_reference?(user, ref_project)
can?(user, :read_project_snippet, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :read_project_snippet, referenced_by([node]).first)
end
end
end
Loading
Loading
Loading
Loading
@@ -103,7 +103,7 @@ module Banzai
flat_map { |p| p.team.members.to_a }
end
 
def can_read_reference?(user, ref_project)
def can_read_reference?(user, ref_project, node)
can?(user, :read_project, ref_project)
end
end
Loading
Loading
Loading
Loading
@@ -30,7 +30,7 @@ describe Banzai::ReferenceParser::BaseParser, lib: true do
it 'checks if user can read the resource' do
link['data-project'] = project.id.to_s
 
expect(subject).to receive(:can_read_reference?).with(user, project)
expect(subject).to receive(:can_read_reference?).with(user, project, link)
 
subject.nodes_visible_to_user(user, [link])
end
Loading
Loading
Loading
Loading
@@ -4,20 +4,199 @@ describe Banzai::ReferenceParser::SnippetParser, lib: true do
include ReferenceParserHelpers
 
let(:project) { create(:empty_project, :public) }
let(:user) { create(:user) }
let(:snippet) { create(:snippet, project: project) }
let(:external_user) { create(:user, :external) }
let(:project_member) { create(:user) }
subject { described_class.new(project, user) }
let(:link) { empty_html_link }
 
def visible_references(snippet_visibility, user = nil)
snippet = create(:project_snippet, snippet_visibility, project: project)
link['data-project'] = project.id.to_s
link['data-snippet'] = snippet.id.to_s
subject.nodes_visible_to_user(user, [link])
end
before do
project.add_user(project_member, :developer)
end
describe '#nodes_visible_to_user' do
context 'when the link has a data-issue attribute' do
before { link['data-snippet'] = snippet.id.to_s }
context 'when a project is public and the snippets feature is enabled for everyone' do
before do
project.project_feature.update_attribute(:snippets_access_level, ProjectFeature::ENABLED)
end
it 'creates a reference for guest for a public snippet' do
expect(visible_references(:public)).to eq([link])
end
it 'creates a reference for a regular user for a public snippet' do
expect(visible_references(:public, user)).to eq([link])
end
it 'creates a reference for a regular user for an internal snippet' do
expect(visible_references(:internal, user)).to eq([link])
end
it 'does not create a reference for an external user for an internal snippet' do
expect(visible_references(:internal, external_user)).to be_empty
end
it 'creates a reference for a project member for a private snippet' do
expect(visible_references(:private, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for a private snippet' do
expect(visible_references(:private, user)).to be_empty
end
end
context 'when a project is public and the snippets feature is enabled for project team members' do
before do
project.project_feature.update_attribute(:snippets_access_level, ProjectFeature::PRIVATE)
end
it 'creates a reference for a project member for a public snippet' do
expect(visible_references(:public, project_member)).to eq([link])
end
it 'does not create a reference for guest for a public snippet' do
expect(visible_references(:public, nil)).to be_empty
end
it 'does not create a reference for a regular user for a public snippet' do
expect(visible_references(:public, user)).to be_empty
end
it 'creates a reference for a project member for an internal snippet' do
expect(visible_references(:internal, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for an internal snippet' do
expect(visible_references(:internal, user)).to be_empty
end
it 'creates a reference for a project member for a private snippet' do
expect(visible_references(:private, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for a private snippet' do
expect(visible_references(:private, user)).to be_empty
end
end
context 'when a project is internal and the snippets feature is enabled for everyone' do
before do
project.update_attribute(:visibility, Gitlab::VisibilityLevel::INTERNAL)
project.project_feature.update_attribute(:snippets_access_level, ProjectFeature::ENABLED)
end
it 'does not create a reference for guest for a public snippet' do
expect(visible_references(:public)).to be_empty
end
it 'does not create a reference for an external user for a public snippet' do
expect(visible_references(:public, external_user)).to be_empty
end
 
it_behaves_like "referenced feature visibility", "snippets"
it 'creates a reference for a regular user for a public snippet' do
expect(visible_references(:public, user)).to eq([link])
end
it 'creates a reference for a regular user for an internal snippet' do
expect(visible_references(:internal, user)).to eq([link])
end
it 'does not create a reference for an external user for an internal snippet' do
expect(visible_references(:internal, external_user)).to be_empty
end
it 'creates a reference for a project member for a private snippet' do
expect(visible_references(:private, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for a private snippet' do
expect(visible_references(:private, user)).to be_empty
end
end
context 'when a project is internal and the snippets feature is enabled for project team members' do
before do
project.update_attribute(:visibility, Gitlab::VisibilityLevel::INTERNAL)
project.project_feature.update_attribute(:snippets_access_level, ProjectFeature::PRIVATE)
end
it 'creates a reference for a project member for a public snippet' do
expect(visible_references(:public, project_member)).to eq([link])
end
it 'does not create a reference for guest for a public snippet' do
expect(visible_references(:public, nil)).to be_empty
end
it 'does not create reference for a regular user for a public snippet' do
expect(visible_references(:public, user)).to be_empty
end
it 'creates a reference for a project member for an internal snippet' do
expect(visible_references(:internal, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for an internal snippet' do
expect(visible_references(:internal, user)).to be_empty
end
it 'creates a reference for a project member for a private snippet' do
expect(visible_references(:private, project_member)).to eq([link])
end
it 'does not create reference for a regular user for a private snippet' do
expect(visible_references(:private, user)).to be_empty
end
end
context 'when a project is private and the snippets feature is enabled for project team members' do
before do
project.update_attribute(:visibility, Gitlab::VisibilityLevel::PRIVATE)
project.project_feature.update_attribute(:snippets_access_level, ProjectFeature::PRIVATE)
end
it 'creates a reference for a project member for a public snippet' do
expect(visible_references(:public, project_member)).to eq([link])
end
it 'does not create a reference for guest for a public snippet' do
expect(visible_references(:public, nil)).to be_empty
end
it 'does not create a reference for a regular user for a public snippet' do
expect(visible_references(:public, user)).to be_empty
end
it 'creates a reference for a project member for an internal snippet' do
expect(visible_references(:internal, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for an internal snippet' do
expect(visible_references(:internal, user)).to be_empty
end
it 'creates a reference for a project member for a private snippet' do
expect(visible_references(:private, project_member)).to eq([link])
end
it 'does not create a reference for a regular user for a private snippet' do
expect(visible_references(:private, user)).to be_empty
end
end
end
 
describe '#referenced_by' do
let(:snippet) { create(:snippet, project: project) }
describe 'when the link has a data-snippet attribute' do
context 'using an existing snippet ID' do
it 'returns an Array of snippets' do
Loading
Loading
@@ -31,7 +210,7 @@ describe Banzai::ReferenceParser::SnippetParser, lib: true do
it 'returns an empty Array' do
link['data-snippet'] = ''
 
expect(subject.referenced_by([link])).to eq([])
expect(subject.referenced_by([link])).to be_empty
end
end
end
Loading
Loading
Loading
Loading
@@ -3,7 +3,7 @@ require 'spec_helper'
describe ProjectSnippetPolicy, models: true do
let(:regular_user) { create(:user) }
let(:external_user) { create(:user, :external) }
let(:project) { create(:empty_project) }
let(:project) { create(:empty_project, :public) }
 
let(:author_permissions) do
[
Loading
Loading
@@ -107,7 +107,7 @@ describe ProjectSnippetPolicy, models: true do
end
 
context 'snippet author' do
let(:snippet) { create(:project_snippet, :private, author: regular_user) }
let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
 
subject { described_class.abilities(regular_user, snippet).to_set }
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment