Commit 924d5fee authored by Douwe Maan's avatar Douwe Maan

Merge branch 'feature/user-datetime-search-api-mysql-ee' into 'master'

[CE Port] Add creation time filters to user search API for admins

See merge request !2386
parents f40b0495 98ae75cf
module CreatedAtFilter
def by_created_at(items)
items = items.created_before(params[:created_before]) if params[:created_before].present?
items = items.created_after(params[:created_after]) if params[:created_after].present?
items
end
end
......@@ -19,6 +19,8 @@
# iids: integer[]
#
class IssuableFinder
include CreatedAtFilter
NONE = '0'.freeze
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page].freeze
......@@ -36,6 +38,7 @@ class IssuableFinder
def execute
items = init_collection
items = by_scope(items)
items = by_created_at(items)
items = by_state(items)
items = by_group(items)
items = by_search(items)
......@@ -47,7 +50,6 @@ class IssuableFinder
items = by_iids(items)
items = by_milestone(items)
items = by_label(items)
items = by_created_at(items)
# Filtering by project HAS TO be the last because we use the project IDs yielded by the issuable query thus far
items = by_project(items)
......@@ -438,18 +440,6 @@ class IssuableFinder
params[:non_archived].present? ? items.non_archived : items
end
def by_created_at(items)
if params[:created_after].present?
items = items.where(items.klass.arel_table[:created_at].gteq(params[:created_after]))
end
if params[:created_before].present?
items = items.where(items.klass.arel_table[:created_at].lteq(params[:created_before]))
end
items
end
def current_user_related?
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
end
......
......@@ -15,6 +15,8 @@
# skip_ldap: boolean
#
class UsersFinder
include CreatedAtFilter
attr_accessor :current_user, :params
def initialize(current_user, params = {})
......@@ -30,6 +32,7 @@ class UsersFinder
users = by_active(users)
users = by_external_identity(users)
users = by_external(users)
users = by_created_at(users)
users = by_non_ldap(users)
users
......
module CreatedAtFilterable
extend ActiveSupport::Concern
included do
scope :created_before, ->(date) { where(scoped_table[:created_at].lteq(date)) }
scope :created_after, ->(date) { where(scoped_table[:created_at].gteq(date)) }
def self.scoped_table
arel_table.alias(table_name)
end
end
end
......@@ -13,6 +13,7 @@ class Issue < ActiveRecord::Base
include FasterCacheKeys
include RelativePositioning
include IgnorableColumn
include CreatedAtFilterable
ignore_column :position
......@@ -60,8 +61,6 @@ class Issue < ActiveRecord::Base
scope :order_weight_desc, -> { reorder('weight IS NOT NULL, weight DESC') }
scope :order_weight_asc, -> { reorder('weight ASC') }
scope :created_after, -> (datetime) { where("created_at >= ?", datetime) }
scope :preload_associations, -> { preload(:labels, project: :namespace) }
after_save :expire_etag_cache
......
......@@ -6,6 +6,7 @@ class MergeRequest < ActiveRecord::Base
include Sortable
include Elastic::MergeRequestsSearch
include IgnorableColumn
include CreatedAtFilterable
ignore_column :position
......
......@@ -12,6 +12,7 @@ class User < ActiveRecord::Base
include TokenAuthenticatable
include IgnorableColumn
include FeatureGate
include CreatedAtFilterable
prepend EE::GeoAwareAvatar
prepend EE::User
......
---
title: Add creation time filters to user search API for admins
merge_request: 12682
author:
......@@ -29,7 +29,8 @@ module Gitlab
#{config.root}/app/models/project_services
#{config.root}/app/workers/concerns
#{config.root}/app/services/concerns
#{config.root}/app/uploaders/concerns))
#{config.root}/app/uploaders/concerns
#{config.root}/app/finders/concerns))
config.generators.templates.push("#{config.root}/generator_templates")
......
......@@ -148,6 +148,12 @@ GET /users?extern_uid=1234567&provider=github
You can search for users who are external with: `/users?external=true`
You can search users by creation date time range with:
```
GET /users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060
```
## Single user
Get a single user.
......
......@@ -51,6 +51,8 @@ module API
optional :active, type: Boolean, default: false, desc: 'Filters only active users'
optional :external, type: Boolean, default: false, desc: 'Filters only external users'
optional :blocked, type: Boolean, default: false, desc: 'Filters only blocked users'
optional :created_after, type: DateTime, desc: 'Return users created after the specified time'
optional :created_before, type: DateTime, desc: 'Return users created before the specified time'
all_or_none_of :extern_uid, :provider
# EE
......@@ -61,6 +63,10 @@ module API
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)
end
users = UsersFinder.new(current_user, params).execute
authorized = can?(current_user, :read_users_list)
......
......@@ -61,6 +61,17 @@ describe UsersFinder do
expect(users).to contain_exactly(user, user1, user2, omniauth_user)
end
end
it 'filters by created_at' do
filtered_user_before = create(:user, created_at: 3.days.ago)
filtered_user_after = create(:user, created_at: Time.now + 3.days)
users = described_class.new(user,
created_after: 2.days.ago,
created_before: Time.now + 2.days).execute
expect(users.map(&:username)).not_to include([filtered_user_before.username, filtered_user_after.username])
end
end
context 'with an admin user' do
......
......@@ -163,6 +163,35 @@ describe API::Users do
expect(response).to have_http_status(400)
end
it "returns a user created before a specific date" do
user = create(:user, created_at: Date.new(2000, 1, 1))
get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)
expect(response).to have_http_status(200)
expect(json_response.size).to eq(1)
expect(json_response.first['username']).to eq(user.username)
end
it "returns no users created before a specific date" do
create(:user, created_at: Date.new(2001, 1, 1))
get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)
expect(response).to have_http_status(200)
expect(json_response.size).to eq(0)
end
it "returns users created before and after a specific date" do
user = create(:user, created_at: Date.new(2001, 1, 1))
get api("/users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060", admin)
expect(response).to have_http_status(200)
expect(json_response.size).to eq(1)
expect(json_response.first['username']).to eq(user.username)
end
end
context "when authenticated and ldap is enabled" do
......
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