Commit 2832ecfc authored by Mark Chao's avatar Mark Chao

Merge branch...

Merge branch '238314-search-ui-implement-issue-scope-results-filter-by-confidentiality-backend' into 'master'

Backend support for search issue filtering by confidential

See merge request gitlab-org/gitlab!42018
parents 17b5fb7a e65b8416
# frozen_string_literal: true # frozen_string_literal: true
module SearchHelper 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) def search_autocomplete_opts(term)
return unless current_user return unless current_user
......
...@@ -14,7 +14,7 @@ module Search ...@@ -14,7 +14,7 @@ module Search
Gitlab::SearchResults.new(current_user, Gitlab::SearchResults.new(current_user,
params[:search], params[:search],
projects, projects,
filters: { state: params[:state] }) filters: { state: params[:state], confidential: params[:confidential] })
end end
def projects def projects
......
...@@ -16,7 +16,7 @@ module Search ...@@ -16,7 +16,7 @@ module Search
params[:search], params[:search],
projects, projects,
group: group, group: group,
filters: { state: params[:state] } filters: { state: params[:state], confidential: params[:confidential] }
) )
end end
......
...@@ -13,7 +13,8 @@ module Search ...@@ -13,7 +13,8 @@ module Search
params[:search], params[:search],
project: project, project: project,
repository_ref: params[:repository_ref], repository_ref: params[:repository_ref],
filters: { state: params[:state] }) filters: { confidential: params[:confidential], state: params[:state] }
)
end end
def scope def scope
......
...@@ -16,7 +16,7 @@ module EE ...@@ -16,7 +16,7 @@ module EE
params[:search], params[:search],
elastic_projects, elastic_projects,
public_and_internal_projects: elastic_global, public_and_internal_projects: elastic_global,
filters: { state: params[:state] } filters: { confidential: params[:confidential], state: params[:state] }
) )
end end
......
...@@ -30,7 +30,7 @@ module EE ...@@ -30,7 +30,7 @@ module EE
elastic_projects, elastic_projects,
group: group, group: group,
public_and_internal_projects: elastic_global, public_and_internal_projects: elastic_global,
filters: { state: params[:state] } filters: { confidential: params[:confidential], state: params[:state] }
) )
end end
end end
......
...@@ -15,7 +15,7 @@ module EE ...@@ -15,7 +15,7 @@ module EE
params[:search], params[:search],
project: project, project: project,
repository_ref: repository_ref, repository_ref: repository_ref,
filters: { state: params[:state] } filters: { confidential: params[:confidential], state: params[:state] }
) )
end end
......
...@@ -33,6 +33,11 @@ module Elastic ...@@ -33,6 +33,11 @@ module Elastic
def confidentiality_filter(query_hash, options) def confidentiality_filter(query_hash, options)
current_user = options[:current_user] current_user = options[:current_user]
project_ids = options[:project_ids] 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? return query_hash if current_user&.can_read_all_resources?
......
...@@ -197,8 +197,7 @@ module Gitlab ...@@ -197,8 +197,7 @@ module Gitlab
def issues def issues
strong_memoize(:issues) do strong_memoize(:issues) do
options = base_options options = base_options.merge(filters.slice(:confidential, :state))
options[:state] = filters[:state] if filters.key?(:state)
Issue.elastic_search(query, options: options) Issue.elastic_search(query, options: options)
end end
......
...@@ -19,15 +19,19 @@ RSpec.describe Gitlab::Elastic::GroupSearchResults, :elastic do ...@@ -19,15 +19,19 @@ RSpec.describe Gitlab::Elastic::GroupSearchResults, :elastic do
let!(:project) { create(:project, :public, group: group) } let!(:project) { create(:project, :public, group: group) }
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') } let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') } 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(:query) { 'foo' }
let(:scope) { 'issues' } let(:scope) { 'issues' }
include_examples 'search results filtered by state' do
before do before do
project.add_developer(user)
ensure_elasticsearch_index! ensure_elasticsearch_index!
end end
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end end
context 'merge_requests search', :sidekiq_inline do context 'merge_requests search', :sidekiq_inline do
......
...@@ -70,32 +70,35 @@ RSpec.describe Gitlab::Elastic::ProjectSearchResults, :elastic do ...@@ -70,32 +70,35 @@ RSpec.describe Gitlab::Elastic::ProjectSearchResults, :elastic do
end end
context 'filtering' do context 'filtering' do
context 'issues' do
let!(:project) { create(:project, :public) } let!(:project) { create(:project, :public) }
let(:query) { 'foo' }
context 'issues' do
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') } let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') } 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' } let(:scope) { 'issues' }
include_examples 'search results filtered by state' do
before do before do
project.add_developer(user)
ensure_elasticsearch_index! ensure_elasticsearch_index!
end end
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end end
context 'merge_requests' do context 'merge_requests' do
let!(:project) { create(:project, :public) }
let!(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') } 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!(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
let(:query) { 'foo' }
let(:scope) { 'merge_requests' } let(:scope) { 'merge_requests' }
include_examples 'search results filtered by state' do
before do before do
ensure_elasticsearch_index! ensure_elasticsearch_index!
end end
end
include_examples 'search results filtered by state'
end end
end end
end end
......
...@@ -171,15 +171,19 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need ...@@ -171,15 +171,19 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
let!(:project) { create(:project, :public) } let!(:project) { create(:project, :public) }
let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') } let!(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
let!(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') } 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(: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 before do
project.add_developer(user)
ensure_elasticsearch_index! ensure_elasticsearch_index!
end end
end
include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end end
end end
......
...@@ -193,6 +193,10 @@ module Gitlab ...@@ -193,6 +193,10 @@ module Gitlab
end end
params[:state] = filters[:state] if filters.key?(:state) 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
end end
......
...@@ -17,10 +17,17 @@ RSpec.describe Gitlab::GroupSearchResults do ...@@ -17,10 +17,17 @@ RSpec.describe Gitlab::GroupSearchResults do
describe 'issues search' do describe 'issues search' do
let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') } 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(: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(:query) { 'foo' }
let(:scope) { 'issues' } let(:scope) { 'issues' }
before do
project.add_developer(user)
end
include_examples 'search results filtered by state' include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end end
describe 'merge_requests search' do describe 'merge_requests search' do
......
...@@ -265,9 +265,15 @@ RSpec.describe Gitlab::ProjectSearchResults do ...@@ -265,9 +265,15 @@ RSpec.describe Gitlab::ProjectSearchResults do
let_it_be(:project) { create(:project, :public) } let_it_be(:project) { create(:project, :public) }
let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') } 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(: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' } let(:query) { 'foo' }
before do
project.add_developer(user)
end
include_examples 'search results filtered by state' include_examples 'search results filtered by state'
include_examples 'search results filtered by confidential'
end end
end end
......
...@@ -181,8 +181,10 @@ RSpec.describe Gitlab::SearchResults do ...@@ -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(: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(: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 state'
include_examples 'search results filtered by confidential'
end end
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