Commit f8530580 authored by Yar's avatar Yar Committed by Yar

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.
parent 6893bccd
...@@ -41,6 +41,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -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 - 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) - 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) - 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) ## 8.13.2 (2016-10-31)
......
...@@ -3,7 +3,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -3,7 +3,7 @@ class Admin::UsersController < Admin::ApplicationController
def index def index
@users = User.order_name_asc.filter(params[:filter]) @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.sort(@sort = params[:sort])
@users = @users.page(params[:page]) @users = @users.page(params[:page])
end end
......
...@@ -258,6 +258,24 @@ class User < ActiveRecord::Base ...@@ -258,6 +258,24 @@ class User < ActiveRecord::Base
) )
end 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) def by_login(login)
return nil unless login return nil unless login
......
...@@ -599,6 +599,80 @@ describe User, models: true do ...@@ -599,6 +599,80 @@ describe User, models: true do
end end
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 describe 'by_username_or_id' do
let(:user1) { create(:user, username: 'foo') } let(:user1) { create(:user, username: 'foo') }
......
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