Fix Gitlab::Elastic::SearchResults

parent 8a95867b
...@@ -113,7 +113,9 @@ module Elastic ...@@ -113,7 +113,9 @@ module Elastic
def project_ids_filter(query_hash, project_ids) def project_ids_filter(query_hash, project_ids)
if project_ids if project_ids
query_hash[:query][:filtered][:filter] = { query_hash[:query][:filtered][:filter] = {
and: [ { terms: { project_id: project_ids } } ] bool: {
must: [ { terms: { project_id: project_ids } } ]
}
} }
end end
......
...@@ -34,7 +34,7 @@ module Elastic ...@@ -34,7 +34,7 @@ module Elastic
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes # We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349 # https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[:id, :iid, :title, :description, :created_at, :updated_at, :state, :project_id, :author_id].each do |attr| [:id, :iid, :title, :description, :created_at, :updated_at, :state, :project_id, :author_id, :assignee_id, :confidential].each do |attr|
data[attr.to_s] = self.send(attr) data[attr.to_s] = self.send(attr)
end end
...@@ -52,36 +52,41 @@ module Elastic ...@@ -52,36 +52,41 @@ module Elastic
end end
query_hash = project_ids_filter(query_hash, options[:project_ids]) query_hash = project_ids_filter(query_hash, options[:project_ids])
query_hash = confidentiality_filter(query_hash, options[:user]) query_hash = confidentiality_filter(query_hash, options[:current_user])
self.__elasticsearch__.search(query_hash) self.__elasticsearch__.search(query_hash)
end end
def self.confidentiality_filter(query_hash, user) def self.confidentiality_filter(query_hash, current_user)
return query_hash if user.blank? || user.admin? return query_hash if current_user.present? && current_user.admin?
query_hash[:query][:filtered][:filter] = { filter = if current_user.present?
bool: { {
should: [ bool: {
{ term: { confidential: false } }, should: [
{ bool: { { term: { confidential: false } },
must: [ { bool: {
{ term: { confidential: true } }, must: [
{ bool: { { term: { confidential: true } },
should: [ { bool: {
{ term: { author_id: user.id } }, should: [
{ term: { assignee_id: user.id } }, { term: { author_id: current_user.id } },
{ terms: { project_id: user.authorized_projects.pluck(:id) } } { term: { assignee_id: current_user.id } },
] { terms: { project_id: current_user.authorized_projects.pluck(:id) } }
} ]
} }
] }
} ]
} }
] }
} ]
} }
}
else
{ term: { confidential: false } }
end
query_hash[:query][:filtered][:filter][:bool][:must] << filter
query_hash query_hash
end end
end end
......
...@@ -3,8 +3,8 @@ module Gitlab ...@@ -3,8 +3,8 @@ module Gitlab
class ProjectSearchResults < SearchResults class ProjectSearchResults < SearchResults
attr_reader :project, :repository_ref attr_reader :project, :repository_ref
def initialize(user, project_id, query, repository_ref = nil) def initialize(current_user, project_id, query, repository_ref = nil)
@user = user @current_user = current_user
@project = Project.find(project_id) @project = Project.find(project_id)
@repository_ref = if repository_ref.present? @repository_ref = if repository_ref.present?
......
module Gitlab module Gitlab
module Elastic module Elastic
class SearchResults class SearchResults
attr_reader :user, :query attr_reader :current_user, :query
# Limit search results by passed project ids # Limit search results by passed project ids
# It allows us to search only for projects user has access to # It allows us to search only for projects user has access to
attr_reader :limit_project_ids attr_reader :limit_project_ids
def initialize(user, limit_project_ids, query) def initialize(current_user, limit_project_ids, query)
@user = user @current_user = current_user
@limit_project_ids = limit_project_ids || Project.all @limit_project_ids = limit_project_ids || Project.all
@query = Shellwords.shellescape(query) if query.present? @query = Shellwords.shellescape(query) if query.present?
end end
...@@ -64,8 +64,8 @@ module Gitlab ...@@ -64,8 +64,8 @@ module Gitlab
def issues def issues
opt = { opt = {
projects_ids: limit_project_ids, project_ids: limit_project_ids,
user: user current_user: current_user
} }
Issue.elastic_search(query, options: opt) Issue.elastic_search(query, options: opt)
......
...@@ -33,7 +33,8 @@ describe "Issue", elastic: true do ...@@ -33,7 +33,8 @@ describe "Issue", elastic: true do
issue = create :issue, project: project issue = create :issue, project: project
expected_hash = issue.attributes.extract!('id', 'iid', 'title', 'description', 'created_at', expected_hash = issue.attributes.extract!('id', 'iid', 'title', 'description', 'created_at',
'updated_at', 'state', 'project_id', 'author_id') 'updated_at', 'state', 'project_id', 'author_id',
'assignee_id', 'confidential')
expected_hash['project'] = { "id" => project.id } expected_hash['project'] = { "id" => project.id }
expected_hash['author'] = { "id" => issue.author_id } expected_hash['author'] = { "id" => issue.author_id }
......
...@@ -103,6 +103,19 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -103,6 +103,19 @@ describe Gitlab::Elastic::SearchResults, lib: true do
context 'search by term' do context 'search by term' do
let(:query) { 'issue' } let(:query) { 'issue' }
it 'should not list confidential issues for guests' do
results = described_class.new(nil, limit_project_ids, query)
issues = results.objects('issues')
expect(issues).to include issue
expect(issues).not_to include security_issue_1
expect(issues).not_to include security_issue_2
expect(issues).not_to include security_issue_3
expect(issues).not_to include security_issue_4
expect(issues).not_to include security_issue_5
expect(results.issues_count).to eq 1
end
it 'should not list confidential issues for non project members' do it 'should not list confidential issues for non project members' do
results = described_class.new(non_member, limit_project_ids, query) results = described_class.new(non_member, limit_project_ids, query)
issues = results.objects('issues') issues = results.objects('issues')
...@@ -175,6 +188,19 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -175,6 +188,19 @@ describe Gitlab::Elastic::SearchResults, lib: true do
context 'search by iid' do context 'search by iid' do
let(:query) { '#1' } let(:query) { '#1' }
it 'should not list confidential issues for guests' do
results = described_class.new(nil, limit_project_ids, query)
issues = results.objects('issues')
expect(issues).to include issue
expect(issues).not_to include security_issue_1
expect(issues).not_to include security_issue_2
expect(issues).not_to include security_issue_3
expect(issues).not_to include security_issue_4
expect(issues).not_to include security_issue_5
expect(results.issues_count).to eq 1
end
it 'should not list confidential issues for non project members' do it 'should not list confidential issues for non project members' do
results = described_class.new(non_member, limit_project_ids, query) results = described_class.new(non_member, limit_project_ids, query)
issues = results.objects('issues') issues = results.objects('issues')
...@@ -257,8 +283,8 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -257,8 +283,8 @@ describe Gitlab::Elastic::SearchResults, lib: true do
iid: 1 iid: 1
) )
@merge_request_2 = create( @merge_request_2 = create(
:merge_request, :merge_request,
:conflict, :conflict,
source_project: project_1, source_project: project_1,
target_project: project_1, target_project: project_1,
title: 'Merge Request 2', title: 'Merge Request 2',
...@@ -315,7 +341,6 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -315,7 +341,6 @@ describe Gitlab::Elastic::SearchResults, lib: true do
end end
end end
describe 'project scoping' do describe 'project scoping' do
before do before do
[Project, MergeRequest, Issue, Milestone].each do |model| [Project, MergeRequest, Issue, Milestone].each do |model|
...@@ -356,7 +381,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -356,7 +381,7 @@ describe Gitlab::Elastic::SearchResults, lib: true do
model.__elasticsearch__.refresh_index! model.__elasticsearch__.refresh_index!
end end
result = Gitlab::Elastic::SearchResults.new([project.id], 'term') result = Gitlab::Elastic::SearchResults.new(user, [project.id], 'term')
expect(result.issues_count).to eq(2) expect(result.issues_count).to eq(2)
expect(result.merge_requests_count).to eq(2) expect(result.merge_requests_count).to eq(2)
......
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