Merge branch 'query-users-by-extern-uid' into 'master'

Implement search by extern_uid in Users API

See merge request !10509
This commit is contained in:
Robert Speicher 2017-04-19 19:50:38 +00:00
commit 93e23a5d71
5 changed files with 59 additions and 8 deletions

View File

@ -7,6 +7,8 @@ class Identity < ActiveRecord::Base
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
validates :user_id, uniqueness: { scope: :provider }
scope :with_extern_uid, ->(provider, extern_uid) { where(extern_uid: extern_uid, provider: provider) }
def ldap?
provider.starts_with?('ldap')
end

View File

@ -0,0 +1,4 @@
---
title: Implement search by extern_uid in Users API
merge_request: 10509
author: Robin Bobbitt

View File

@ -132,6 +132,18 @@ For example:
GET /users?username=jack_smith
```
You can also lookup users by external UID and provider:
```
GET /users?extern_uid=:extern_uid&provider=:provider
```
For example:
```
GET /users?extern_uid=1234567&provider=github
```
You can search for users who are external with: `/users?external=true`
## Single user

View File

@ -39,10 +39,13 @@ module API
params do
# CE
optional :username, type: String, desc: 'Get a single user with a specific username'
optional :extern_uid, type: String, desc: 'Get a single user with a specific external authentication provider UID'
optional :provider, type: String, desc: 'The external provider'
optional :search, type: String, desc: 'Search for a username'
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'
all_or_none_of :extern_uid, :provider
use :pagination
end
@ -51,14 +54,17 @@ module API
render_api_error!("Not authorized.", 403)
end
if params[:username].present?
users = User.where(username: params[:username])
else
users = User.all
users = users.active if params[:active]
users = users.search(params[:search]) if params[:search].present?
users = users.blocked if params[:blocked]
users = users.external if params[:external] && current_user.admin?
authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?)
users = User.all
users = User.where(username: params[:username]) if params[:username]
users = users.active if params[:active]
users = users.search(params[:search]) if params[:search].present?
users = users.blocked if params[:blocked]
if current_user.admin?
users = users.joins(:identities).merge(Identity.with_extern_uid(params[:provider], params[:extern_uid])) if params[:extern_uid] && params[:provider]
users = users.external if params[:external]
end
entity = current_user.admin? ? Entities::UserPublic : Entities::UserBasic

View File

@ -72,6 +72,12 @@ describe API::Users, api: true do
expect(json_response).to be_an Array
expect(json_response.first['username']).to eq(omniauth_user.username)
end
it "returns a 403 when non-admin user searches by external UID" do
get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", user)
expect(response).to have_http_status(403)
end
end
context "when admin" do
@ -100,6 +106,27 @@ describe API::Users, api: true do
expect(json_response).to be_an Array
expect(json_response).to all(include('external' => true))
end
it "returns one user by external UID" do
get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", admin)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
expect(json_response.first['username']).to eq(omniauth_user.username)
end
it "returns 400 error if provider with no extern_uid" do
get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}", admin)
expect(response).to have_http_status(400)
end
it "returns 400 error if provider with no extern_uid" do
get api("/users?provider=#{omniauth_user.identities.first.provider}", admin)
expect(response).to have_http_status(400)
end
end
end