Commit ddf7e6ae authored by Robin Bobbitt's avatar Robin Bobbitt

Implement search by extern_uid in Users API

parent 22c40500
...@@ -7,6 +7,8 @@ class Identity < ActiveRecord::Base ...@@ -7,6 +7,8 @@ class Identity < ActiveRecord::Base
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider } validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
validates :user_id, 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? def ldap?
provider.starts_with?('ldap') provider.starts_with?('ldap')
end end
......
---
title: Implement search by extern_uid in Users API
merge_request: 10509
author: Robin Bobbitt
...@@ -130,6 +130,18 @@ For example: ...@@ -130,6 +130,18 @@ For example:
GET /users?username=jack_smith 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` You can search for users who are external with: `/users?external=true`
## Single user ## Single user
......
...@@ -39,10 +39,13 @@ module API ...@@ -39,10 +39,13 @@ module API
params do params do
# CE # CE
optional :username, type: String, desc: 'Get a single user with a specific username' 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 :search, type: String, desc: 'Search for a username'
optional :active, type: Boolean, default: false, desc: 'Filters only active users' optional :active, type: Boolean, default: false, desc: 'Filters only active users'
optional :external, type: Boolean, default: false, desc: 'Filters only external users' optional :external, type: Boolean, default: false, desc: 'Filters only external users'
optional :blocked, type: Boolean, default: false, desc: 'Filters only blocked users' optional :blocked, type: Boolean, default: false, desc: 'Filters only blocked users'
all_or_none_of :extern_uid, :provider
use :pagination use :pagination
end end
...@@ -51,14 +54,17 @@ module API ...@@ -51,14 +54,17 @@ module API
render_api_error!("Not authorized.", 403) render_api_error!("Not authorized.", 403)
end end
if params[:username].present? authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?)
users = User.where(username: params[:username])
else users = User.all
users = User.all users = User.where(username: params[:username]) if params[:username]
users = users.active if params[:active] users = users.active if params[:active]
users = users.search(params[:search]) if params[:search].present? users = users.search(params[:search]) if params[:search].present?
users = users.blocked if params[:blocked] users = users.blocked if params[:blocked]
users = users.external if params[:external] && current_user.admin?
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 end
entity = current_user.admin? ? Entities::UserPublic : Entities::UserBasic entity = current_user.admin? ? Entities::UserPublic : Entities::UserBasic
......
...@@ -72,6 +72,12 @@ describe API::Users, api: true do ...@@ -72,6 +72,12 @@ describe API::Users, api: true do
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.first['username']).to eq(omniauth_user.username) expect(json_response.first['username']).to eq(omniauth_user.username)
end 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 end
context "when admin" do context "when admin" do
...@@ -100,6 +106,27 @@ describe API::Users, api: true do ...@@ -100,6 +106,27 @@ describe API::Users, api: true do
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response).to all(include('external' => true)) expect(json_response).to all(include('external' => true))
end 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
end end
......
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