Commit 6df6125b authored by Robert Speicher's avatar Robert Speicher

Merge branch '196777-add-account-creation-and-sign-in-ip-to-api' into 'master'

Provide user's current ip and last ip to admins

Closes #196777

See merge request gitlab-org/gitlab!23103
parents f2e69e92 e98f5ad1
---
title: Expose current and last IPs to /users endpoint
merge_request: 19781
author:
type: added
...@@ -111,7 +111,9 @@ GET /users ...@@ -111,7 +111,9 @@ GET /users
"can_create_project": true, "can_create_project": true,
"two_factor_enabled": true, "two_factor_enabled": true,
"external": false, "external": false,
"private_profile": false "private_profile": false,
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22"
}, },
{ {
"id": 2, "id": 2,
...@@ -142,7 +144,9 @@ GET /users ...@@ -142,7 +144,9 @@ GET /users
"can_create_project": true, "can_create_project": true,
"two_factor_enabled": true, "two_factor_enabled": true,
"external": false, "external": false,
"private_profile": false "private_profile": false,
"current_sign_in_ip": "10.165.1.102",
"last_sign_in_ip": "172.127.2.22"
} }
] ]
``` ```
...@@ -294,7 +298,9 @@ Example Responses: ...@@ -294,7 +298,9 @@ Example Responses:
"can_create_project": true, "can_create_project": true,
"two_factor_enabled": true, "two_factor_enabled": true,
"external": false, "external": false,
"private_profile": false "private_profile": false,
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22"
} }
``` ```
...@@ -534,7 +540,9 @@ GET /user ...@@ -534,7 +540,9 @@ GET /user
"can_create_project": true, "can_create_project": true,
"two_factor_enabled": true, "two_factor_enabled": true,
"external": false, "external": false,
"private_profile": false "private_profile": false,
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22"
} }
``` ```
......
...@@ -115,6 +115,8 @@ module API ...@@ -115,6 +115,8 @@ module API
class UserDetailsWithAdmin < UserWithAdmin class UserDetailsWithAdmin < UserWithAdmin
expose :highest_role expose :highest_role
expose :current_sign_in_ip
expose :last_sign_in_ip
end end
class UserStatus < Grape::Entity class UserStatus < Grape::Entity
......
...@@ -77,6 +77,14 @@ describe API::Users do ...@@ -77,6 +77,14 @@ describe API::Users do
expect(json_response.first.keys).not_to include 'highest_role' expect(json_response.first.keys).not_to include 'highest_role'
end end
it "does not return the current or last sign-in ip addresses" do
get api("/users"), params: { username: user.username }
expect(response).to match_response_schema('public_api/v4/user/basics')
expect(json_response.first.keys).not_to include 'current_sign_in_ip'
expect(json_response.first.keys).not_to include 'last_sign_in_ip'
end
context "when public level is restricted" do context "when public level is restricted" do
before do before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
...@@ -314,6 +322,14 @@ describe API::Users do ...@@ -314,6 +322,14 @@ describe API::Users do
expect(json_response.keys).not_to include 'highest_role' expect(json_response.keys).not_to include 'highest_role'
end end
it "does not return the user's sign in IPs" do
get api("/users/#{user.id}", user)
expect(response).to match_response_schema('public_api/v4/user/basic')
expect(json_response.keys).not_to include 'current_sign_in_ip'
expect(json_response.keys).not_to include 'last_sign_in_ip'
end
context 'when authenticated as admin' do context 'when authenticated as admin' do
it 'includes the `is_admin` field' do it 'includes the `is_admin` field' do
get api("/users/#{user.id}", admin) get api("/users/#{user.id}", admin)
...@@ -328,12 +344,34 @@ describe API::Users do ...@@ -328,12 +344,34 @@ describe API::Users do
expect(response).to match_response_schema('public_api/v4/user/admin') expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response.keys).to include 'created_at' expect(json_response.keys).to include 'created_at'
end end
it 'includes the `highest_role` field' do it 'includes the `highest_role` field' do
get api("/users/#{user.id}", admin) get api("/users/#{user.id}", admin)
expect(response).to match_response_schema('public_api/v4/user/admin') expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['highest_role']).to be(0) expect(json_response['highest_role']).to be(0)
end end
context 'when user has not logged in' do
it 'does not include the sign in IPs' do
get api("/users/#{user.id}", admin)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response).to include('current_sign_in_ip' => nil, 'last_sign_in_ip' => nil)
end
end
context 'when user has logged in' do
let_it_be(:signed_in_user) { create(:user, :with_sign_ins) }
it 'includes the sign in IPs' do
get api("/users/#{signed_in_user.id}", admin)
expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['current_sign_in_ip']).to eq('127.0.0.1')
expect(json_response['last_sign_in_ip']).to eq('127.0.0.1')
end
end
end end
context 'for an anonymous user' do context 'for an anonymous user' 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