Commit 032ba126 authored by Robert Speicher's avatar Robert Speicher

Merge remote-tracking branch 'dev/master'

parents 2d4d724b 587eca1e
...@@ -38,7 +38,12 @@ module Elastic ...@@ -38,7 +38,12 @@ module Elastic
after_commit on: :update do after_commit on: :update do
if Gitlab.config.elasticsearch.enabled && self.searchable? if Gitlab.config.elasticsearch.enabled && self.searchable?
ElasticIndexerWorker.perform_async(:update, self.class.to_s, self.id) ElasticIndexerWorker.perform_async(
:update,
self.class.to_s,
self.id,
changed_fields: self.previous_changes.keys
)
end end
end end
......
...@@ -12,6 +12,12 @@ module Elastic ...@@ -12,6 +12,12 @@ module Elastic
indexes :project_id, type: :integer indexes :project_id, type: :integer
indexes :created_at, type: :date indexes :created_at, type: :date
indexes :issue do
indexes :assignee_id, type: :integer
indexes :author_id, type: :integer
indexes :confidential, type: :boolean
end
indexes :updated_at_sort, type: :string, index: 'not_analyzed' indexes :updated_at_sort, type: :string, index: 'not_analyzed'
end end
...@@ -24,27 +30,36 @@ module Elastic ...@@ -24,27 +30,36 @@ module Elastic
data[attr.to_s] = self.send(attr) data[attr.to_s] = self.send(attr)
end end
if noteable.is_a?(Issue)
data['issue'] = {
assignee_id: noteable.assignee_id,
author_id: noteable.author_id,
confidential: noteable.confidential
}
end
data['updated_at_sort'] = updated_at data['updated_at_sort'] = updated_at
data data
end end
def self.elastic_search(query, options: {}) def self.elastic_search(query, options: {})
options[:in] = ["note"] options[:in] = ['note']
query_hash = { query_hash = {
query: { query: {
bool: { bool: {
must: { match: { note: query } }, must: [{ match: { note: query } }],
}, },
} }
} }
if query.blank? if query.blank?
query_hash[:query][:bool][:must] = { match_all: {} } query_hash[:query][:bool][:must] = [{ match_all: {} }]
query_hash[:track_scores] = true query_hash[:track_scores] = true
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[:current_user])
query_hash[:sort] = [ query_hash[:sort] = [
{ updated_at_sort: { order: :desc, mode: :min } }, { updated_at_sort: { order: :desc, mode: :min } },
...@@ -55,6 +70,40 @@ module Elastic ...@@ -55,6 +70,40 @@ module Elastic
self.__elasticsearch__.search(query_hash) self.__elasticsearch__.search(query_hash)
end end
def self.confidentiality_filter(query_hash, current_user)
return query_hash if current_user && current_user.admin?
filter = {
bool: {
should: [
{ bool: { must_not: [{ exists: { field: :issue } }] } },
{ term: { "issue.confidential" => false } }
]
}
}
if current_user
filter[:bool][:should] << {
bool: {
must: [
{ term: { "issue.confidential" => true } },
{ bool: {
should: [
{ term: { "issue.author_id" => current_user.id } },
{ term: { "issue.assignee_id" => current_user.id } },
{ terms: { "issue.project_id" => current_user.authorized_projects.pluck(:id) } }
]
}
}
]
}
}
end
query_hash[:query][:bool][:must] << filter
query_hash
end
end end
end end
end end
...@@ -3,6 +3,8 @@ class ElasticIndexerWorker ...@@ -3,6 +3,8 @@ class ElasticIndexerWorker
sidekiq_options queue: :elasticsearch sidekiq_options queue: :elasticsearch
ISSUE_TRACKED_FIELDS = %w(assignee_id author_id confidential)
Client = Elasticsearch::Client.new(host: Gitlab.config.elasticsearch.host, Client = Elasticsearch::Client.new(host: Gitlab.config.elasticsearch.host,
port: Gitlab.config.elasticsearch.port) port: Gitlab.config.elasticsearch.port)
...@@ -14,6 +16,8 @@ class ElasticIndexerWorker ...@@ -14,6 +16,8 @@ class ElasticIndexerWorker
record = klass.find(record_id) record = klass.find(record_id)
record.__elasticsearch__.client = Client record.__elasticsearch__.client = Client
record.__elasticsearch__.__send__ "#{operation}_document" record.__elasticsearch__.__send__ "#{operation}_document"
update_issue_notes(record, options["changed_fields"]) if klass == Issue
when /delete/ when /delete/
Client.delete index: klass.index_name, type: klass.document_type, id: record_id Client.delete index: klass.index_name, type: klass.document_type, id: record_id
...@@ -23,6 +27,12 @@ class ElasticIndexerWorker ...@@ -23,6 +27,12 @@ class ElasticIndexerWorker
true # Less work to do! true # Less work to do!
end end
def update_issue_notes(record, changed_fields)
if changed_fields && (changed_fields & ISSUE_TRACKED_FIELDS).any?
Note.import query: -> { where(noteable: record) }
end
end
def clear_project_indexes(record_id) def clear_project_indexes(record_id)
# Remove repository index # Remove repository index
Client.delete_by_query({ Client.delete_by_query({
......
...@@ -86,7 +86,8 @@ module Gitlab ...@@ -86,7 +86,8 @@ module Gitlab
def notes def notes
opt = { opt = {
project_ids: limit_project_ids project_ids: limit_project_ids,
current_user: @current_user
} }
Note.elastic_search(query, options: opt) Note.elastic_search(query, options: opt)
......
...@@ -48,4 +48,33 @@ describe "Note", elastic: true do ...@@ -48,4 +48,33 @@ describe "Note", elastic: true do
create :note, :system, project: project create :note, :system, project: project
create :note, :award, project: project create :note, :award, project: project
end end
context 'notes to confidential issues' do
it "does not find note" do
issue = create :issue, :confidential
create :note, note: 'bla-bla term', project: issue.project, noteable: issue
create :note, project: issue.project, noteable: issue
Note.__elasticsearch__.refresh_index!
options = { project_ids: [issue.project.id] }
expect(Note.elastic_search('term', options: options).total_count).to eq(0)
end
it "finds note when user is authorized to see it" do
user = create :user
issue = create :issue, :confidential, author: user
create :note, note: 'bla-bla term', project: issue.project, noteable: issue
create :note, project: issue.project, noteable: issue
Note.__elasticsearch__.refresh_index!
options = { project_ids: [issue.project.id], current_user: user }
expect(Note.elastic_search('term', options: options).total_count).to eq(1)
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