Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
0355e90a
Commit
0355e90a
authored
Jul 01, 2019
by
Mark Chao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ES: Decouple other ActiveRecord models
See
https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/14428
parent
61a2d19f
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
359 additions
and
585 deletions
+359
-585
config/initializers/zz_metrics.rb
config/initializers/zz_metrics.rb
+1
-5
ee/app/models/concerns/elastic/application_search.rb
ee/app/models/concerns/elastic/application_search.rb
+0
-315
ee/app/models/concerns/elastic/issues_search.rb
ee/app/models/concerns/elastic/issues_search.rb
+0
-79
ee/app/models/concerns/elastic/projects_search.rb
ee/app/models/concerns/elastic/projects_search.rb
+1
-94
ee/app/models/ee/issue.rb
ee/app/models/ee/issue.rb
+1
-1
ee/app/models/ee/legacy_diff_note.rb
ee/app/models/ee/legacy_diff_note.rb
+1
-1
ee/app/models/ee/merge_request.rb
ee/app/models/ee/merge_request.rb
+1
-1
ee/app/models/ee/milestone.rb
ee/app/models/ee/milestone.rb
+1
-1
ee/app/models/ee/note.rb
ee/app/models/ee/note.rb
+1
-1
ee/lib/elastic/latest/issue_class_proxy.rb
ee/lib/elastic/latest/issue_class_proxy.rb
+64
-0
ee/lib/elastic/latest/issue_instance_proxy.rb
ee/lib/elastic/latest/issue_instance_proxy.rb
+21
-0
ee/lib/elastic/latest/merge_request_class_proxy.rb
ee/lib/elastic/latest/merge_request_class_proxy.rb
+25
-0
ee/lib/elastic/latest/merge_request_instance_proxy.rb
ee/lib/elastic/latest/merge_request_instance_proxy.rb
+2
-28
ee/lib/elastic/latest/milestone_class_proxy.rb
ee/lib/elastic/latest/milestone_class_proxy.rb
+21
-0
ee/lib/elastic/latest/milestone_instance_proxy.rb
ee/lib/elastic/latest/milestone_instance_proxy.rb
+2
-20
ee/lib/elastic/latest/note_class_proxy.rb
ee/lib/elastic/latest/note_class_proxy.rb
+10
-32
ee/lib/elastic/latest/note_instance_proxy.rb
ee/lib/elastic/latest/note_instance_proxy.rb
+29
-0
ee/lib/elastic/latest/project_class_proxy.rb
ee/lib/elastic/latest/project_class_proxy.rb
+51
-0
ee/lib/elastic/latest/project_instance_proxy.rb
ee/lib/elastic/latest/project_instance_proxy.rb
+50
-0
ee/lib/elastic/v12p1/issue_class_proxy.rb
ee/lib/elastic/v12p1/issue_class_proxy.rb
+7
-0
ee/lib/elastic/v12p1/issue_instance_proxy.rb
ee/lib/elastic/v12p1/issue_instance_proxy.rb
+7
-0
ee/lib/elastic/v12p1/merge_request_class_proxy.rb
ee/lib/elastic/v12p1/merge_request_class_proxy.rb
+7
-0
ee/lib/elastic/v12p1/merge_request_instance_proxy.rb
ee/lib/elastic/v12p1/merge_request_instance_proxy.rb
+7
-0
ee/lib/elastic/v12p1/milestone_class_proxy.rb
ee/lib/elastic/v12p1/milestone_class_proxy.rb
+7
-0
ee/lib/elastic/v12p1/milestone_instance_proxy.rb
ee/lib/elastic/v12p1/milestone_instance_proxy.rb
+7
-0
ee/lib/elastic/v12p1/note_class_proxy.rb
ee/lib/elastic/v12p1/note_class_proxy.rb
+7
-0
ee/lib/elastic/v12p1/note_instance_proxy.rb
ee/lib/elastic/v12p1/note_instance_proxy.rb
+7
-0
ee/lib/elastic/v12p1/project_class_proxy.rb
ee/lib/elastic/v12p1/project_class_proxy.rb
+7
-0
ee/lib/elastic/v12p1/project_instance_proxy.rb
ee/lib/elastic/v12p1/project_instance_proxy.rb
+7
-0
ee/lib/gitlab/elastic/search_results.rb
ee/lib/gitlab/elastic/search_results.rb
+1
-1
ee/spec/models/concerns/elastic/issue_spec.rb
ee/spec/models/concerns/elastic/issue_spec.rb
+1
-1
ee/spec/models/concerns/elastic/merge_request_spec.rb
ee/spec/models/concerns/elastic/merge_request_spec.rb
+1
-1
ee/spec/models/concerns/elastic/milestone_spec.rb
ee/spec/models/concerns/elastic/milestone_spec.rb
+1
-1
ee/spec/models/concerns/elastic/note_spec.rb
ee/spec/models/concerns/elastic/note_spec.rb
+2
-2
ee/spec/models/concerns/elastic/project_spec.rb
ee/spec/models/concerns/elastic/project_spec.rb
+1
-1
No files found.
config/initializers/zz_metrics.rb
View file @
0355e90a
...
...
@@ -100,11 +100,7 @@ def instrument_classes(instrumentation)
instrumentation
.
instrument_instance_methods
(
Gitlab
::
Elastic
::
SnippetSearchResults
)
instrumentation
.
instrument_methods
(
Gitlab
::
Elastic
::
Helper
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
ApplicationSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
IssuesSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
MergeRequestsSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
MilestonesSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
NotesSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
ApplicationVersionedSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
ProjectsSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
RepositoriesSearch
)
instrumentation
.
instrument_instance_methods
(
Elastic
::
SnippetsSearch
)
...
...
ee/app/models/concerns/elastic/application_search.rb
deleted
100644 → 0
View file @
61a2d19f
# frozen_string_literal: true
module
Elastic
module
ApplicationSearch
extend
ActiveSupport
::
Concern
# Defer evaluation from class-definition time to index-creation time
class
AsJSON
def
initialize
(
&
blk
)
@blk
=
blk
end
def
call
@blk
.
call
end
def
as_json
(
*
args
,
&
blk
)
call
end
end
included
do
include
Elasticsearch
::
Model
index_name
[
Rails
.
application
.
class
.
parent_name
.
downcase
,
Rails
.
env
].
join
(
'-'
)
# ES6 requires a single type per index
document_type
'doc'
# A temp solution to keep only one copy of setting,
# will be removed in https://gitlab.com/gitlab-org/gitlab-ee/issues/12548
__elasticsearch__
.
instance_variable_set
(
:@settings
,
Elastic
::
Latest
::
Config
.
settings
)
__elasticsearch__
.
instance_variable_set
(
:@mapping
,
Elastic
::
Latest
::
Config
.
mappings
)
after_commit
on: :create
do
if
Gitlab
::
CurrentSettings
.
elasticsearch_indexing?
&&
self
.
searchable?
ElasticIndexerWorker
.
perform_async
(
:index
,
self
.
class
.
to_s
,
self
.
id
,
self
.
es_id
)
end
end
after_commit
on: :update
do
if
Gitlab
::
CurrentSettings
.
elasticsearch_indexing?
&&
self
.
searchable?
ElasticIndexerWorker
.
perform_async
(
:update
,
self
.
class
.
to_s
,
self
.
id
,
self
.
es_id
,
changed_fields:
self
.
previous_changes
.
keys
)
end
end
after_commit
on: :destroy
do
if
Gitlab
::
CurrentSettings
.
elasticsearch_indexing?
&&
self
.
searchable?
ElasticIndexerWorker
.
perform_async
(
:delete
,
self
.
class
.
to_s
,
self
.
id
,
self
.
es_id
,
es_parent:
self
.
es_parent
)
end
end
# Should be overridden in the models where some records should be skipped
def
searchable?
self
.
use_elasticsearch?
end
def
use_elasticsearch?
self
.
project
&
.
use_elasticsearch?
end
def
generic_attributes
{
'join_field'
=>
{
'name'
=>
es_type
,
'parent'
=>
es_parent
},
'type'
=>
es_type
}
end
def
es_parent
"project_
#{
project_id
}
"
unless
is_a?
(
Project
)
||
self
&
.
project_id
.
nil?
end
def
es_type
self
.
class
.
es_type
end
def
es_id
"
#{
es_type
}
_
#{
id
}
"
end
# Some attributes are actually complicated methods. Bad data can cause
# them to raise exceptions. When this happens, we still want the remainder
# of the object to be saved, so silently swallow the errors
def
safely_read_attribute_for_elasticsearch
(
attr_name
)
send
(
attr_name
)
# rubocop:disable GitlabSecurity/PublicSend
rescue
=>
err
logger
.
warn
(
"Elasticsearch failed to read
#{
attr_name
}
for
#{
self
.
class
}
#{
self
.
id
}
:
#{
err
}
"
)
nil
end
end
class_methods
do
# Support STI models
def
inherited
(
subclass
)
super
# Avoid SystemStackError in Model.import
# See https://github.com/elastic/elasticsearch-rails/issues/144
subclass
.
include
Elasticsearch
::
Model
# Use ES configuration from parent model
# TODO: Revisit after upgrading to elasticsearch-model 7.0.0
# See https://github.com/elastic/elasticsearch-rails/commit/b8455db186664e21927bfb271bab6390853e7ff3
subclass
.
__elasticsearch__
.
index_name
=
self
.
index_name
subclass
.
__elasticsearch__
.
document_type
=
self
.
document_type
subclass
.
__elasticsearch__
.
instance_variable_set
(
:@mapping
,
self
.
mapping
.
dup
)
end
# Should be overridden for all nested models
def
nested?
false
end
def
es_type
name
.
underscore
end
def
highlight_options
(
fields
)
es_fields
=
fields
.
map
{
|
field
|
field
.
split
(
'^'
).
first
}.
each_with_object
({})
do
|
field
,
memo
|
memo
[
field
.
to_sym
]
=
{}
end
{
fields:
es_fields
}
end
def
es_import
(
**
options
)
transform
=
lambda
do
|
r
|
{
index:
{
_id:
r
.
es_id
,
data:
r
.
__elasticsearch__
.
as_indexed_json
}
}.
tap
do
|
data
|
data
[
:index
][
:routing
]
=
r
.
es_parent
if
r
.
es_parent
end
end
options
[
:transform
]
=
transform
self
.
import
(
options
)
end
def
basic_query_hash
(
fields
,
query
)
query_hash
=
if
query
.
present?
{
query:
{
bool:
{
must:
[{
simple_query_string:
{
fields:
fields
,
query:
query
,
default_operator: :and
}
}],
filter:
[{
term:
{
type:
self
.
es_type
}
}]
}
}
}
else
{
query:
{
bool:
{
must:
{
match_all:
{}
}
}
},
track_scores:
true
}
end
query_hash
[
:sort
]
=
[
{
updated_at:
{
order: :desc
}
},
:_score
]
query_hash
[
:highlight
]
=
highlight_options
(
fields
)
query_hash
end
def
iid_query_hash
(
iid
)
{
query:
{
bool:
{
filter:
[{
term:
{
iid:
iid
}
}]
}
}
}
end
# Builds an elasticsearch query that will select child documents from a
# set of projects, taking user access rules into account.
def
project_ids_filter
(
query_hash
,
options
)
project_query
=
project_ids_query
(
options
[
:current_user
],
options
[
:project_ids
],
options
[
:public_and_internal_projects
],
options
[
:features
]
)
query_hash
[
:query
][
:bool
][
:filter
]
||=
[]
query_hash
[
:query
][
:bool
][
:filter
]
<<
{
has_parent:
{
parent_type:
"project"
,
query:
{
bool:
project_query
}
}
}
query_hash
end
# Builds an elasticsearch query that will select projects the user is
# granted access to.
#
# If a project feature(s) is specified, it indicates interest in child
# documents gated by that project feature - e.g., "issues". The feature's
# visibility level must be taken into account.
def
project_ids_query
(
user
,
project_ids
,
public_and_internal_projects
,
features
=
nil
)
# When reading cross project is not allowed, only allow searching a
# a single project, so the `:read_*` ability is only checked once.
unless
Ability
.
allowed?
(
user
,
:read_cross_project
)
project_ids
=
[]
if
project_ids
.
is_a?
(
Array
)
&&
project_ids
.
size
>
1
end
# At least one condition must be present, so pick no projects for
# anonymous users.
# Pick private, internal and public projects the user is a member of.
# Pick all private projects for admins & auditors.
conditions
=
[
pick_projects_by_membership
(
project_ids
,
features
)]
if
public_and_internal_projects
# Skip internal projects for anonymous and external users.
# Others are given access to all internal projects. Admins & auditors
# get access to internal projects where the feature is private.
conditions
<<
pick_projects_by_visibility
(
Project
::
INTERNAL
,
user
,
features
)
if
user
&&
!
user
.
external?
# All users, including anonymous, can access public projects.
# Admins & auditors get access to public projects where the feature is
# private.
conditions
<<
pick_projects_by_visibility
(
Project
::
PUBLIC
,
user
,
features
)
end
{
should:
conditions
}
end
private
# Most users come with a list of projects they are members of, which may
# be a mix of public, internal or private. Grant access to them all, as
# long as the project feature is not disabled.
#
# Admins & auditors are given access to all private projects. Access to
# internal or public projects where the project feature is private is not
# granted here.
def
pick_projects_by_membership
(
project_ids
,
features
=
nil
)
condition
=
if
project_ids
==
:any
{
term:
{
visibility_level:
Project
::
PRIVATE
}
}
else
{
terms:
{
id:
project_ids
}
}
end
limit_by_feature
(
condition
,
features
,
include_members_only:
true
)
end
# Grant access to projects of the specified visibility level to the user.
#
# If a project feature is specified, access is only granted if the feature
# is enabled or, for admins & auditors, private.
def
pick_projects_by_visibility
(
visibility
,
user
,
features
)
condition
=
{
term:
{
visibility_level:
visibility
}
}
limit_by_feature
(
condition
,
features
,
include_members_only:
user
&
.
full_private_access?
)
end
# If a project feature(s) is specified, access is dependent on its visibility
# level being enabled (or private if `include_members_only: true`).
#
# This method is a no-op if no project feature is specified.
# It accepts an array of features or a single feature, when an array is provided
# it queries if any of the features is enabled.
#
# Always denies access to projects when the features are disabled - even to
# admins & auditors - as stale child documents may be present.
def
limit_by_feature
(
condition
,
features
,
include_members_only
:)
return
condition
unless
features
features
=
Array
(
features
)
features
.
map
do
|
feature
|
limit
=
if
include_members_only
{
terms:
{
"
#{
feature
}
_access_level"
=>
[
::
ProjectFeature
::
ENABLED
,
::
ProjectFeature
::
PRIVATE
]
}
}
else
{
term:
{
"
#{
feature
}
_access_level"
=>
::
ProjectFeature
::
ENABLED
}
}
end
{
bool:
{
filter:
[
condition
,
limit
]
}
}
end
end
end
end
end
ee/app/models/concerns/elastic/issues_search.rb
deleted
100644 → 0
View file @
61a2d19f
# frozen_string_literal: true
module
Elastic
module
IssuesSearch
extend
ActiveSupport
::
Concern
included
do
include
ApplicationSearch
def
as_indexed_json
(
options
=
{})
data
=
{}
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[
:id
,
:iid
,
:title
,
:description
,
:created_at
,
:updated_at
,
:state
,
:project_id
,
:author_id
,
:confidential
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
data
[
'assignee_id'
]
=
safely_read_attribute_for_elasticsearch
(
:assignee_ids
)
data
.
merge
(
generic_attributes
)
end
def
self
.
nested?
true
end
def
self
.
elastic_search
(
query
,
options:
{})
query_hash
=
if
query
=~
/#(\d+)\z/
iid_query_hash
(
Regexp
.
last_match
(
1
))
else
basic_query_hash
(
%w(title^2 description)
,
query
)
end
options
[
:features
]
=
'issues'
query_hash
=
project_ids_filter
(
query_hash
,
options
)
query_hash
=
confidentiality_filter
(
query_hash
,
options
[
:current_user
])
self
.
__elasticsearch__
.
search
(
query_hash
)
end
def
self
.
confidentiality_filter
(
query_hash
,
current_user
)
return
query_hash
if
current_user
&&
current_user
.
full_private_access?
filter
=
if
current_user
{
bool:
{
should:
[
{
term:
{
confidential:
false
}
},
{
bool:
{
must:
[
{
term:
{
confidential:
true
}
},
{
bool:
{
should:
[
{
term:
{
author_id:
current_user
.
id
}
},
{
term:
{
assignee_id:
current_user
.
id
}
},
{
terms:
{
project_id:
current_user
.
authorized_projects
(
Gitlab
::
Access
::
REPORTER
).
pluck
(
:id
)
}
}
]
}
}
]
}
}
]
}
}
else
{
term:
{
confidential:
false
}
}
end
query_hash
[
:query
][
:bool
][
:filter
]
<<
filter
query_hash
end
end
end
end
ee/app/models/concerns/elastic/projects_search.rb
View file @
0355e90a
...
...
@@ -4,13 +4,7 @@ module Elastic
module
ProjectsSearch
extend
ActiveSupport
::
Concern
TRACKED_FEATURE_SETTINGS
=
%w(
issues_access_level
merge_requests_access_level
snippets_access_level
wiki_access_level
repository_access_level
)
.
freeze
include
ApplicationVersionedSearch
INDEXED_ASSOCIATIONS
=
[
:issues
,
...
...
@@ -21,97 +15,10 @@ module Elastic
].
freeze
included
do
include
ApplicationSearch
def
use_elasticsearch?
::
Gitlab
::
CurrentSettings
.
elasticsearch_indexes_project?
(
self
)
end
def
as_indexed_json
(
options
=
{})
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
data
=
{}
[
:id
,
:name
,
:path
,
:description
,
:namespace_id
,
:created_at
,
:updated_at
,
:archived
,
:visibility_level
,
:last_activity_at
,
:name_with_namespace
,
:path_with_namespace
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
# Set it as a parent in our `project => child` JOIN field
data
[
'join_field'
]
=
es_type
# ES6 is now single-type per index, so we implement our own typing
data
[
'type'
]
=
'project'
TRACKED_FEATURE_SETTINGS
.
each
do
|
feature
|
data
[
feature
]
=
project_feature
.
public_send
(
feature
)
# rubocop:disable GitlabSecurity/PublicSend
end
data
end
def
self
.
elastic_search
(
query
,
options:
{})
options
[
:in
]
=
%w(name^10 name_with_namespace^2 path_with_namespace path^9 description)
query_hash
=
basic_query_hash
(
options
[
:in
],
query
)
filters
=
[]
if
options
[
:namespace_id
]
filters
<<
{
terms:
{
namespace_id:
[
options
[
:namespace_id
]].
flatten
}
}
end
if
options
[
:non_archived
]
filters
<<
{
terms:
{
archived:
[
!
options
[
:non_archived
]].
flatten
}
}
end
if
options
[
:visibility_levels
]
filters
<<
{
terms:
{
visibility_level:
[
options
[
:visibility_levels
]].
flatten
}
}
end
if
options
[
:project_ids
]
filters
<<
{
bool:
project_ids_query
(
options
[
:current_user
],
options
[
:project_ids
],
options
[
:public_and_internal_projects
])
}
end
query_hash
[
:query
][
:bool
][
:filter
]
=
filters
query_hash
[
:sort
]
=
[
:_score
]
self
.
__elasticsearch__
.
search
(
query_hash
)
end
def
self
.
indexed_association_classes
INDEXED_ASSOCIATIONS
.
map
do
|
association_name
|
reflect_on_association
(
association_name
).
klass
end
end
def
each_indexed_association
INDEXED_ASSOCIATIONS
.
each
do
|
association_name
|
association
=
self
.
association
(
association_name
)
...
...
ee/app/models/ee/issue.rb
View file @
0355e90a
...
...
@@ -11,7 +11,7 @@ module EE
WEIGHT_ANY
=
'Any'
.
freeze
WEIGHT_NONE
=
'None'
.
freeze
include
Elastic
::
Issues
Search
include
Elastic
::
ApplicationVersioned
Search
scope
:order_weight_desc
,
->
{
reorder
::
Gitlab
::
Database
.
nulls_last_order
(
'weight'
,
'DESC'
)
}
scope
:order_weight_asc
,
->
{
reorder
::
Gitlab
::
Database
.
nulls_last_order
(
'weight'
)
}
...
...
ee/app/models/ee/legacy_diff_note.rb
View file @
0355e90a
...
...
@@ -5,7 +5,7 @@ module EE
extend
ActiveSupport
::
Concern
prepended
do
include
Elastic
::
Notes
Search
include
Elastic
::
ApplicationVersioned
Search
end
end
end
ee/app/models/ee/merge_request.rb
View file @
0355e90a
...
...
@@ -11,7 +11,7 @@ module EE
include
FromUnion
prepended
do
include
Elastic
::
MergeRequests
Search
include
Elastic
::
ApplicationVersioned
Search
has_many
:reviews
,
inverse_of: :merge_request
has_many
:approvals
,
dependent: :delete_all
# rubocop:disable Cop/ActiveRecordDependent
...
...
ee/app/models/ee/milestone.rb
View file @
0355e90a
...
...
@@ -5,7 +5,7 @@ module EE
extend
ActiveSupport
::
Concern
prepended
do
include
Elastic
::
Milestones
Search
include
Elastic
::
ApplicationVersioned
Search
has_many
:boards
end
...
...
ee/app/models/ee/note.rb
View file @
0355e90a
...
...
@@ -7,7 +7,7 @@ module EE
prepended
do
include
::
ObjectStorage
::
BackgroundMove
include
Elastic
::
Notes
Search
include
Elastic
::
ApplicationVersioned
Search
belongs_to
:review
,
inverse_of: :notes
...
...
ee/lib/elastic/latest/issue_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
IssueClassProxy
<
ApplicationClassProxy
def
nested?
true
end
def
elastic_search
(
query
,
options:
{})
query_hash
=
if
query
=~
/#(\d+)\z/
iid_query_hash
(
Regexp
.
last_match
(
1
))
else
basic_query_hash
(
%w(title^2 description)
,
query
)
end
options
[
:features
]
=
'issues'
query_hash
=
project_ids_filter
(
query_hash
,
options
)
query_hash
=
confidentiality_filter
(
query_hash
,
options
[
:current_user
])
search
(
query_hash
)
end
private
def
confidentiality_filter
(
query_hash
,
current_user
)
return
query_hash
if
current_user
&&
current_user
.
full_private_access?
filter
=
if
current_user
{
bool:
{
should:
[
{
term:
{
confidential:
false
}
},
{
bool:
{
must:
[
{
term:
{
confidential:
true
}
},
{
bool:
{
should:
[
{
term:
{
author_id:
current_user
.
id
}
},
{
term:
{
assignee_id:
current_user
.
id
}
},
{
terms:
{
project_id:
current_user
.
authorized_projects
(
Gitlab
::
Access
::
REPORTER
).
pluck_primary_key
}
}
]
}
}
]
}
}
]
}
}
else
{
term:
{
confidential:
false
}
}
end
query_hash
[
:query
][
:bool
][
:filter
]
<<
filter
query_hash
end
end
end
end
ee/lib/elastic/latest/issue_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
IssueInstanceProxy
<
ApplicationInstanceProxy
def
as_indexed_json
(
options
=
{})
data
=
{}
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[
:id
,
:iid
,
:title
,
:description
,
:created_at
,
:updated_at
,
:state
,
:project_id
,
:author_id
,
:confidential
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
data
[
'assignee_id'
]
=
safely_read_attribute_for_elasticsearch
(
:assignee_ids
)
data
.
merge
(
generic_attributes
)
end
end
end
end
ee/lib/elastic/latest/merge_request_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
MergeRequestClassProxy
<
ApplicationClassProxy
def
nested?
true
end
def
elastic_search
(
query
,
options:
{})
query_hash
=
if
query
=~
/\!(\d+)\z/
iid_query_hash
(
Regexp
.
last_match
(
1
))
else
basic_query_hash
(
%w(title^2 description)
,
query
)
end
options
[
:features
]
=
'merge_requests'
query_hash
=
project_ids_filter
(
query_hash
,
options
)
search
(
query_hash
)
end
end
end
end
ee/
app/models/concerns/elastic/merge_requests_search
.rb
→
ee/
lib/elastic/latest/merge_request_instance_proxy
.rb
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
MergeRequestsSearch
extend
ActiveSupport
::
Concern
included
do
include
ApplicationSearch
module
Latest
class
MergeRequestInstanceProxy
<
ApplicationInstanceProxy
def
as_indexed_json
(
options
=
{})
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
...
...
@@ -32,28 +28,6 @@ module Elastic
data
.
merge
(
generic_attributes
)
end
def
es_parent
"project_
#{
target_project_id
}
"
end
def
self
.
nested?
true
end
def
self
.
elastic_search
(
query
,
options:
{})
query_hash
=
if
query
=~
/\!(\d+)\z/
iid_query_hash
(
Regexp
.
last_match
(
1
))
else
basic_query_hash
(
%w(title^2 description)
,
query
)
end
options
[
:features
]
=
'merge_requests'
query_hash
=
project_ids_filter
(
query_hash
,
options
)
self
.
__elasticsearch__
.
search
(
query_hash
)
end
end
end
end
ee/lib/elastic/latest/milestone_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
MilestoneClassProxy
<
ApplicationClassProxy
def
nested?
true
end
def
elastic_search
(
query
,
options:
{})
options
[
:in
]
=
%w(title^2 description)
query_hash
=
basic_query_hash
(
options
[
:in
],
query
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
search
(
query_hash
)
end
end
end
end
ee/
app/models/concerns/elastic/milestones_search
.rb
→
ee/
lib/elastic/latest/milestone_instance_proxy
.rb
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
MilestonesSearch
extend
ActiveSupport
::
Concern
included
do
include
ApplicationSearch
module
Latest
class
MilestoneInstanceProxy
<
ApplicationInstanceProxy
def
as_indexed_json
(
options
=
{})
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
...
...
@@ -18,20 +14,6 @@ module Elastic
data
.
merge
(
generic_attributes
)
end
def
self
.
nested?
true
end
def
self
.
elastic_search
(
query
,
options:
{})
options
[
:in
]
=
%w(title^2 description)
query_hash
=
basic_query_hash
(
options
[
:in
],
query
)
query_hash
=
project_ids_filter
(
query_hash
,
options
)
self
.
__elasticsearch__
.
search
(
query_hash
)
end
end
end
end
ee/
app/models/concerns/elastic/notes_search
.rb
→
ee/
lib/elastic/latest/note_class_proxy
.rb
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
NotesSearch
extend
ActiveSupport
::
Concern
included
do
include
ApplicationSearch
module
Latest
class
NoteClassProxy
<
ApplicationClassProxy
def
es_type
'note'
end
def
as_indexed_json
(
options
=
{})
data
=
{}
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[
:id
,
:note
,
:project_id
,
:noteable_type
,
:noteable_id
,
:created_at
,
:updated_at
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
if
noteable
.
is_a?
(
Issue
)
data
[
'issue'
]
=
{
assignee_id:
noteable
.
assignee_ids
,
author_id:
noteable
.
author_id
,
confidential:
noteable
.
confidential
}
end
data
.
merge
(
generic_attributes
)
end
def
self
.
nested?
def
nested?
true
end
def
self
.
elastic_search
(
query
,
options:
{})
def
elastic_search
(
query
,
options:
{})
options
[
:in
]
=
[
'note'
]
query_hash
=
basic_query_hash
(
%w[note]
,
query
)
...
...
@@ -49,11 +25,13 @@ module Elastic
query_hash
[
:highlight
]
=
highlight_options
(
options
[
:in
])
se
lf
.
__elasticsearch__
.
se
arch
(
query_hash
)
search
(
query_hash
)
end
def
self
.
confidentiality_filter
(
query_hash
,
current_user
)
return
query_hash
if
current_user
&&
current_user
.
full_private_access?
private
def
confidentiality_filter
(
query_hash
,
current_user
)
return
query_hash
if
current_user
&
.
full_private_access?
filter
=
{
bool:
{
...
...
@@ -74,7 +52,7 @@ module Elastic
should:
[
{
term:
{
"issue.author_id"
=>
current_user
.
id
}
},
{
term:
{
"issue.assignee_id"
=>
current_user
.
id
}
},
{
terms:
{
"project_id"
=>
current_user
.
authorized_projects
(
Gitlab
::
Access
::
REPORTER
).
pluck
(
:id
)
}
}
{
terms:
{
"project_id"
=>
current_user
.
authorized_projects
(
Gitlab
::
Access
::
REPORTER
).
pluck
_primary_key
}
}
]
}
}
...
...
ee/lib/elastic/latest/note_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
NoteInstanceProxy
<
ApplicationInstanceProxy
delegate
:noteable
,
to: :target
def
as_indexed_json
(
options
=
{})
data
=
{}
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
[
:id
,
:note
,
:project_id
,
:noteable_type
,
:noteable_id
,
:created_at
,
:updated_at
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
if
noteable
.
is_a?
(
Issue
)
data
[
'issue'
]
=
{
assignee_id:
noteable
.
assignee_ids
,
author_id:
noteable
.
author_id
,
confidential:
noteable
.
confidential
}
end
data
.
merge
(
generic_attributes
)
end
end
end
end
ee/lib/elastic/latest/project_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
ProjectClassProxy
<
ApplicationClassProxy
def
elastic_search
(
query
,
options:
{})
options
[
:in
]
=
%w(name^10 name_with_namespace^2 path_with_namespace path^9 description)
query_hash
=
basic_query_hash
(
options
[
:in
],
query
)
filters
=
[]
if
options
[
:namespace_id
]
filters
<<
{
terms:
{
namespace_id:
[
options
[
:namespace_id
]].
flatten
}
}
end
if
options
[
:non_archived
]
filters
<<
{
terms:
{
archived:
[
!
options
[
:non_archived
]].
flatten
}
}
end
if
options
[
:visibility_levels
]
filters
<<
{
terms:
{
visibility_level:
[
options
[
:visibility_levels
]].
flatten
}
}
end
if
options
[
:project_ids
]
filters
<<
{
bool:
project_ids_query
(
options
[
:current_user
],
options
[
:project_ids
],
options
[
:public_and_internal_projects
])
}
end
query_hash
[
:query
][
:bool
][
:filter
]
=
filters
query_hash
[
:sort
]
=
[
:_score
]
search
(
query_hash
)
end
end
end
end
ee/lib/elastic/latest/project_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
Latest
class
ProjectInstanceProxy
<
ApplicationInstanceProxy
TRACKED_FEATURE_SETTINGS
=
%w(
issues_access_level
merge_requests_access_level
snippets_access_level
wiki_access_level
repository_access_level
)
.
freeze
def
as_indexed_json
(
options
=
{})
# We don't use as_json(only: ...) because it calls all virtual and serialized attributtes
# https://gitlab.com/gitlab-org/gitlab-ee/issues/349
data
=
{}
[
:id
,
:name
,
:path
,
:description
,
:namespace_id
,
:created_at
,
:updated_at
,
:archived
,
:visibility_level
,
:last_activity_at
,
:name_with_namespace
,
:path_with_namespace
].
each
do
|
attr
|
data
[
attr
.
to_s
]
=
safely_read_attribute_for_elasticsearch
(
attr
)
end
# Set it as a parent in our `project => child` JOIN field
data
[
'join_field'
]
=
es_type
# ES6 is now single-type per index, so we implement our own typing
data
[
'type'
]
=
'project'
TRACKED_FEATURE_SETTINGS
.
each
do
|
feature
|
data
[
feature
]
=
target
.
project_feature
.
public_send
(
feature
)
# rubocop:disable GitlabSecurity/PublicSend
end
data
end
end
end
end
ee/lib/elastic/v12p1/issue_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
IssueClassProxy
=
Elastic
::
Latest
::
IssueClassProxy
end
end
ee/lib/elastic/v12p1/issue_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
IssueInstanceProxy
=
Elastic
::
Latest
::
IssueInstanceProxy
end
end
ee/lib/elastic/v12p1/merge_request_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
MergeRequestClassProxy
=
Elastic
::
Latest
::
MergeRequestClassProxy
end
end
ee/lib/elastic/v12p1/merge_request_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
MergeRequestInstanceProxy
=
Elastic
::
Latest
::
MergeRequestInstanceProxy
end
end
ee/lib/elastic/v12p1/milestone_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
MilestoneClassProxy
=
Elastic
::
Latest
::
MilestoneClassProxy
end
end
ee/lib/elastic/v12p1/milestone_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
MilestoneInstanceProxy
=
Elastic
::
Latest
::
MilestoneInstanceProxy
end
end
ee/lib/elastic/v12p1/note_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
NoteClassProxy
=
Elastic
::
Latest
::
NoteClassProxy
end
end
ee/lib/elastic/v12p1/note_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
NoteInstanceProxy
=
Elastic
::
Latest
::
NoteInstanceProxy
end
end
ee/lib/elastic/v12p1/project_class_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
ProjectClassProxy
=
Elastic
::
Latest
::
ProjectClassProxy
end
end
ee/lib/elastic/v12p1/project_instance_proxy.rb
0 → 100644
View file @
0355e90a
# frozen_string_literal: true
module
Elastic
module
V12p1
ProjectInstanceProxy
=
Elastic
::
Latest
::
ProjectInstanceProxy
end
end
ee/lib/gitlab/elastic/search_results.rb
View file @
0355e90a
...
...
@@ -199,7 +199,7 @@ module Gitlab
def
milestones
strong_memoize
(
:milestones
)
do
# Must pass 'issues' and 'merge_requests' to check
# if any of the features is available for projects in
Elastic::ApplicationSearch
#project_ids_query
# if any of the features is available for projects in
ApplicationClassProxy
#project_ids_query
# Otherwise it will ignore project_ids and return milestones
# from projects with milestones disabled.
options
=
base_options
...
...
ee/spec/models/concerns/elastic/issue_spec.rb
View file @
0355e90a
...
...
@@ -89,7 +89,7 @@ describe Issue, :elastic do
expected_hash
[
'assignee_id'
]
=
[
assignee
.
id
]
expect
(
issue
.
as_indexed_json
).
to
eq
(
expected_hash
)
expect
(
issue
.
__elasticsearch__
.
as_indexed_json
).
to
eq
(
expected_hash
)
end
it_behaves_like
'no results when the user cannot read cross project'
do
...
...
ee/spec/models/concerns/elastic/merge_request_spec.rb
View file @
0355e90a
...
...
@@ -61,7 +61,7 @@ describe MergeRequest, :elastic do
'type'
=>
merge_request
.
es_type
})
expect
(
merge_request
.
as_indexed_json
).
to
eq
(
expected_hash
)
expect
(
merge_request
.
__elasticsearch__
.
as_indexed_json
).
to
eq
(
expected_hash
)
end
it_behaves_like
'no results when the user cannot read cross project'
do
...
...
ee/spec/models/concerns/elastic/milestone_spec.rb
View file @
0355e90a
...
...
@@ -53,7 +53,7 @@ describe Milestone, :elastic do
'type'
=>
milestone
.
es_type
})
expect
(
milestone
.
as_indexed_json
).
to
eq
(
expected_hash
)
expect
(
milestone
.
__elasticsearch__
.
as_indexed_json
).
to
eq
(
expected_hash
)
end
it_behaves_like
'no results when the user cannot read cross project'
do
...
...
ee/spec/models/concerns/elastic/note_spec.rb
View file @
0355e90a
...
...
@@ -88,7 +88,7 @@ describe Note, :elastic do
type
)
expect
(
note
.
as_indexed_json
.
keys
).
to
eq
(
expected_hash_keys
)
expect
(
note
.
__elasticsearch__
.
as_indexed_json
.
keys
).
to
eq
(
expected_hash_keys
)
end
it
"does not create ElasticIndexerWorker job for system messages"
do
...
...
@@ -105,7 +105,7 @@ describe Note, :elastic do
Note
.
subclasses
.
each
do
|
note_class
|
expect
(
note_class
.
index_name
).
to
eq
(
Note
.
index_name
)
expect
(
note_class
.
document_type
).
to
eq
(
Note
.
document_type
)
expect
(
note_class
.
mappings
.
to_hash
).
to
eq
(
Note
.
mappings
.
to_hash
)
expect
(
note_class
.
__elasticsearch__
.
mappings
.
to_hash
).
to
eq
(
Note
.
__elasticsearch__
.
mappings
.
to_hash
)
end
end
...
...
ee/spec/models/concerns/elastic/project_spec.rb
View file @
0355e90a
...
...
@@ -159,6 +159,6 @@ describe Project, :elastic do
expected_hash
[
'name_with_namespace'
]
=
project
.
full_name
expected_hash
[
'path_with_namespace'
]
=
project
.
full_path
expect
(
project
.
as_indexed_json
).
to
eq
(
expected_hash
)
expect
(
project
.
__elasticsearch__
.
as_indexed_json
).
to
eq
(
expected_hash
)
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment