diff options
author | Yar <mrrezaque@gmail.com> | 2016-10-25 20:14:58 +0300 |
---|---|---|
committer | Yar <YarTheGreat@gmail.com> | 2016-11-01 17:58:03 +0300 |
commit | f8530580100f56fe3bef5f3a73d3e543b038f98f (patch) | |
tree | 63b63eb3fc037cd92a6c04fa0aa328066da305e7 | |
parent | 6893bccd06320c22162037047ab90fc90cfa0246 (diff) | |
download | gitlab-ce-f8530580100f56fe3bef5f3a73d3e543b038f98f.tar.gz |
Allow to search for user by secondary email address in the admin interface
It is not possible to search for a user by his secondary email address in
the Users search bar in the admin interface(/admin/users). A use-case could
be that an admin wants to remove a specific secondary email address of an
user, because it interferes with another user. Issue #23761
This commit adds ability to search not only by main email, but also
by any secondary email in the admin interface.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | app/controllers/admin/users_controller.rb | 2 | ||||
-rw-r--r-- | app/models/user.rb | 18 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 74 |
4 files changed, 94 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 26f0a0eb1c1..792e5b48891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Please view this file on the master branch, on stable branches it's out of date. - Shortened merge request modal to let clipboard button not overlap - In all filterable drop downs, put input field in focus only after load is complete (Ido @leibo) - Improve search query parameter naming in /admin/users !7115 (YarNayar) +- Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar) ## 8.13.2 (2016-10-31) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 57efa899694..bb912ed10cc 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -3,7 +3,7 @@ class Admin::UsersController < Admin::ApplicationController def index @users = User.order_name_asc.filter(params[:filter]) - @users = @users.search(params[:search_query]) if params[:search_query].present? + @users = @users.search_with_secondary_emails(params[:search_query]) if params[:search_query].present? @users = @users.sort(@sort = params[:sort]) @users = @users.page(params[:page]) end diff --git a/app/models/user.rb b/app/models/user.rb index e2a97c3a757..af3c0b7dc02 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -258,6 +258,24 @@ class User < ActiveRecord::Base ) end + # searches user by given pattern + # it compares name, email, username fields and user's secondary emails with given pattern + # This method uses ILIKE on PostgreSQL and LIKE on MySQL. + + def search_with_secondary_emails(query) + table = arel_table + email_table = Email.arel_table + pattern = "%#{query}%" + matched_by_emails_user_ids = email_table.project(email_table[:user_id]).where(email_table[:email].matches(pattern)) + + where( + table[:name].matches(pattern). + or(table[:email].matches(pattern)). + or(table[:username].matches(pattern)). + or(table[:id].in(matched_by_emails_user_ids)) + ) + end + def by_login(login) return nil unless login diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 10c39b90212..d1ed774a914 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -599,6 +599,80 @@ describe User, models: true do end end + describe '.search_with_secondary_emails' do + def search_with_secondary_emails(query) + described_class.search_with_secondary_emails(query) + end + + let!(:user) { create(:user) } + let!(:email) { create(:email) } + + it 'returns users with a matching name' do + expect(search_with_secondary_emails(user.name)).to eq([user]) + end + + it 'returns users with a partially matching name' do + expect(search_with_secondary_emails(user.name[0..2])).to eq([user]) + end + + it 'returns users with a matching name regardless of the casing' do + expect(search_with_secondary_emails(user.name.upcase)).to eq([user]) + end + + it 'returns users with a matching email' do + expect(search_with_secondary_emails(user.email)).to eq([user]) + end + + it 'returns users with a partially matching email' do + expect(search_with_secondary_emails(user.email[0..2])).to eq([user]) + end + + it 'returns users with a matching email regardless of the casing' do + expect(search_with_secondary_emails(user.email.upcase)).to eq([user]) + end + + it 'returns users with a matching username' do + expect(search_with_secondary_emails(user.username)).to eq([user]) + end + + it 'returns users with a partially matching username' do + expect(search_with_secondary_emails(user.username[0..2])).to eq([user]) + end + + it 'returns users with a matching username regardless of the casing' do + expect(search_with_secondary_emails(user.username.upcase)).to eq([user]) + end + + it 'returns users with a matching whole secondary email' do + expect(search_with_secondary_emails(email.email)).to eq([email.user]) + end + + it 'returns users with a matching part of secondary email' do + expect(search_with_secondary_emails(email.email[1..4])).to eq([email.user]) + end + + it 'return users with a matching part of secondary email regardless of case' do + expect(search_with_secondary_emails(email.email[1..4].upcase)).to eq([email.user]) + expect(search_with_secondary_emails(email.email[1..4].downcase)).to eq([email.user]) + expect(search_with_secondary_emails(email.email[1..4].capitalize)).to eq([email.user]) + end + + it 'returns multiple users with matching secondary emails' do + email1 = create(:email, email: '1_testemail@example.com') + email2 = create(:email, email: '2_testemail@example.com') + email3 = create(:email, email: 'other@email.com') + email3.user.update_attributes!(email: 'another@mail.com') + + expect( + search_with_secondary_emails('testemail@example.com').map(&:id) + ).to include(email1.user.id, email2.user.id) + + expect( + search_with_secondary_emails('testemail@example.com').map(&:id) + ).not_to include(email3.user.id) + end + end + describe 'by_username_or_id' do let(:user1) { create(:user, username: 'foo') } |