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
2ea35022
Commit
2ea35022
authored
Feb 03, 2021
by
Dmitry Gruzd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix opensearch for anonymous users
parent
92a06b97
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
208 additions
and
199 deletions
+208
-199
app/controllers/search_controller.rb
app/controllers/search_controller.rb
+1
-1
changelogs/unreleased/fix-opensearch.yml
changelogs/unreleased/fix-opensearch.yml
+5
-0
spec/controllers/search_controller_spec.rb
spec/controllers/search_controller_spec.rb
+202
-198
No files found.
app/controllers/search_controller.rb
View file @
2ea35022
...
@@ -9,7 +9,7 @@ class SearchController < ApplicationController
...
@@ -9,7 +9,7 @@ class SearchController < ApplicationController
around_action
:allow_gitaly_ref_name_caching
around_action
:allow_gitaly_ref_name_caching
before_action
:block_anonymous_global_searches
before_action
:block_anonymous_global_searches
,
except: :opensearch
skip_before_action
:authenticate_user!
skip_before_action
:authenticate_user!
requires_cross_project_access
if:
->
do
requires_cross_project_access
if:
->
do
search_term_present
=
params
[
:search
].
present?
||
params
[
:term
].
present?
search_term_present
=
params
[
:search
].
present?
||
params
[
:term
].
present?
...
...
changelogs/unreleased/fix-opensearch.yml
0 → 100644
View file @
2ea35022
---
title
:
Fix opensearch for anonymous users
merge_request
:
53056
author
:
type
:
fixed
spec/controllers/search_controller_spec.rb
View file @
2ea35022
...
@@ -5,292 +5,296 @@ require 'spec_helper'
...
@@ -5,292 +5,296 @@ require 'spec_helper'
RSpec
.
describe
SearchController
do
RSpec
.
describe
SearchController
do
include
ExternalAuthorizationServiceHelpers
include
ExternalAuthorizationServiceHelpers
let
(
:user
)
{
create
(
:user
)
}
context
'authorized user'
do
let
(
:user
)
{
create
(
:user
)
}
before
do
sign_in
(
user
)
end
shared_examples_for
'when the user cannot read cross project'
do
|
action
,
params
|
before
do
before
do
allow
(
Ability
).
to
receive
(
:allowed?
).
and_call_original
sign_in
(
user
)
allow
(
Ability
).
to
receive
(
:allowed?
)
.
with
(
user
,
:read_cross_project
,
:global
)
{
false
}
end
end
it
'blocks access without a project_id'
do
shared_examples_for
'when the user cannot read cross project'
do
|
action
,
params
|
get
action
,
params:
params
before
do
allow
(
Ability
).
to
receive
(
:allowed?
).
and_call_original
expect
(
response
).
to
have_gitlab_http_status
(
:forbidden
)
allow
(
Ability
).
to
receive
(
:allowed?
)
end
.
with
(
user
,
:read_cross_project
,
:global
)
{
false
}
end
it
'allows access with
a project_id'
do
it
'blocks access without
a project_id'
do
get
action
,
params:
params
.
merge
(
project_id:
create
(
:project
,
:public
).
id
)
get
action
,
params:
params
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:forbidden
)
end
end
end
shared_examples_for
'with external authorization service enabled'
do
|
action
,
params
|
it
'allows access with a project_id'
do
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
get
action
,
params:
params
.
merge
(
project_id:
create
(
:project
,
:public
).
id
)
let
(
:note
)
{
create
(
:note_on_issue
,
project:
project
)
}
before
do
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
en
able_external_authorization_service_check
en
d
end
end
it
'renders a 403 when no project is given'
do
shared_examples_for
'with external authorization service enabled'
do
|
action
,
params
|
get
action
,
params:
params
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let
(
:note
)
{
create
(
:note_on_issue
,
project:
project
)
}
expect
(
response
).
to
have_gitlab_http_status
(
:forbidden
)
before
do
end
enable_external_authorization_service_check
end
it
'renders a 200 when a project was set
'
do
it
'renders a 403 when no project is given
'
do
get
action
,
params:
params
.
merge
(
project_id:
project
.
id
)
get
action
,
params:
params
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:forbidden
)
end
end
end
describe
'GET #show'
do
it
'renders a 200 when a project was set'
do
it_behaves_like
'when the user cannot read cross project'
,
:show
,
{
search:
'hello'
}
do
get
action
,
params:
params
.
merge
(
project_id:
project
.
id
)
it
'still allows accessing the search page'
do
get
:show
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
end
end
end
end
it_behaves_like
'with external authorization service enabled'
,
:show
,
{
search:
'hello'
}
describe
'GET #show'
do
it_behaves_like
'when the user cannot read cross project'
,
:show
,
{
search:
'hello'
}
do
it
'still allows accessing the search page'
do
get
:show
context
'uses the right partials depending on scope'
do
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
using
RSpec
::
Parameterized
::
TableSyntax
end
render_views
let_it_be
(
:project
)
{
create
(
:project
,
:public
,
:repository
,
:wiki_repo
)
}
before
do
expect
(
::
Gitlab
::
GitalyClient
).
to
receive
(
:allow_ref_name_caching
).
and_call_original
end
end
subject
{
get
(
:show
,
params:
{
project_id:
project
.
id
,
scope:
scope
,
search:
'merge'
})
}
it_behaves_like
'with external authorization service enabled'
,
:show
,
{
search:
'hello'
}
where
(
:partial
,
:scope
)
do
context
'uses the right partials depending on scope'
do
'_blob'
|
:blobs
using
RSpec
::
Parameterized
::
TableSyntax
'_wiki_blob'
|
:wiki_blobs
render_views
'_commit'
|
:commits
end
with_them
do
let_it_be
(
:project
)
{
create
(
:project
,
:public
,
:repository
,
:wiki_repo
)
}
it
do
project_wiki
=
create
(
:project_wiki
,
project:
project
,
user:
user
)
create
(
:wiki_page
,
wiki:
project_wiki
,
title:
'merge'
,
content:
'merge'
)
expect
(
subject
).
to
render_template
(
"search/results/
#{
partial
}
"
)
before
do
expect
(
::
Gitlab
::
GitalyClient
).
to
receive
(
:allow_ref_name_caching
).
and_call_original
end
end
end
end
context
'global search'
do
subject
{
get
(
:show
,
params:
{
project_id:
project
.
id
,
scope:
scope
,
search:
'merge'
})
}
using
RSpec
::
Parameterized
::
TableSyntax
render_views
context
'when block_anonymous_global_searches is disabled'
do
where
(
:partial
,
:scope
)
do
before
do
'_blob'
|
:blobs
stub_feature_flags
(
block_anonymous_global_searches:
false
)
'_wiki_blob'
|
:wiki_blobs
'_commit'
|
:commits
end
end
it
'omits pipeline status from load'
do
with_them
do
project
=
create
(
:project
,
:public
)
it
do
expect
(
Gitlab
::
Cache
::
Ci
::
ProjectPipelineStatus
).
not_to
receive
(
:load_in_batch_for_projects
)
project_wiki
=
create
(
:project_wiki
,
project:
project
,
user:
user
)
create
(
:wiki_page
,
wiki:
project_wiki
,
title:
'merge'
,
content:
'merge'
)
get
:show
,
params:
{
scope:
'projects'
,
search:
project
.
name
}
expect
(
subject
).
to
render_template
(
"search/results/
#{
partial
}
"
)
end
expect
(
assigns
[
:search_objects
].
first
).
to
eq
project
end
end
end
context
'check search term length'
do
context
'global search'
do
let
(
:search_queries
)
do
using
RSpec
::
Parameterized
::
TableSyntax
char_limit
=
SearchService
::
SEARCH_CHAR_LIMIT
render_views
term_limit
=
SearchService
::
SEARCH_TERM_LIMIT
{
context
'when block_anonymous_global_searches is disabled'
do
chars_under_limit:
(
'a'
*
(
char_limit
-
1
)),
before
do
chars_over_limit:
(
'a'
*
(
char_limit
+
1
)),
stub_feature_flags
(
block_anonymous_global_searches:
false
)
terms_under_limit:
(
'abc '
*
(
term_limit
-
1
)),
terms_over_limit:
(
'abc '
*
(
term_limit
+
1
))
}
end
end
where
(
:string_name
,
:expectation
)
do
it
'omits pipeline status from load'
do
:chars_under_limit
|
:not_to_set_flash
project
=
create
(
:project
,
:public
)
:chars_over_limit
|
:set_chars_flash
expect
(
Gitlab
::
Cache
::
Ci
::
ProjectPipelineStatus
).
not_to
receive
(
:load_in_batch_for_projects
)
:terms_under_limit
|
:not_to_set_flash
:terms_over_limit
|
:set_terms_flash
get
:show
,
params:
{
scope:
'projects'
,
search:
project
.
name
}
expect
(
assigns
[
:search_objects
].
first
).
to
eq
project
end
end
with_them
do
context
'check search term length'
do
it
do
let
(
:search_queries
)
do
get
:show
,
params:
{
scope:
'projects'
,
search:
search_queries
[
string_name
]
}
char_limit
=
SearchService
::
SEARCH_CHAR_LIMIT
term_limit
=
SearchService
::
SEARCH_TERM_LIMIT
case
expectation
{
when
:not_to_set_flash
chars_under_limit:
(
'a'
*
(
char_limit
-
1
)),
expect
(
controller
).
not_to
set_flash
[
:alert
]
chars_over_limit:
(
'a'
*
(
char_limit
+
1
)),
when
:set_chars_flash
terms_under_limit:
(
'abc '
*
(
term_limit
-
1
)),
expect
(
controller
).
to
set_flash
[
:alert
].
to
(
/characters/
)
terms_over_limit:
(
'abc '
*
(
term_limit
+
1
))
when
:set_terms_flash
}
expect
(
controller
).
to
set_flash
[
:alert
].
to
(
/terms/
)
end
where
(
:string_name
,
:expectation
)
do
:chars_under_limit
|
:not_to_set_flash
:chars_over_limit
|
:set_chars_flash
:terms_under_limit
|
:not_to_set_flash
:terms_over_limit
|
:set_terms_flash
end
with_them
do
it
do
get
:show
,
params:
{
scope:
'projects'
,
search:
search_queries
[
string_name
]
}
case
expectation
when
:not_to_set_flash
expect
(
controller
).
not_to
set_flash
[
:alert
]
when
:set_chars_flash
expect
(
controller
).
to
set_flash
[
:alert
].
to
(
/characters/
)
when
:set_terms_flash
expect
(
controller
).
to
set_flash
[
:alert
].
to
(
/terms/
)
end
end
end
end
end
end
end
end
end
end
context
'when block_anonymous_global_searches is enabled'
do
context
'when block_anonymous_global_searches is enabled'
do
context
'for unauthenticated user'
do
context
'for unauthenticated user'
do
before
do
before
do
sign_out
(
user
)
sign_out
(
user
)
end
end
it
'redirects to login page'
do
it
'redirects to login page'
do
get
:show
,
params:
{
scope:
'projects'
,
search:
'*'
}
get
:show
,
params:
{
scope:
'projects'
,
search:
'*'
}
expect
(
response
).
to
redirect_to
new_user_session_path
expect
(
response
).
to
redirect_to
new_user_session_path
end
end
end
end
context
'for authenticated user'
do
context
'for authenticated user'
do
it
'succeeds'
do
it
'succeeds'
do
get
:show
,
params:
{
scope:
'projects'
,
search:
'*'
}
get
:show
,
params:
{
scope:
'projects'
,
search:
'*'
}
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
end
end
end
end
end
end
end
end
it
'finds issue comments'
do
it
'finds issue comments'
do
project
=
create
(
:project
,
:public
)
project
=
create
(
:project
,
:public
)
note
=
create
(
:note_on_issue
,
project:
project
)
note
=
create
(
:note_on_issue
,
project:
project
)
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
expect
(
assigns
[
:search_objects
].
first
).
to
eq
note
end
context
'unique users tracking'
do
expect
(
assigns
[
:search_objects
].
first
).
to
eq
note
before
do
allow
(
Gitlab
::
UsageDataCounters
::
HLLRedisCounter
).
to
receive
(
:track_event
)
end
end
it_behaves_like
'tracking unique hll events'
,
:search_track_unique_users
do
context
'unique users tracking'
do
subject
(
:request
)
{
get
:show
,
params:
{
scope:
'projects'
,
search:
'term'
}
}
before
do
allow
(
Gitlab
::
UsageDataCounters
::
HLLRedisCounter
).
to
receive
(
:track_event
)
end
let
(
:target_id
)
{
'i_search_total'
}
it_behaves_like
'tracking unique hll events'
,
:search_track_unique_users
do
let
(
:expected_type
)
{
instance_of
(
String
)
}
subject
(
:request
)
{
get
:show
,
params:
{
scope:
'projects'
,
search:
'term'
}
}
end
end
context
'on restricted projects'
do
let
(
:target_id
)
{
'i_search_total'
}
context
'when signed out'
do
let
(
:expected_type
)
{
instance_of
(
String
)
}
before
do
sign_out
(
user
)
end
end
end
it
"doesn't expose comments on issues"
do
context
'on restricted projects'
do
project
=
create
(
:project
,
:public
,
:issues_private
)
context
'when signed out'
do
note
=
create
(
:note_on_issue
,
project:
project
)
before
do
sign_out
(
user
)
end
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
it
"doesn't expose comments on issues"
do
project
=
create
(
:project
,
:public
,
:issues_private
)
note
=
create
(
:note_on_issue
,
project:
project
)
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
end
end
end
end
it
"doesn't expose comments on merge_requests"
do
it
"doesn't expose comments on merge_requests"
do
project
=
create
(
:project
,
:public
,
:merge_requests_private
)
project
=
create
(
:project
,
:public
,
:merge_requests_private
)
note
=
create
(
:note_on_merge_request
,
project:
project
)
note
=
create
(
:note_on_merge_request
,
project:
project
)
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
end
end
it
"doesn't expose comments on snippets"
do
it
"doesn't expose comments on snippets"
do
project
=
create
(
:project
,
:public
,
:snippets_private
)
project
=
create
(
:project
,
:public
,
:snippets_private
)
note
=
create
(
:note_on_project_snippet
,
project:
project
)
note
=
create
(
:note_on_project_snippet
,
project:
project
)
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
get
:show
,
params:
{
project_id:
project
.
id
,
scope:
'notes'
,
search:
note
.
note
}
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
expect
(
assigns
[
:search_objects
].
count
).
to
eq
(
0
)
end
end
end
end
end
end
describe
'GET #count'
do
describe
'GET #count'
do
it_behaves_like
'when the user cannot read cross project'
,
:count
,
{
search:
'hello'
,
scope:
'projects'
}
it_behaves_like
'when the user cannot read cross project'
,
:count
,
{
search:
'hello'
,
scope:
'projects'
}
it_behaves_like
'with external authorization service enabled'
,
:count
,
{
search:
'hello'
,
scope:
'projects'
}
it_behaves_like
'with external authorization service enabled'
,
:count
,
{
search:
'hello'
,
scope:
'projects'
}
it
'returns the result count for the given term and scope'
do
it
'returns the result count for the given term and scope'
do
create
(
:project
,
:public
,
name:
'hello world'
)
create
(
:project
,
:public
,
name:
'hello world'
)
create
(
:project
,
:public
,
name:
'foo bar'
)
create
(
:project
,
:public
,
name:
'foo bar'
)
get
:count
,
params:
{
search:
'hello'
,
scope:
'projects'
}
get
:count
,
params:
{
search:
'hello'
,
scope:
'projects'
}
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
json_response
).
to
eq
({
'count'
=>
'1'
})
expect
(
json_response
).
to
eq
({
'count'
=>
'1'
})
end
end
it
'raises an error if search term is missing'
do
it
'raises an error if search term is missing'
do
expect
do
expect
do
get
:count
,
params:
{
scope:
'projects'
}
get
:count
,
params:
{
scope:
'projects'
}
end
.
to
raise_error
(
ActionController
::
ParameterMissing
)
end
.
to
raise_error
(
ActionController
::
ParameterMissing
)
end
end
it
'raises an error if search scope is missing'
do
it
'raises an error if search scope is missing'
do
expect
do
expect
do
get
:count
,
params:
{
search:
'hello'
}
get
:count
,
params:
{
search:
'hello'
}
end
.
to
raise_error
(
ActionController
::
ParameterMissing
)
end
.
to
raise_error
(
ActionController
::
ParameterMissing
)
end
end
end
end
describe
'GET #autocomplete'
do
describe
'GET #autocomplete'
do
it_behaves_like
'when the user cannot read cross project'
,
:autocomplete
,
{
term:
'hello'
}
it_behaves_like
'when the user cannot read cross project'
,
:autocomplete
,
{
term:
'hello'
}
it_behaves_like
'with external authorization service enabled'
,
:autocomplete
,
{
term:
'hello'
}
it_behaves_like
'with external authorization service enabled'
,
:autocomplete
,
{
term:
'hello'
}
end
end
describe
'GET #opensearch'
do
describe
'#append_info_to_payload'
do
render_views
it
'appends search metadata for logging'
do
last_payload
=
nil
original_append_info_to_payload
=
controller
.
method
(
:append_info_to_payload
)
it
'renders xml'
do
expect
(
controller
).
to
receive
(
:append_info_to_payload
)
do
|
payload
|
get
:opensearch
,
format: :xml
original_append_info_to_payload
.
call
(
payload
)
last_payload
=
payload
end
doc
=
Nokogiri
::
XML
.
parse
(
response
.
body
)
get
:show
,
params:
{
scope:
'issues'
,
search:
'hello world'
,
group_id:
'123'
,
project_id:
'456'
,
confidential:
true
,
state:
true
,
force_search_results:
true
}
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
last_payload
[
:metadata
][
'meta.search.group_id'
]).
to
eq
(
'123'
)
expect
(
doc
.
css
(
'OpenSearchDescription ShortName'
).
text
).
to
eq
(
'GitLab'
)
expect
(
last_payload
[
:metadata
][
'meta.search.project_id'
]).
to
eq
(
'456'
)
expect
(
doc
.
css
(
'OpenSearchDescription *'
).
map
(
&
:name
)).
to
eq
(
%w[ShortName Description InputEncoding Image Url SearchForm]
)
expect
(
last_payload
[
:metadata
]).
not_to
have_key
(
'meta.search.search'
)
expect
(
last_payload
[
:metadata
][
'meta.search.scope'
]).
to
eq
(
'issues'
)
expect
(
last_payload
[
:metadata
][
'meta.search.force_search_results'
]).
to
eq
(
'true'
)
expect
(
last_payload
[
:metadata
][
'meta.search.filters.confidential'
]).
to
eq
(
'true'
)
expect
(
last_payload
[
:metadata
][
'meta.search.filters.state'
]).
to
eq
(
'true'
)
end
end
end
end
end
describe
'#append_info_to_payload'
do
context
'unauthorized user'
do
it
'appends search metadata for logging'
do
describe
'GET #opensearch'
do
last_payload
=
nil
render_views
original_append_info_to_payload
=
controller
.
method
(
:append_info_to_payload
)
expect
(
controller
).
to
receive
(
:append_info_to_payload
)
do
|
payload
|
it
'renders xml'
do
original_append_info_to_payload
.
call
(
payload
)
get
:opensearch
,
format: :xml
last_payload
=
payload
end
get
:show
,
params:
{
scope:
'issues'
,
search:
'hello world'
,
group_id:
'123'
,
project_id:
'456'
,
confidential:
true
,
state:
true
,
force_search_results:
true
}
doc
=
Nokogiri
::
XML
.
parse
(
response
.
body
)
expect
(
last_payload
[
:metadata
][
'meta.search.group_id'
]).
to
eq
(
'123'
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
last_payload
[
:metadata
][
'meta.search.project_id'
]).
to
eq
(
'456'
)
expect
(
doc
.
css
(
'OpenSearchDescription ShortName'
).
text
).
to
eq
(
'GitLab'
)
expect
(
last_payload
[
:metadata
]).
not_to
have_key
(
'meta.search.search'
)
expect
(
doc
.
css
(
'OpenSearchDescription *'
).
map
(
&
:name
)).
to
eq
(
%w[ShortName Description InputEncoding Image Url SearchForm]
)
expect
(
last_payload
[
:metadata
][
'meta.search.scope'
]).
to
eq
(
'issues'
)
end
expect
(
last_payload
[
:metadata
][
'meta.search.force_search_results'
]).
to
eq
(
'true'
)
expect
(
last_payload
[
:metadata
][
'meta.search.filters.confidential'
]).
to
eq
(
'true'
)
expect
(
last_payload
[
:metadata
][
'meta.search.filters.state'
]).
to
eq
(
'true'
)
end
end
end
end
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