diff --git a/changelogs/unreleased/42669-allow-order_by-users-in-gitlab-api.yml b/changelogs/unreleased/42669-allow-order_by-users-in-gitlab-api.yml new file mode 100644 index 00000000000..24fcc38ee0e --- /dev/null +++ b/changelogs/unreleased/42669-allow-order_by-users-in-gitlab-api.yml @@ -0,0 +1,5 @@ +--- +title: Add sorting options for /users API (admin only) +merge_request: 16945 +author: +type: added diff --git a/doc/api/users.md b/doc/api/users.md index 1da6fcf297d..2082e45756a 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -51,6 +51,11 @@ GET /users?blocked=true GET /users ``` +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `order_by` | string | no | Return projects ordered by `id`, `name`, `username`, `created_at`, or `updated_at` fields. Default is `id` | +| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` | + ```json [ { diff --git a/lib/api/users.rb b/lib/api/users.rb index c7c2aa280d5..3cc12724b8a 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -18,6 +18,14 @@ module API User.find_by(id: id) || not_found!('User') end + def reorder_users(users) + if params[:order_by] && params[:sort] + users.reorder(params[:order_by] => params[:sort]) + else + users + end + end + params :optional_attributes do optional :skype, type: String, desc: 'The Skype username' optional :linkedin, type: String, desc: 'The LinkedIn username' @@ -35,6 +43,13 @@ module API optional :avatar, type: File, desc: 'Avatar image for user' all_or_none_of :extern_uid, :provider end + + params :sort_params do + optional :order_by, type: String, values: %w[id name username created_at updated_at], + default: 'id', desc: 'Return users ordered by a field' + optional :sort, type: String, values: %w[asc desc], default: 'desc', + desc: 'Return users sorted in ascending and descending order' + end end desc 'Get the list of users' do @@ -53,16 +68,18 @@ module API optional :created_before, type: DateTime, desc: 'Return users created before the specified time' all_or_none_of :extern_uid, :provider + use :sort_params use :pagination end get do authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?) unless current_user&.admin? - params.except!(:created_after, :created_before) + params.except!(:created_after, :created_before, :order_by, :sort) end users = UsersFinder.new(current_user, params).execute + users = reorder_users(users) authorized = can?(current_user, :read_users_list) diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 2428e63e149..f406d2ffb22 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -199,6 +199,24 @@ describe API::Users do expect(json_response.size).to eq(1) expect(json_response.first['username']).to eq(user.username) end + + it 'returns the correct order when sorted by id' do + admin + user + + get api('/users', admin), { order_by: 'id', sort: 'asc' } + + expect(response).to match_response_schema('public_api/v4/user/admins') + expect(json_response.size).to eq(2) + expect(json_response.first['id']).to eq(admin.id) + expect(json_response.last['id']).to eq(user.id) + end + + it 'returns 400 when provided incorrect sort params' do + get api('/users', admin), { order_by: 'magic', sort: 'asc' } + + expect(response).to have_gitlab_http_status(400) + end end end