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 |
if group_id = params[:group_id].presence |
|
57 |
@query.add_filter 'is_member_of_group', '=', [group_id] |
|
58 |
end |
|
59 |
end |
|
60 | ||
48 | 61 |
if @query.valid? |
49 | 62 |
scope = @query.results_scope |
50 | 63 |
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/integration/api_test/users_test.rb | ||
---|---|---|
82 | 82 |
end |
83 | 83 |
end |
84 | 84 | |
85 |
test "GET /users.json with legacy filter params" do |
|
86 |
get '/users.json', :headers => credentials('admin'), params: { status: 3 } |
|
87 |
assert_response :success |
|
88 |
json = ActiveSupport::JSON.decode(response.body) |
|
89 |
assert json.key?('users') |
|
90 |
users = User.where(status: 3) |
|
91 |
assert_equal users.size, json['users'].size |
|
92 | ||
93 |
get '/users.json', :headers => credentials('admin'), params: { name: 'jsmith' } |
|
94 |
assert_response :success |
|
95 |
json = ActiveSupport::JSON.decode(response.body) |
|
96 |
assert json.key?('users') |
|
97 |
assert_equal 1, json['users'].size |
|
98 |
assert_equal 2, json['users'][0]['id'] |
|
99 | ||
100 |
get '/users.json', :headers => credentials('admin'), params: { group_id: '10' } |
|
101 |
assert_response :success |
|
102 |
json = ActiveSupport::JSON.decode(response.body) |
|
103 |
assert json.key?('users') |
|
104 |
assert_equal 1, json['users'].size |
|
105 |
assert_equal 8, json['users'][0]['id'] |
|
106 | ||
107 |
# there should be an implicit filter for status = 1 |
|
108 |
User.where(id: [2, 8]).update_all status: 3 |
|
109 | ||
110 |
get '/users.json', :headers => credentials('admin'), params: { name: 'jsmith' } |
|
111 |
assert_response :success |
|
112 |
json = ActiveSupport::JSON.decode(response.body) |
|
113 |
assert json.key?('users') |
|
114 |
assert_equal 0, json['users'].size |
|
115 | ||
116 |
get '/users.json', :headers => credentials('admin'), params: { group_id: '10' } |
|
117 |
assert_response :success |
|
118 |
json = ActiveSupport::JSON.decode(response.body) |
|
119 |
assert json.key?('users') |
|
120 |
assert_equal 0, json['users'].size |
|
121 |
end |
|
122 | ||
85 | 123 |
test "GET /users/:id.xml should return the user" do |
86 | 124 |
Redmine::Configuration.with 'avatar_server_url' => 'https://gravatar.com' do |
87 | 125 |
with_settings :gravatar_enabled => '1', :gravatar_default => 'robohash' do |
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']) |
- « Previous
- 1
- 2
- Next »