Merge branch 'if-53347_fix_impersonation_tokens' into 'master'

Display impersonation token value only after creation

See merge request gitlab-org/gitlab-ce!22916
This commit is contained in:
Stan Hu 2018-11-15 19:06:28 +00:00
commit 1d16530501
14 changed files with 54 additions and 26 deletions

View file

@ -11,6 +11,7 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token = finder.build(impersonation_token_params)
if @impersonation_token.save
PersonalAccessToken.redis_store!(current_user.id, @impersonation_token.token)
redirect_to admin_user_impersonation_tokens_path, notice: "A new impersonation token has been created."
else
set_index_vars
@ -53,6 +54,8 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token ||= finder.build
@inactive_impersonation_tokens = finder(state: 'inactive').execute
@active_impersonation_tokens = finder(state: 'active').execute.order(:expires_at)
@new_impersonation_token = PersonalAccessToken.redis_getdel(current_user.id)
end
# rubocop: enable CodeReuse/ActiveRecord
end

View file

@ -5,6 +5,11 @@
.row.prepend-top-default
.col-lg-12
- if @new_impersonation_token
= render "shared/personal_access_tokens_created_container", new_token_value: @new_impersonation_token,
container_title: 'Your New Impersonation Token',
clipboard_button_title: 'Copy impersonation token to clipboard'
= render "shared/personal_access_tokens_form", path: admin_user_impersonation_tokens_path, impersonation: true, token: @impersonation_token, scopes: @scopes
= render "shared/personal_access_tokens_table", impersonation: true, active_tokens: @active_impersonation_tokens, inactive_tokens: @inactive_impersonation_tokens

View file

@ -14,17 +14,7 @@
.col-lg-8
- if @new_personal_access_token
.created-personal-access-token-container
%h5.prepend-top-0
Your New Personal Access Token
.form-group
.input-group
= text_field_tag 'created-personal-access-token', @new_personal_access_token, readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-personal-access-token-help-block"
%span.input-group-append
= clipboard_button(text: @new_personal_access_token, title: "Copy personal access token to clipboard", placement: "left", class: "input-group-text btn-default btn-clipboard")
%span#created-personal-access-token-help-block.form-text.text-muted.text-danger Make sure you save it - you won't be able to access it again.
%hr
= render "shared/personal_access_tokens_created_container", new_token_value: @new_personal_access_token
= render "shared/personal_access_tokens_form", path: profile_personal_access_tokens_path, impersonation: false, token: @personal_access_token, scopes: @scopes

View file

@ -0,0 +1,14 @@
- container_title = local_assigns.fetch(:container_title, 'Your New Personal Access Token')
- clipboard_button_title = local_assigns.fetch(:clipboard_button_title, 'Copy personal access token to clipboard')
.created-personal-access-token-container
%h5.prepend-top-0
= container_title
.form-group
.input-group
= text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-token-help-block"
%span.input-group-append
= clipboard_button(text: new_token_value, title: clipboard_button_title, placement: "left", class: "input-group-text btn-default btn-clipboard")
%span#created-token-help-block.form-text.text-muted.text-danger Make sure you save it - you won't be able to access it again.
%hr

View file

@ -15,8 +15,6 @@
%th Created
%th Expires
%th Scopes
- if impersonation
%th Token
%th
%tbody
- active_tokens.each do |token|
@ -30,10 +28,6 @@
- else
%span.token-never-expires-label Never
%td= token.scopes.present? ? token.scopes.join(", ") : "<no scopes selected>"
- if impersonation
%td.token-token-container
= text_field_tag 'impersonation-token-token', token.token, readonly: true, class: "form-control"
= clipboard_button(text: token.token)
- path = impersonation ? revoke_admin_user_impersonation_token_path(token.user, token) : revoke_profile_personal_access_token_path(token)
%td= link_to "Revoke", path, method: :put, class: "btn btn-danger float-right", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
- else

View file

@ -0,0 +1,5 @@
---
title: Display impersonation token value only after creation
merge_request: 22916
author:
type: fixed

View file

@ -1072,7 +1072,6 @@ Example response:
[
{
"active" : true,
"token" : "EsMo-vhKfXGwX9RKrwiy",
"scopes" : [
"api"
],
@ -1089,7 +1088,6 @@ Example response:
"read_user"
],
"revoked" : true,
"token" : "ZcZRpLeEuQRprkRjYydY",
"name" : "mytoken2",
"created_at" : "2017-03-17T17:19:28.697Z",
"id" : 3,
@ -1125,7 +1123,6 @@ Example response:
```json
{
"active" : true,
"token" : "EsMo-vhKfXGwX9RKrwiy",
"scopes" : [
"api"
],
@ -1142,6 +1139,8 @@ Example response:
> Requires admin permissions.
> Token values are returned once. Make sure you save it - you won't be able to access it again.
It creates a new impersonation token. Note that only administrators can do this.
You are only able to create impersonation tokens to impersonate the user and perform
both API calls and Git reads and writes. The user will not see these tokens in their profile

View file

@ -1263,7 +1263,11 @@ module API
expose :token
end
class ImpersonationToken < PersonalAccessTokenWithToken
class ImpersonationToken < PersonalAccessToken
expose :impersonation
end
class ImpersonationTokenWithToken < PersonalAccessTokenWithToken
expose :impersonation
end

View file

@ -531,7 +531,7 @@ module API
desc 'Create a impersonation token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::ImpersonationToken
success Entities::ImpersonationTokenWithToken
end
params do
requires :name, type: String, desc: 'The name of the impersonation token'
@ -542,7 +542,7 @@ module API
impersonation_token = finder.build(declared_params(include_missing: false))
if impersonation_token.save
present impersonation_token, with: Entities::ImpersonationToken
present impersonation_token, with: Entities::ImpersonationTokenWithToken
else
render_validation_error!(impersonation_token)
end

View file

@ -8,7 +8,7 @@ module QA
element :scopes_api_radios, "label :scopes" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/profiles/personal_access_tokens/index.html.haml' do
view 'app/views/shared/_personal_access_tokens_created_container.html.haml' do
element :create_token_field, "text_field_tag 'created-personal-access-token'" # rubocop:disable QA/ElementWithPattern
end

View file

@ -39,8 +39,10 @@ describe Profiles::PersonalAccessTokensController do
let!(:active_personal_access_token) { create(:personal_access_token, user: user) }
let!(:inactive_personal_access_token) { create(:personal_access_token, :revoked, user: user) }
let!(:impersonation_personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
let(:token_value) { 's3cr3t' }
before do
PersonalAccessToken.redis_store!(user.id, token_value)
get :index
end
@ -56,5 +58,9 @@ describe Profiles::PersonalAccessTokensController do
expect(assigns(:active_personal_access_tokens)).not_to include(impersonation_personal_access_token)
expect(assigns(:inactive_personal_access_tokens)).not_to include(impersonation_personal_access_token)
end
it "retrieves newly created personal access token value" do
expect(assigns(:new_personal_access_token)).to eql(token_value)
end
end
end

View file

@ -12,6 +12,10 @@ describe 'Admin > Users > Impersonation Tokens', :js do
find(".settings-message")
end
def created_impersonation_token
find("#created-personal-access-token").value
end
before do
sign_in(admin)
end
@ -39,6 +43,7 @@ describe 'Admin > Users > Impersonation Tokens', :js do
expect(active_impersonation_tokens).to have_text('api')
expect(active_impersonation_tokens).to have_text('read_user')
expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1)
expect(created_impersonation_token).not_to be_empty
end
end

View file

@ -43,10 +43,12 @@ describe 'Profile > Personal Access Tokens', :js do
check "read_user"
click_on "Create personal access token"
expect(active_personal_access_tokens).to have_text(name)
expect(active_personal_access_tokens).to have_text('In')
expect(active_personal_access_tokens).to have_text('api')
expect(active_personal_access_tokens).to have_text('read_user')
expect(created_personal_access_token).not_to be_empty
end
context "when creation fails" do
@ -57,6 +59,7 @@ describe 'Profile > Personal Access Tokens', :js do
expect { click_on "Create personal access token" }.not_to change { PersonalAccessToken.count }
expect(page).to have_content("Name cannot be nil")
expect(page).not_to have_selector("#created-personal-access-token")
end
end
end

View file

@ -2018,11 +2018,11 @@ describe API::Users do
expect(json_response['message']).to eq('403 Forbidden')
end
it 'returns a personal access token' do
it 'returns an impersonation token' do
get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
expect(response).to have_gitlab_http_status(200)
expect(json_response['token']).to be_present
expect(json_response['token']).not_to be_present
expect(json_response['impersonation']).to be_truthy
end
end