Commit 16d98f42 authored by Sean McGivern's avatar Sean McGivern 🎄

Merge branch 'Allow-admin-to-search-for-user-by-secondary-email-address' into 'master'

Allow admin to search for user by secondary email address

Closes #23761

See merge request !7115
parents b58d7cea f8530580
Pipeline #4829677 failed with stages
in 58 minutes and 12 seconds
...@@ -43,6 +43,8 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -43,6 +43,8 @@ Please view this file on the master branch, on stable branches it's out of date.
- Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov)
- 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)
- Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar)
## 8.13.3 ## 8.13.3
......
...@@ -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[:name]) if params[:name].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
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
= hidden_field_tag "filter", h(params[:filter]) = hidden_field_tag "filter", h(params[:filter])
.search-holder .search-holder
.search-field-holder .search-field-holder
= search_field_tag :name, params[:name], placeholder: 'Search by name, email or username', class: 'form-control search-text-input js-search-input', spellcheck: false = search_field_tag :search_query, params[:search_query], placeholder: 'Search by name, email or username', class: 'form-control search-text-input js-search-input', spellcheck: false
= icon("search", class: "search-icon") = icon("search", class: "search-icon")
.dropdown .dropdown
- toggle_text = if @sort.present? then sort_options_hash[@sort] else sort_title_name end - toggle_text = if @sort.present? then sort_options_hash[@sort] else sort_title_name end
......
...@@ -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