Commit e65b8416 authored by Terri Chu's avatar Terri Chu Committed by Mark Chao

Backend support for search issue filtering by confidential

Pass confidential filter through to search when backed
by PostgreSQL or Elasticsearch.
parent 759f6a3f
# frozen_string_literal: true
module SearchHelper
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :state].freeze
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :state, :confidential].freeze
def search_autocomplete_opts(term)
return unless current_user
......
......@@ -14,7 +14,7 @@ module Search
Gitlab::SearchResults.new(current_user,
params[:search],
projects,
filters: { state: params[:state] })
filters: { state: params[:state], confidential: params[:confidential] })
end
def projects
......
......@@ -16,7 +16,7 @@ module Search
params[:search],
projects,
group: group,
filters: { state: params[:state] }
filters: { state: params[:state], confidential: params[:confidential] }
)
end
......
......@@ -13,7 +13,8 @@ module Search
params[:search],
project: project,
repository_ref: params[:repository_ref],
filters: { state: params[:state] })
filters: { confidential: params[:confidential], state: params[:state] }
)
end
def scope
......
......@@ -16,7 +16,7 @@ module EE
params[:search],
elastic_projects,
public_and_internal_projects: elastic_global,
filters: { state: params[:state] }
filters: { confidential: params[:confidential], state: params[:state] }
)
end
......
......@@ -30,7 +30,7 @@ module EE
elastic_projects,
group: group,
public_and_internal_projects: elastic_global,
filters: { state: params[:state] }
filters: { confidential: params[:confidential], state: params[:state] }
)
end
end
......
......@@ -15,7 +15,7 @@ module EE
params[:search],
project: project,
repository_ref: repository_ref,
filters: { state: params[:state] }
filters: { confidential: params[:confidential], state: params[:state] }
)
end
......
......@@ -33,6 +33,11 @@ module Elastic
def confidentiality_filter(query_hash, options)
current_user = options[:current_user]
project_ids = options[:project_ids]
confidential_filter = options[:confidential]
if Feature.enabled?(:search_filter_by_confidential) && confidential_filter.present? && %w(yes no).include?(confidential_filter)
query_hash[:query][:bool][:filter] << { term: { confidential: confidential_filter == 'yes' } }
end
return query_hash if current_user&.can_read_all_resources?
......
......@@ -197,8 +197,7 @@ module Gitlab
def issues
strong_memoize(:issues) do
options = base_options
options[:state] = filters[:state] if filters.key?(:state)
options = base_options.merge(filters.slice(:confidential, :state))
Issue.elastic_search(query, options: options)
end
......
......@@ -19,15 +19,19 @@ RSpec.describe Gitlab::Elastic::GroupSearchResults, :elastic do
let!(:project) { create(:project, :public, group: group) }
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
let!(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
let(:query) { 'foo' }
let(:scope) { 'issues' }
include_examples 'search results filtered by state' do
before do
ensure_elasticsearch_index!
end
before do
project.add_developer(user)
ensure_elasticsearch_index!
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
context 'merge_requests search', :sidekiq_inline do
......
......@@ -70,32 +70,35 @@ RSpec.describe Gitlab::Elastic::ProjectSearchResults, :elastic do
end
context 'filtering' do
let!(:project) { create(:project, :public) }
let(:query) { 'foo' }
context 'issues' do
let!(:project) { create(:project, :public) }
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
let(:query) { 'foo' }
let!(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
let(:scope) { 'issues' }
include_examples 'search results filtered by state' do
before do
ensure_elasticsearch_index!
end
before do
project.add_developer(user)
ensure_elasticsearch_index!
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
context 'merge_requests' do
let!(:project) { create(:project, :public) }
let!(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') }
let!(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
let(:query) { 'foo' }
let(:scope) { 'merge_requests' }
include_examples 'search results filtered by state' do
before do
ensure_elasticsearch_index!
end
before do
ensure_elasticsearch_index!
end
include_examples 'search results filtered by state'
end
end
end
......
......@@ -171,15 +171,19 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
let!(:project) { create(:project, :public) }
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
let!(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
let(:scope) { 'issues' }
let(:results) { described_class.new(user, 'foo', [project], filters: filters) }
let(:results) { described_class.new(user, 'foo', [project.id], filters: filters) }
include_examples 'search results filtered by state' do
before do
ensure_elasticsearch_index!
end
before do
project.add_developer(user)
ensure_elasticsearch_index!
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
end
......
......@@ -193,6 +193,10 @@ module Gitlab
end
params[:state] = filters[:state] if filters.key?(:state)
if Feature.enabled?(:search_filter_by_confidential) && filters.key?(:confidential) && %w(yes no).include?(filters[:confidential])
params[:confidential] = filters[:confidential] == 'yes'
end
end
end
......
......@@ -17,10 +17,17 @@ RSpec.describe Gitlab::GroupSearchResults do
describe 'issues search' do
let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let_it_be(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
let(:query) { 'foo' }
let(:scope) { 'issues' }
before do
project.add_developer(user)
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
describe 'merge_requests search' do
......
......@@ -265,9 +265,15 @@ RSpec.describe Gitlab::ProjectSearchResults do
let_it_be(:project) { create(:project, :public) }
let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
let_it_be(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
let(:query) { 'foo' }
before do
project.add_developer(user)
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
end
......
......@@ -181,8 +181,10 @@ RSpec.describe Gitlab::SearchResults do
let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo open') }
let_it_be(:confidential_result) { create(:issue, :confidential, project: project, title: 'foo confidential') }
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end
end
......
# frozen_string_literal: true
RSpec.shared_examples 'search results filtered by confidential' do
context 'filter not provided (all behavior)' do
let(:filters) { {} }
context 'when Feature search_filter_by_confidential enabled' do
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
context 'when Feature search_filter_by_confidential not enabled' do
before do
stub_feature_flags(search_filter_by_confidential: false)
end
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
end
context 'confidential filter' do
let(:filters) { { confidential: 'yes' } }
context 'when Feature search_filter_by_confidential enabled' do
it 'returns only confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).not_to include opened_result
end
end
context 'when Feature search_filter_by_confidential not enabled' do
before do
stub_feature_flags(search_filter_by_confidential: false)
end
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
end
context 'not confidential filter' do
let(:filters) { { confidential: 'no' } }
context 'when Feature search_filter_by_confidential enabled' do
it 'returns not confidential results', :aggregate_failures do
expect(results.objects('issues')).not_to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
context 'when Feature search_filter_by_confidential not enabled' do
before do
stub_feature_flags(search_filter_by_confidential: false)
end
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
end
context 'unsupported filter' do
let(:filters) { { confidential: 'goodbye' } }
context 'when Feature search_filter_by_confidential enabled' do
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
end
context 'when Feature search_filter_by_confidential not enabled' do
before do
stub_feature_flags(search_filter_by_confidential: false)
end
it 'returns confidential and not confidential results', :aggregate_failures do
expect(results.objects('issues')).to include confidential_result
expect(results.objects('issues')).to include opened_result
end
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