Patch #39181 » 0001-API-compatibility-to-legacy-status-and-name-query-pa.patch
| app/controllers/users_controller.rb | ||
|---|---|---|
| 45 | 45 |
use_session = !request.format.csv? |
| 46 | 46 |
retrieve_query(UserQuery, use_session) |
| 47 | 47 | |
| 48 |
# API backwards compatibility: handle legacy status and name filter parameters |
|
| 49 |
unless request.format.html? |
|
| 50 |
if status_id = params[:status].presence |
|
| 51 |
@query.add_filter 'status', '=', [status_id] |
|
| 52 |
end |
|
| 53 |
if name = params[:name].presence |
|
| 54 |
@query.add_filter 'name', '~', [name] |
|
| 55 |
end |
|
| 56 |
end |
|
| 57 | ||
| 48 | 58 |
if @query.valid? |
| 49 | 59 |
scope = @query.results_scope |
| 50 | 60 | |
| app/models/user_query.rb | ||
|---|---|---|
| 51 | 51 |
type: :list_optional, |
| 52 | 52 |
values: ->{ Redmine::Twofa.available_schemes.map {|s| [I18n.t("twofa__#{s}__name"), s] } }
|
| 53 | 53 |
end |
| 54 |
add_available_filter "name", type: :text, label: :field_name_or_email_or_login |
|
| 54 | 55 |
add_available_filter "login", type: :string |
| 55 | 56 |
add_available_filter "firstname", type: :string |
| 56 | 57 |
add_available_filter "lastname", type: :string |
| ... | ... | |
| 165 | 166 | |
| 166 | 167 |
joins.any? ? joins.join(' ') : nil
|
| 167 | 168 |
end |
| 169 | ||
| 170 |
def sql_for_name_field(field, operator, value) |
|
| 171 |
case operator |
|
| 172 |
when '*' |
|
| 173 |
'1=1' |
|
| 174 |
when '!*' |
|
| 175 |
'1=0' |
|
| 176 |
else |
|
| 177 |
# match = (operator == '~') |
|
| 178 |
match = !operator.start_with?('!')
|
|
| 179 |
matching_operator = operator.sub /^\!/, '' |
|
| 180 |
name_sql = %w(login firstname lastname).map{|field| sql_for_field(:name, operator, value, User.table_name, field)}
|
|
| 181 | ||
| 182 |
emails = EmailAddress.table_name |
|
| 183 |
email_sql = <<-SQL |
|
| 184 |
#{match ? "EXISTS" : "NOT EXISTS"}
|
|
| 185 |
(SELECT 1 FROM #{emails} WHERE
|
|
| 186 |
#{emails}.user_id = #{User.table_name}.id AND
|
|
| 187 |
#{sql_for_field(:name, matching_operator, value, emails, 'address')})
|
|
| 188 |
SQL |
|
| 189 | ||
| 190 |
conditions = name_sql + [email_sql] |
|
| 191 |
op = match ? " OR " : " AND " |
|
| 192 |
"(#{conditions.map{|s| "(#{s})"}.join(op)})"
|
|
| 193 |
end |
|
| 194 | ||
| 195 |
end |
|
| 168 | 196 |
end |
| config/locales/en.yml | ||
|---|---|---|
| 1410 | 1410 |
twofa_text_group_disabled: "This setting is only effective when the global two factor authentication setting is set to 'optional'. Currently, two factor authentication is disabled." |
| 1411 | 1411 |
text_user_destroy_confirmation: "Are you sure you want to delete this user and remove all references to them? This cannot be undone. Often, locking a user instead of deleting them is the better solution. To confirm, please enter their login (%{login}) below."
|
| 1412 | 1412 |
text_project_destroy_enter_identifier: "To confirm, please enter the project's identifier (%{identifier}) below."
|
| 1413 |
field_name_or_email_or_login: Name, email or login |
|
| test/unit/user_query_test.rb | ||
|---|---|---|
| 108 | 108 |
end |
| 109 | 109 |
end |
| 110 | 110 | |
| 111 |
def test_name_or_email_or_login_filter |
|
| 112 |
[ |
|
| 113 |
['~', 'jsmith', [2]], |
|
| 114 |
['^', 'jsm', [2]], |
|
| 115 |
['$', 'ith', [2]], |
|
| 116 |
['~', 'john', [2]], |
|
| 117 |
['~', 'smith', [2]], |
|
| 118 |
['~', 'somenet', [1, 2, 3, 4]], |
|
| 119 |
['!~', 'somenet', [7, 8, 9]], |
|
| 120 |
['^', 'dlop', [3]], |
|
| 121 |
['$', 'bar', [7, 8, 9]], |
|
| 122 |
['=', 'bar', []], |
|
| 123 |
['=', 'someone@foo.bar', [7]], |
|
| 124 |
['*', '', [1, 2, 3, 4, 7, 8, 9]], |
|
| 125 |
['!*', '', []], |
|
| 126 |
].each do |op, string, result| |
|
| 127 |
q = UserQuery.new name: '_' |
|
| 128 |
q.add_filter('name', op, [string])
|
|
| 129 |
users = find_users_with_query q |
|
| 130 |
assert_equal result, users.map(&:id).sort, "#{op} #{string} should have found #{result}"
|
|
| 131 |
end |
|
| 132 |
end |
|
| 133 | ||
| 111 | 134 |
def test_group_filter |
| 112 | 135 |
q = UserQuery.new name: '_' |
| 113 | 136 |
q.add_filter('is_member_of_group', '=', ['10', '99'])
|