summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Provaznik <jprovaznik@gitlab.com>2019-03-16 08:19:02 +0100
committerJan Provaznik <jprovaznik@gitlab.com>2019-03-16 08:19:02 +0100
commita68c1cdc38ffe8d4fe21c1bf562c8456c354da7f (patch)
tree40626328888ffa46d3495f2f9dc219d1ee006e88
parentb53376592491cf2016fe68fecaf5f090cf4627b4 (diff)
parent27ac48c394780df923eeb94f3a7f47f6a5f4c649 (diff)
downloadgitlab-ce-a68c1cdc38ffe8d4fe21c1bf562c8456c354da7f.tar.gz
Merge branch 'siemens/gitlab-ce-feature/users-search-results' into users-search-resultsusers-search-results
-rw-r--r--app/controllers/search_controller.rb7
-rw-r--r--app/helpers/projects_helper.rb3
-rw-r--r--app/helpers/search_helper.rb10
-rw-r--r--app/services/search/global_service.rb3
-rw-r--r--app/services/search/group_service.rb6
-rw-r--r--app/services/search/project_service.rb7
-rw-r--r--app/views/search/_category.html.haml10
-rw-r--r--app/views/search/results/_user.html.haml10
-rw-r--r--changelogs/unreleased/feature-users-search-results.yml5
-rw-r--r--doc/api/search.md69
-rw-r--r--lib/api/helpers/search_helpers.rb6
-rw-r--r--lib/api/search.rb13
-rw-r--r--lib/gitlab/group_search_results.rb30
-rw-r--r--lib/gitlab/project_search_results.rb6
-rw-r--r--lib/gitlab/search_results.rb14
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/features/search/user_searches_for_users_spec.rb83
-rw-r--r--spec/lib/gitlab/group_search_results_spec.rb69
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb32
-rw-r--r--spec/lib/gitlab/search_results_spec.rb16
-rw-r--r--spec/requests/api/search_spec.rb79
21 files changed, 471 insertions, 10 deletions
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 1b22907c10f..90d4bc674d9 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -29,6 +29,7 @@ class SearchController < ApplicationController
@search_objects = search_service.search_objects
render_commits if @scope == 'commits'
+ eager_load_user_status if @scope == 'users'
check_single_commit_result
end
@@ -54,6 +55,12 @@ class SearchController < ApplicationController
@search_objects = prepare_commits_for_rendering(@search_objects)
end
+ def eager_load_user_status
+ return if Feature.disabled?(:users_search, default_enabled: true)
+
+ @search_objects = @search_objects.eager_load(:status) # rubocop:disable CodeReuse/ActiveRecord
+ end
+
def check_single_commit_result
if @search_results.single_commit_result?
only_commit = @search_results.objects('commits').first
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 2ac8ddc5244..5496aa4908c 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -364,7 +364,8 @@ module ProjectsHelper
blobs: :download_code,
commits: :download_code,
merge_requests: :read_merge_request,
- notes: [:read_merge_request, :download_code, :read_issue, :read_project_snippet]
+ notes: [:read_merge_request, :download_code, :read_issue, :read_project_snippet],
+ members: :read_project_member
)
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 0ee76a51f7d..8110377850b 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -201,4 +201,14 @@ module SearchHelper
def limited_count(count, limit = 1000)
count > limit ? "#{limit}+" : count
end
+
+ def search_tabs?(tab)
+ return false if Feature.disabled?(:users_search, default_enabled: true)
+
+ if @project
+ project_search_tabs?(:members)
+ else
+ can?(current_user, :read_users_list)
+ end
+ end
end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index d6af26d949d..f711839e389 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -23,7 +23,8 @@ module Search
def allowed_scopes
strong_memoize(:allowed_scopes) do
- %w[issues merge_requests milestones]
+ allowed_scopes = %w[issues merge_requests milestones]
+ allowed_scopes << 'users' if Feature.enabled?(:users_search, default_enabled: true)
end
end
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index 34803d005e3..6f3b5f00b86 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -11,6 +11,12 @@ module Search
@group = group
end
+ def execute
+ Gitlab::GroupSearchResults.new(
+ current_user, projects, group, params[:search], default_project_filter: default_project_filter
+ )
+ end
+
def projects
return Project.none unless group
return @projects if defined? @projects
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index f223c8be103..32d5cd7ddb2 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -16,7 +16,12 @@ module Search
end
def scope
- @scope ||= %w[notes issues merge_requests milestones wiki_blobs commits].delete(params[:scope]) { 'blobs' }
+ @scope ||= begin
+ allowed_scopes = %w[notes issues merge_requests milestones wiki_blobs commits]
+ allowed_scopes << 'users' if Feature.enabled?(:users_search, default_enabled: true)
+
+ allowed_scopes.delete(params[:scope]) { 'blobs' }
+ end
end
end
end
diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml
index aaf9b973cda..df408e5fb60 100644
--- a/app/views/search/_category.html.haml
+++ b/app/views/search/_category.html.haml
@@ -1,3 +1,11 @@
+- users = capture_haml do
+ - if search_tabs?(:members)
+ %li{ class: active_when(@scope == 'users') }
+ = link_to search_filter_path(scope: 'users') do
+ Users
+ %span.badge.badge-pill
+ = limited_count(@search_results.limited_users_count)
+
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
@@ -45,6 +53,7 @@
= _("Commits")
%span.badge.badge-pill
= @search_results.commits_count
+ = users
- elsif @show_snippets
%li{ class: active_when(@scope == 'snippet_blobs') }
@@ -78,3 +87,4 @@
= _("Milestones")
%span.badge.badge-pill
= limited_count(@search_results.limited_milestones_count)
+ = users
diff --git a/app/views/search/results/_user.html.haml b/app/views/search/results/_user.html.haml
new file mode 100644
index 00000000000..8060a1577e4
--- /dev/null
+++ b/app/views/search/results/_user.html.haml
@@ -0,0 +1,10 @@
+%ul.content-list
+ %li
+ .avatar-cell.d-none.d-sm-block
+ = user_avatar(user: user, user_name: user.name, css_class: 'd-none d-sm-inline avatar s40')
+ .user-info
+ = link_to user_path(user), class: 'd-none d-sm-inline' do
+ .item-title
+ = user.name
+ = user_status(user)
+ .cgray= user.to_reference
diff --git a/changelogs/unreleased/feature-users-search-results.yml b/changelogs/unreleased/feature-users-search-results.yml
new file mode 100644
index 00000000000..151d08bce12
--- /dev/null
+++ b/changelogs/unreleased/feature-users-search-results.yml
@@ -0,0 +1,5 @@
+---
+title: Add users search results to global search
+merge_request: 21197
+author: Alexis Reigel
+type: added
diff --git a/doc/api/search.md b/doc/api/search.md
index 330047e323b..6ee3d32d8bc 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -17,7 +17,7 @@ GET /search
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
-Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, snippet_blobs.
+Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, snippet_blobs, users.
The response depends on the requested scope.
@@ -281,6 +281,27 @@ Example response:
]
```
+### Scope: users
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=users&search=doe
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ }
+]
+```
+
## Group Search API
Search within the specified group.
@@ -297,7 +318,7 @@ GET /groups/:id/search
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
-Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones.
+Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
The response depends on the requested scope.
@@ -499,6 +520,27 @@ Example response:
]
```
+### Scope: users
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/3/search?scope=users&search=doe
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ }
+]
+```
+
## Project Search API
Search within the specified project.
@@ -515,7 +557,7 @@ GET /projects/:id/search
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
-Search the expression within the specified scope. Currently these scopes are supported: issues, merge_requests, milestones, notes, wiki_blobs, commits, blobs.
+Search the expression within the specified scope. Currently these scopes are supported: issues, merge_requests, milestones, notes, wiki_blobs, commits, blobs, users.
The response depends on the requested scope.
@@ -828,4 +870,25 @@ Example response:
]
```
+### Scope: users
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/6/search?scope=users&search=doe
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "John Doe1",
+ "username": "user1",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon",
+ "web_url": "http://localhost/user1"
+ }
+]
+```
+
[ce-41763]: https://gitlab.com/gitlab-org/gitlab-ce/issues/41763
diff --git a/lib/api/helpers/search_helpers.rb b/lib/api/helpers/search_helpers.rb
index 47fb5a36327..0e052e0e273 100644
--- a/lib/api/helpers/search_helpers.rb
+++ b/lib/api/helpers/search_helpers.rb
@@ -5,17 +5,17 @@ module API
module SearchHelpers
def self.global_search_scopes
# This is a separate method so that EE can redefine it.
- %w(projects issues merge_requests milestones snippet_titles snippet_blobs)
+ %w(projects issues merge_requests milestones snippet_titles snippet_blobs users)
end
def self.group_search_scopes
# This is a separate method so that EE can redefine it.
- %w(projects issues merge_requests milestones)
+ %w(projects issues merge_requests milestones users)
end
def self.project_search_scopes
# This is a separate method so that EE can redefine it.
- %w(issues merge_requests milestones notes wiki_blobs commits blobs)
+ %w(issues merge_requests milestones notes wiki_blobs commits blobs users)
end
end
end
diff --git a/lib/api/search.rb b/lib/api/search.rb
index f65e810bf90..60095300ea1 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -17,7 +17,8 @@ module API
blobs: Entities::Blob,
wiki_blobs: Entities::Blob,
snippet_titles: Entities::Snippet,
- snippet_blobs: Entities::Snippet
+ snippet_blobs: Entities::Snippet,
+ users: Entities::UserBasic
}.freeze
def search(additional_params = {})
@@ -51,6 +52,12 @@ module API
# Defining this method here as a noop allows us to easily extend it in
# EE, without having to modify this file directly.
end
+
+ def check_users_search_allowed!
+ if params[:scope].to_sym == :users && Feature.disabled?(:users_search, default_enabled: true)
+ render_api_error!({ error: _("Scope not supported with disabled 'users_search' feature!") }, 400)
+ end
+ end
end
resource :search do
@@ -67,6 +74,7 @@ module API
end
get do
verify_search_scope!
+ check_users_search_allowed!
present search, with: entity
end
@@ -87,6 +95,7 @@ module API
end
get ':id/(-/)search' do
verify_search_scope!
+ check_users_search_allowed!
present search(group_id: user_group.id), with: entity
end
@@ -106,6 +115,8 @@ module API
use :pagination
end
get ':id/(-/)search' do
+ check_users_search_allowed!
+
present search(project_id: user_project.id), with: entity
end
end
diff --git a/lib/gitlab/group_search_results.rb b/lib/gitlab/group_search_results.rb
new file mode 100644
index 00000000000..7255293b194
--- /dev/null
+++ b/lib/gitlab/group_search_results.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class GroupSearchResults < SearchResults
+ def initialize(current_user, limit_projects, group, query, default_project_filter: false, per_page: 20)
+ super(current_user, limit_projects, query, default_project_filter: default_project_filter, per_page: per_page)
+
+ @group = group
+ end
+
+ # rubocop:disable CodeReuse/ActiveRecord
+ def users
+ # 1: get all groups the current user has access to
+ groups = GroupsFinder.new(current_user).execute.joins(:users)
+
+ # 2: Get the group's whole hierarchy
+ group_users = @group.direct_and_indirect_users
+
+ # 3: get all users the current user has access to (->
+ # `SearchResults#users`), which also applies the query.
+ users = super
+
+ # 4: filter for users that belong to the previously selected groups
+ users
+ .where(id: group_users.select('id'))
+ .where(id: groups.select('members.user_id'))
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index a68f8801c2a..58f06b6708c 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -22,11 +22,17 @@ module Gitlab
paginated_blobs(wiki_blobs, page)
when 'commits'
Kaminari.paginate_array(commits).page(page).per(per_page)
+ when 'users'
+ users.page(page).per(per_page)
else
super(scope, page, false)
end
end
+ def users
+ super.where(id: @project.team.members) # rubocop:disable CodeReuse/ActiveRecord
+ end
+
def blobs_count
@blobs_count ||= blobs.count
end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 491148ec1a6..8988b9ad7be 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -32,6 +32,8 @@ module Gitlab
merge_requests.page(page).per(per_page)
when 'milestones'
milestones.page(page).per(per_page)
+ when 'users'
+ users.page(page).per(per_page)
else
Kaminari.paginate_array([]).page(page).per(per_page)
end
@@ -71,6 +73,12 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ # rubocop:disable CodeReuse/ActiveRecord
+ def limited_users_count
+ @limited_users_count ||= users.limit(count_limit).count
+ end
+ # rubocop:enable CodeReuse/ActiveRecord
+
def single_commit_result?
false
end
@@ -79,6 +87,12 @@ module Gitlab
1001
end
+ def users
+ return User.none unless Ability.allowed?(current_user, :read_users_list)
+
+ UsersFinder.new(current_user, search: query).execute
+ end
+
private
def projects
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 31b9af92805..00a45390a9c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6722,6 +6722,9 @@ msgstr ""
msgid "Scope"
msgstr ""
+msgid "Scope not supported with disabled 'users_search' feature!"
+msgstr ""
+
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
msgstr ""
diff --git a/spec/features/search/user_searches_for_users_spec.rb b/spec/features/search/user_searches_for_users_spec.rb
new file mode 100644
index 00000000000..3725143291d
--- /dev/null
+++ b/spec/features/search/user_searches_for_users_spec.rb
@@ -0,0 +1,83 @@
+require 'spec_helper'
+
+describe 'User searches for users' do
+ context 'when on the dashboard' do
+ it 'finds the user' do
+ create(:user, username: 'gob_bluth', name: 'Gob Bluth')
+
+ sign_in(create(:user))
+
+ visit dashboard_projects_path
+
+ fill_in 'search', with: 'gob'
+ click_button 'Go'
+
+ expect(page).to have_content('Users 1')
+
+ click_on('Users 1')
+
+ expect(page).to have_content('Gob Bluth')
+ expect(page).to have_content('@gob_bluth')
+ end
+ end
+
+ context 'when on the project page' do
+ it 'finds the user belonging to the project' do
+ project = create(:project)
+
+ user1 = create(:user, username: 'gob_bluth', name: 'Gob Bluth')
+ create(:project_member, :developer, user: user1, project: project)
+
+ user2 = create(:user, username: 'michael_bluth', name: 'Michael Bluth')
+ create(:project_member, :developer, user: user2, project: project)
+
+ create(:user, username: 'gob_2018', name: 'George Oscar Bluth')
+
+ sign_in(user1)
+
+ visit projects_path(project)
+
+ fill_in 'search', with: 'gob'
+ click_button 'Go'
+
+ expect(page).to have_content('Gob Bluth')
+ expect(page).to have_content('@gob_bluth')
+
+ expect(page).not_to have_content('Michael Bluth')
+ expect(page).not_to have_content('@michael_bluth')
+
+ expect(page).not_to have_content('George Oscar Bluth')
+ expect(page).not_to have_content('@gob_2018')
+ end
+ end
+
+ context 'when on the group page' do
+ it 'finds the user belonging to the group' do
+ group = create(:group)
+
+ user1 = create(:user, username: 'gob_bluth', name: 'Gob Bluth')
+ create(:group_member, :developer, user: user1, group: group)
+
+ user2 = create(:user, username: 'michael_bluth', name: 'Michael Bluth')
+ create(:group_member, :developer, user: user2, group: group)
+
+ create(:user, username: 'gob_2018', name: 'George Oscar Bluth')
+
+ sign_in(user1)
+
+ visit group_path(group)
+
+ fill_in 'search', with: 'gob'
+ click_button 'Go'
+
+ expect(page).to have_content('Gob Bluth')
+ expect(page).to have_content('@gob_bluth')
+
+ expect(page).not_to have_content('Michael Bluth')
+ expect(page).not_to have_content('@michael_bluth')
+
+ expect(page).not_to have_content('George Oscar Bluth')
+ expect(page).not_to have_content('@gob_2018')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/group_search_results_spec.rb b/spec/lib/gitlab/group_search_results_spec.rb
new file mode 100644
index 00000000000..2734fcef0a0
--- /dev/null
+++ b/spec/lib/gitlab/group_search_results_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Gitlab::GroupSearchResults do
+ let(:user) { create(:user) }
+
+ describe 'user search' do
+ let(:group) { create(:group) }
+
+ it 'returns the users belonging to the group matching the search query' do
+ user1 = create(:user, username: 'gob_bluth')
+ create(:group_member, :developer, user: user1, group: group)
+
+ user2 = create(:user, username: 'michael_bluth')
+ create(:group_member, :developer, user: user2, group: group)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, anything, group, 'gob').objects('users')
+
+ expect(result).to eq [user1]
+ end
+
+ it 'returns the user belonging to the subgroup matching the search query', :nested_groups do
+ user1 = create(:user, username: 'gob_bluth')
+ subgroup = create(:group, parent: group)
+ create(:group_member, :developer, user: user1, group: subgroup)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, anything, group, 'gob').objects('users')
+
+ expect(result).to eq [user1]
+ end
+
+ it 'returns the user belonging to the parent group matching the search query', :nested_groups do
+ user1 = create(:user, username: 'gob_bluth')
+ parent_group = create(:group, children: [group])
+ create(:group_member, :developer, user: user1, group: parent_group)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, anything, group, 'gob').objects('users')
+
+ expect(result).to eq [user1]
+ end
+
+ it 'does not return the user belonging to the private subgroup', :nested_groups do
+ user1 = create(:user, username: 'gob_bluth')
+ subgroup = create(:group, :private, parent: group)
+ create(:group_member, :developer, user: user1, group: subgroup)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, anything, group, 'gob').objects('users')
+
+ expect(result).to eq []
+ end
+
+ it 'does not return the user belonging to an unrelated group' do
+ user = create(:user, username: 'gob_bluth')
+ unrelated_group = create(:group)
+ create(:group_member, :developer, user: user, group: unrelated_group)
+
+ result = described_class.new(user, anything, group, 'gob').objects('users')
+
+ expect(result).to eq []
+ end
+ end
+end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index 6831274d37c..4a41d5cf51e 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -412,4 +412,36 @@ describe Gitlab::ProjectSearchResults do
end
end
end
+
+ describe 'user search' do
+ it 'returns the user belonging to the project matching the search query' do
+ project = create(:project)
+
+ user1 = create(:user, username: 'gob_bluth')
+ create(:project_member, :developer, user: user1, project: project)
+
+ user2 = create(:user, username: 'michael_bluth')
+ create(:project_member, :developer, user: user2, project: project)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, project, 'gob').objects('users')
+
+ expect(result).to eq [user1]
+ end
+
+ it 'returns the user belonging to the group matching the search query' do
+ group = create(:group)
+ project = create(:project, namespace: group)
+
+ user1 = create(:user, username: 'gob_bluth')
+ create(:group_member, :developer, user: user1, group: group)
+
+ create(:user, username: 'gob_2018')
+
+ result = described_class.new(user, project, 'gob').objects('users')
+
+ expect(result).to eq [user1]
+ end
+ end
end
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 87288baedb0..4b57eecff93 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -121,6 +121,22 @@ describe Gitlab::SearchResults do
results.objects('issues')
end
end
+
+ describe '#users' do
+ it 'does not call the UsersFinder when the current_user is not allowed to read users list' do
+ allow(Ability).to receive(:allowed?).and_return(false)
+
+ expect(UsersFinder).not_to receive(:new).with(user, search: 'foo').and_call_original
+
+ results.objects('users')
+ end
+
+ it 'calls the UsersFinder' do
+ expect(UsersFinder).to receive(:new).with(user, search: 'foo').and_call_original
+
+ results.objects('users')
+ end
+ end
end
it 'does not list issues on private projects' do
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index c48ca832c85..49672591b3b 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -77,6 +77,28 @@ describe API::Search do
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
+ context 'for users scope' do
+ before do
+ create(:user, name: 'billy')
+
+ get api('/search', user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
+
+ context 'when users search feature is disabled' do
+ before do
+ allow(Feature).to receive(:disabled?).with(:users_search, default_enabled: true).and_return(true)
+
+ get api('/search', user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it 'returns 400 error' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+ end
+ end
+
context 'for snippet_titles scope' do
before do
create(:snippet, :public, title: 'awesome snippet', content: 'snippet content')
@@ -192,6 +214,40 @@ describe API::Search do
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
+
+ context 'for users scope' do
+ before do
+ user = create(:user, name: 'billy')
+ create(:group_member, :developer, user: user, group: group)
+
+ get api("/groups/#{group.id}/search", user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
+
+ context 'when users search feature is disabled' do
+ before do
+ allow(Feature).to receive(:disabled?).with(:users_search, default_enabled: true).and_return(true)
+
+ get api("/groups/#{group.id}/search", user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it 'returns 400 error' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+ end
+ end
+
+ context 'for users scope with group path as id' do
+ before do
+ user1 = create(:user, name: 'billy')
+ create(:group_member, :developer, user: user1, group: group)
+
+ get api("/groups/#{CGI.escape(group.full_path)}/search", user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
+ end
end
end
@@ -269,6 +325,29 @@ describe API::Search do
it_behaves_like 'response is correct', schema: 'public_api/v4/milestones'
end
+ context 'for users scope' do
+ before do
+ user1 = create(:user, name: 'billy')
+ create(:project_member, :developer, user: user1, project: project)
+
+ get api("/projects/#{project.id}/search", user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it_behaves_like 'response is correct', schema: 'public_api/v4/user/basics'
+
+ context 'when users search feature is disabled' do
+ before do
+ allow(Feature).to receive(:disabled?).with(:users_search, default_enabled: true).and_return(true)
+
+ get api("/projects/#{project.id}/search", user), params: { scope: 'users', search: 'billy' }
+ end
+
+ it 'returns 400 error' do
+ expect(response).to have_gitlab_http_status(400)
+ end
+ end
+ end
+
context 'for notes scope' do
before do
create(:note_on_merge_request, project: project, note: 'awesome note')