Commit ede460d3 authored by Douwe Maan's avatar Douwe Maan

Merge branch '30917-wiki-is-not-searchable' into 'master'

[CE Backport + ES implementation]Resolve "Wiki is not searchable with Guest permissions"

See merge request !1964
parents a8e86e48 a501f6ce
...@@ -85,6 +85,12 @@ module ProjectsHelper ...@@ -85,6 +85,12 @@ module ProjectsHelper
@nav_tabs ||= get_project_nav_tabs(@project, current_user) @nav_tabs ||= get_project_nav_tabs(@project, current_user)
end end
def project_search_tabs?(tab)
abilities = Array(search_tab_ability_map[tab])
abilities.any? { |ability| can?(current_user, ability, @project) }
end
def project_nav_tab?(name) def project_nav_tab?(name)
project_nav_tabs.include? name project_nav_tabs.include? name
end end
...@@ -203,7 +209,17 @@ module ProjectsHelper ...@@ -203,7 +209,17 @@ module ProjectsHelper
nav_tabs << :container_registry nav_tabs << :container_registry
end end
tab_ability_map = { tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project)
nav_tabs << tab
end
end
nav_tabs.flatten
end
def tab_ability_map
{
environments: :read_environment, environments: :read_environment,
milestones: :read_milestone, milestones: :read_milestone,
pipelines: :read_pipeline, pipelines: :read_pipeline,
...@@ -215,14 +231,15 @@ module ProjectsHelper ...@@ -215,14 +231,15 @@ module ProjectsHelper
team: :read_project_member, team: :read_project_member,
wiki: :read_wiki wiki: :read_wiki
} }
end
tab_ability_map.each do |tab, ability| def search_tab_ability_map
if can?(current_user, ability, project) @search_tab_ability_map ||= tab_ability_map.merge(
nav_tabs << tab blobs: :download_code,
end commits: :download_code,
end merge_requests: :read_merge_request,
notes: [:read_merge_request, :download_code, :read_issue, :read_project_snippet]
nav_tabs.flatten )
end end
def project_lfs_status(project) def project_lfs_status(project)
......
...@@ -41,7 +41,7 @@ module SearchHelper ...@@ -41,7 +41,7 @@ module SearchHelper
def find_project_for_blob(blob) def find_project_for_blob(blob)
Project.find(blob['_parent']) Project.find(blob['_parent'])
end end
private private
# Autocomplete results for various settings pages # Autocomplete results for various settings pages
......
...@@ -12,7 +12,7 @@ class SearchService ...@@ -12,7 +12,7 @@ class SearchService
@project = @project =
if params[:project_id].present? if params[:project_id].present?
the_project = Project.find_by(id: params[:project_id]) the_project = Project.find_by(id: params[:project_id])
can?(current_user, :download_code, the_project) ? the_project : nil can?(current_user, :read_project, the_project) ? the_project : nil
else else
nil nil
end end
......
...@@ -3,41 +3,48 @@ ...@@ -3,41 +3,48 @@
.fade-right= icon('angle-right') .fade-right= icon('angle-right')
%ul.nav-links.search-filter.scrolling-tabs %ul.nav-links.search-filter.scrolling-tabs
- if @project - if @project
%li{ class: active_when(@scope == 'blobs') } - if project_search_tabs?(:blobs)
= link_to search_filter_path(scope: 'blobs') do %li{ class: active_when(@scope == 'blobs') }
Code = link_to search_filter_path(scope: 'blobs') do
%span.badge Code
= @search_results.blobs_count %span.badge
%li{ class: active_when(@scope == 'issues') } = @search_results.blobs_count
= link_to search_filter_path(scope: 'issues') do - if project_search_tabs?(:issues)
Issues %li{ class: active_when(@scope == 'issues') }
%span.badge = link_to search_filter_path(scope: 'issues') do
= @search_results.issues_count Issues
%li{ class: active_when(@scope == 'merge_requests') } %span.badge
= link_to search_filter_path(scope: 'merge_requests') do = @search_results.issues_count
Merge requests - if project_search_tabs?(:merge_requests)
%span.badge %li{ class: active_when(@scope == 'merge_requests') }
= @search_results.merge_requests_count = link_to search_filter_path(scope: 'merge_requests') do
%li{ class: active_when(@scope == 'milestones') } Merge requests
= link_to search_filter_path(scope: 'milestones') do %span.badge
Milestones = @search_results.merge_requests_count
%span.badge - if project_search_tabs?(:milestones)
= @search_results.milestones_count %li{ class: active_when(@scope == 'milestones') }
%li{ class: active_when(@scope == 'notes') } = link_to search_filter_path(scope: 'milestones') do
= link_to search_filter_path(scope: 'notes') do Milestones
Comments %span.badge
%span.badge = @search_results.milestones_count
= @search_results.notes_count - if project_search_tabs?(:notes)
%li{ class: active_when(@scope == 'wiki_blobs') } %li{ class: active_when(@scope == 'notes') }
= link_to search_filter_path(scope: 'wiki_blobs') do = link_to search_filter_path(scope: 'notes') do
Wiki Comments
%span.badge %span.badge
= @search_results.wiki_blobs_count = @search_results.notes_count
%li{ class: active_when(@scope == 'commits') } - if project_search_tabs?(:wiki)
= link_to search_filter_path(scope: 'commits') do %li{ class: active_when(@scope == 'wiki_blobs') }
Commits = link_to search_filter_path(scope: 'wiki_blobs') do
%span.badge Wiki
= @search_results.commits_count %span.badge
= @search_results.wiki_blobs_count
- if project_search_tabs?(:commits)
%li{ class: active_when(@scope == 'commits') }
= link_to search_filter_path(scope: 'commits') do
Commits
%span.badge
= @search_results.commits_count
- elsif @show_snippets - elsif @show_snippets
%li{ class: active_when(@scope == 'snippet_blobs') } %li{ class: active_when(@scope == 'snippet_blobs') }
......
---
title: 'Fix: Wiki is not searchable with Guest permissions'
merge_request:
author:
...@@ -69,6 +69,8 @@ module Gitlab ...@@ -69,6 +69,8 @@ module Gitlab
end end
def wiki_blobs def wiki_blobs
return Kaminari.paginate_array([]) unless Ability.allowed?(@current_user, :read_wiki, project)
if project.wiki_enabled? && !project.wiki.empty? && query.present? if project.wiki_enabled? && !project.wiki.empty? && query.present?
project.wiki.search( project.wiki.search(
query, query,
......
...@@ -187,19 +187,21 @@ module Gitlab ...@@ -187,19 +187,21 @@ module Gitlab
end end
def wiki_filter def wiki_filter
blob_filter(:wiki_access_level) blob_filter(:wiki_access_level, visible_for_guests: true)
end end
def repository_filter def repository_filter
blob_filter(:repository_access_level) blob_filter(:repository_access_level)
end end
def blob_filter(project_feature_name) def blob_filter(project_feature_name, visible_for_guests: false)
project_ids = visible_for_guests ? limit_project_ids : non_guest_project_ids
conditions = conditions =
if non_guest_project_ids == :any if project_ids == :any
[{ exists: { field: "id" } }] [{ exists: { field: "id" } }]
else else
[{ terms: { id: non_guest_project_ids } }] [{ terms: { id: project_ids } }]
end end
if public_and_internal_projects if public_and_internal_projects
......
require 'spec_helper' require 'spec_helper'
describe 'GlobalSearch' do describe 'GlobalSearch' do
let(:features) { %i(issues merge_requests repository builds) } let(:features) { %i(issues merge_requests repository builds wiki) }
let(:admin) { create :user, admin: true } let(:admin) { create :user, admin: true }
let(:auditor) {create :user, auditor: true } let(:auditor) {create :user, auditor: true }
let(:non_member) { create :user } let(:non_member) { create :user }
...@@ -130,11 +130,13 @@ describe 'GlobalSearch' do ...@@ -130,11 +130,13 @@ describe 'GlobalSearch' do
Sidekiq::Testing.inline! do Sidekiq::Testing.inline! do
create :issue, title: 'term', project: project create :issue, title: 'term', project: project
create :merge_request, title: 'term', target_project: project, source_project: project create :merge_request, title: 'term', target_project: project, source_project: project
project.wiki.create_page('index_page', 'term')
project.project_feature.update!(feature_settings) if feature_settings project.project_feature.update!(feature_settings) if feature_settings
project.repository.index_blobs project.repository.index_blobs
project.repository.index_commits project.repository.index_commits
project.wiki.index_blobs
Gitlab::Elastic::Helper.refresh_index Gitlab::Elastic::Helper.refresh_index
end end
...@@ -149,6 +151,7 @@ describe 'GlobalSearch' do ...@@ -149,6 +151,7 @@ describe 'GlobalSearch' do
results = search(user, 'term') results = search(user, 'term')
expect(results.issues_count).to eq(0) expect(results.issues_count).to eq(0)
expect(results.merge_requests_count).to eq(0) expect(results.merge_requests_count).to eq(0)
expect(results.wiki_blobs_count).to eq(0)
expect(search(user, 'def').blobs_count).to eq(0) expect(search(user, 'def').blobs_count).to eq(0)
expect(search(user, 'add').commits_count).to eq(0) expect(search(user, 'add').commits_count).to eq(0)
end end
...@@ -157,6 +160,7 @@ describe 'GlobalSearch' do ...@@ -157,6 +160,7 @@ describe 'GlobalSearch' do
results = search(user, 'term') results = search(user, 'term')
expect(results.issues_count).not_to eq(0) expect(results.issues_count).not_to eq(0)
expect(results.merge_requests_count).not_to eq(0) expect(results.merge_requests_count).not_to eq(0)
expect(results.wiki_blobs_count).not_to eq(0)
expect(search(user, 'def').blobs_count).not_to eq(0) expect(search(user, 'def').blobs_count).not_to eq(0)
expect(search(user, 'add').commits_count).not_to eq(0) expect(search(user, 'add').commits_count).not_to eq(0)
end end
...@@ -164,6 +168,7 @@ describe 'GlobalSearch' do ...@@ -164,6 +168,7 @@ describe 'GlobalSearch' do
def expect_non_code_items_to_be_found(user) def expect_non_code_items_to_be_found(user)
results = search(guest, 'term') results = search(guest, 'term')
expect(results.issues_count).not_to eq(0) expect(results.issues_count).not_to eq(0)
expect(results.wiki_blobs_count).not_to eq(0)
expect(results.merge_requests_count).to eq(0) expect(results.merge_requests_count).to eq(0)
expect(search(guest, 'def').blobs_count).to eq(0) expect(search(guest, 'def').blobs_count).to eq(0)
expect(search(guest, 'add').commits_count).to eq(0) expect(search(guest, 'add').commits_count).to eq(0)
......
...@@ -61,11 +61,28 @@ describe Gitlab::Elastic::ProjectSearchResults, lib: true do ...@@ -61,11 +61,28 @@ describe Gitlab::Elastic::ProjectSearchResults, lib: true do
result1 = Gitlab::Elastic::ProjectSearchResults.new(user, 'initial', project.id) result1 = Gitlab::Elastic::ProjectSearchResults.new(user, 'initial', project.id)
expect(result1.commits_count).to eq(1) expect(result1.commits_count).to eq(1)
end end
context 'visibility checks' do
it 'shows wiki for guests' do
project = create :empty_project, :public
guest = create :user
project.add_guest(guest)
# Wiki
project.wiki.create_page('index_page', 'term')
project.wiki.index_blobs
Gitlab::Elastic::Helper.refresh_index
result = Gitlab::Elastic::ProjectSearchResults.new(guest, 'term', project.id)
expect(result.wiki_blobs_count).to eq(1)
end
end
end end
describe "search for commits in non-default branch" do describe "search for commits in non-default branch" do
let(:project) { create(:project, :public, visibility) } let(:project) { create(:project, :public, visibility) }
let(:visibility) { :repository_enabled } let(:visibility) { :repository_enabled }
let(:result) { described_class.new(user, 'initial', project.id, 'test') } let(:result) { described_class.new(user, 'initial', project.id, 'test') }
subject(:commits) { result.objects('commits') } subject(:commits) { result.objects('commits') }
......
...@@ -419,6 +419,14 @@ describe Gitlab::Elastic::SearchResults, lib: true do ...@@ -419,6 +419,14 @@ describe Gitlab::Elastic::SearchResults, lib: true do
expect(results.wiki_blobs_count).to eq 1 expect(results.wiki_blobs_count).to eq 1
end end
it 'finds wiki blobs for guest' do
project_1.add_guest(user)
blobs = results.objects('wiki_blobs')
expect(blobs.first["_source"]["blob"]["content"]).to include("term")
expect(results.wiki_blobs_count).to eq 1
end
it 'finds wiki blobs from public projects only' do it 'finds wiki blobs from public projects only' do
project_2 = create :project, :private project_2 = create :project, :private
project_2.wiki.create_page('index_page', 'term') project_2.wiki.create_page('index_page', 'term')
......
...@@ -123,8 +123,8 @@ describe Gitlab::ProjectSearchResults, lib: true do ...@@ -123,8 +123,8 @@ describe Gitlab::ProjectSearchResults, lib: true do
context 'when wiki is internal' do context 'when wiki is internal' do
let(:project) { create(:project, :public, :wiki_private) } let(:project) { create(:project, :public, :wiki_private) }
it 'finds wiki blobs for members' do it 'finds wiki blobs for guest' do
project.add_reporter(user) project.add_guest(user)
is_expected.not_to be_empty is_expected.not_to be_empty
end end
......
...@@ -26,6 +26,15 @@ describe SearchService, services: true do ...@@ -26,6 +26,15 @@ describe SearchService, services: true do
expect(project).to eq accessible_project expect(project).to eq accessible_project
end end
it 'returns the project for guests' do
search_project = create :empty_project
search_project.add_guest(user)
project = SearchService.new(user, project_id: search_project.id).project
expect(project).to eq search_project
end
end end
context 'when the project is not accessible' do context 'when the project is not accessible' do
......
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