Commit f0ea7130 authored by Tiago Botelho's avatar Tiago Botelho

refactors documentation and personal access tokens form to not allow admins to...

refactors documentation and personal access tokens form to not allow admins to generate non impersionation tokens
parent c2b1cdef
...@@ -6,7 +6,8 @@ class Admin::PersonalAccessTokensController < Admin::ApplicationController ...@@ -6,7 +6,8 @@ class Admin::PersonalAccessTokensController < Admin::ApplicationController
end end
def create def create
@personal_access_token = user.personal_access_tokens.generate(personal_access_token_params) # We never want to non-impersonate a user
@personal_access_token = user.personal_access_tokens.generate(personal_access_token_params.merge(impersonation: true))
if @personal_access_token.save if @personal_access_token.save
flash[:personal_access_token] = @personal_access_token.token flash[:personal_access_token] = @personal_access_token.token
......
- personal_access_token = local_assigns.fetch(:personal_access_token)
- scopes = local_assigns.fetch(:scopes)
= form_for [:admin_user, personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f|
= form_errors(personal_access_token)
.form-group
= f.label :name, class: 'label-light'
= f.text_field :name, class: "form-control", required: true
.form-group
= f.label :expires_at, class: 'label-light'
= f.text_field :expires_at, class: "datepicker form-control"
.form-group
= f.label :scopes, class: 'label-light'
= render 'shared/tokens/scopes_form', prefix: 'personal_access_token', token: personal_access_token, scopes: scopes
.form-group
= f.label :impersonation, class: 'label-light'
%fieldset
= f.check_box :impersonation
= f.label 'impersonation', 'You can impersonate the user'
%span= "(Normal users will not see this type of token)"
.prepend-top-default
= f.submit 'Create Personal Access Token', class: "btn btn-create"
...@@ -3,18 +3,15 @@ ...@@ -3,18 +3,15 @@
.row.prepend-top-default .row.prepend-top-default
.col-lg-12 .col-lg-12
%h5.prepend-top-0 %h5.prepend-top-0
Add a Personal Access Token Add a Personal Access Token
%p.profile-settings-content %p.profile-settings-content
Pick a name for the application, and we'll give you a unique token. Pick a name for the application, and we'll give you a unique token.
= render "profiles/personal_access_tokens/form", user: :admin_user, personal_access_token: @personal_access_token, scopes: @scopes
= render "form", personal_access_token: @personal_access_token, scopes: @scopes
%hr %hr
%h5 Active Personal Access Tokens (#{@active_personal_access_tokens.length}) %h5 Active Personal Access Tokens (#{@active_personal_access_tokens.length})
- if @active_personal_access_tokens.present? - if @active_personal_access_tokens.present?
.table-responsive .table-responsive
%table.table.active-personal-access-tokens %table.table.active-personal-access-tokens
...@@ -44,7 +41,6 @@ ...@@ -44,7 +41,6 @@
= clipboard_button(clipboard_text: personal_access_token.token) = clipboard_button(clipboard_text: personal_access_token.token)
%td= personal_access_token.impersonation %td= personal_access_token.impersonation
%td= link_to "Revoke", revoke_admin_user_personal_access_token_path(id: personal_access_token.id, user_id: personal_access_token.user.username), method: :put, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this token? This action cannot be undone." } %td= link_to "Revoke", revoke_admin_user_personal_access_token_path(id: personal_access_token.id, user_id: personal_access_token.user.username), method: :put, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this token? This action cannot be undone." }
- else - else
.settings-message.text-center .settings-message.text-center
This user has no active tokens. This user has no active tokens.
...@@ -52,7 +48,6 @@ ...@@ -52,7 +48,6 @@
%hr %hr
%h5 Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.length}) %h5 Inactive Personal Access Tokens (#{@inactive_personal_access_tokens.length})
- if @inactive_personal_access_tokens.present? - if @inactive_personal_access_tokens.present?
.table-responsive .table-responsive
%table.table.inactive-personal-access-tokens %table.table.inactive-personal-access-tokens
...@@ -65,16 +60,20 @@ ...@@ -65,16 +60,20 @@
%tr %tr
%td= token.name %td= token.name
%td= token.created_at.to_date.to_s(:medium) %td= token.created_at.to_date.to_s(:medium)
- else - else
.settings-message.text-center .settings-message.text-center
This user has no inactive tokens. This user has no inactive tokens.
:javascript :javascript
var date = $('#personal_access_token_expires_at').val(); var $dateField = $('#personal_access_token_expires_at');
var date = $dateField.val();
var datepicker = $(".datepicker").datepicker({ new Pikaday({
dateFormat: "yy-mm-dd", field: $dateField.get(0),
minDate: 0 theme: 'gitlab-theme',
format: 'YYYY-MM-DD',
minDate: new Date(),
onSelect: function(dateText) {
$dateField.val(dateFormat(new Date(dateText), 'yyyy-mm-dd'));
}
}); });
- personal_access_token = local_assigns.fetch(:personal_access_token) - personal_access_token = local_assigns.fetch(:personal_access_token)
- scopes = local_assigns.fetch(:scopes) - scopes = local_assigns.fetch(:scopes)
= form_for [:profile, personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f| = form_for [user, personal_access_token], method: :post, html: { class: 'js-requires-input' } do |f|
= form_errors(personal_access_token) = form_errors(personal_access_token)
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
%p.profile-settings-content %p.profile-settings-content
Pick a name for the application, and we'll give you a unique token. Pick a name for the application, and we'll give you a unique token.
= render "form", personal_access_token: @personal_access_token, scopes: @scopes = render "form", user: :profile, personal_access_token: @personal_access_token, scopes: @scopes
%hr %hr
......
...@@ -8,7 +8,7 @@ under [`/lib/api`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api). ...@@ -8,7 +8,7 @@ under [`/lib/api`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api).
Documentation for various API resources can be found separately in the Documentation for various API resources can be found separately in the
following locations: following locations:
- [Access Tokens](personal_access_tokens.md) - [Personal Access Tokens](personal_access_tokens.md)
- [Award Emoji](award_emoji.md) - [Award Emoji](award_emoji.md)
- [Branches](branches.md) - [Branches](branches.md)
- [Broadcast Messages](broadcast_messages.md) - [Broadcast Messages](broadcast_messages.md)
......
...@@ -14,13 +14,13 @@ An example: ...@@ -14,13 +14,13 @@ An example:
"name": "mytoken", "name": "mytoken",
"revoked": false, "revoked": false,
"expires_at": "2017-01-04", "expires_at": "2017-01-04",
"scopes": ['api'], "scopes": ["api"],
"active": true "active": true
} }
] ]
``` ```
In addition, you can filter users based on state: `all`, `active` and `inactive` In addition, you can filter tokens based on state: `all`, `active` and `inactive`
``` ```
GET /personal_access_tokens?state=all GET /personal_access_tokens?state=all
...@@ -34,6 +34,18 @@ GET /personal_access_tokens?state=active ...@@ -34,6 +34,18 @@ GET /personal_access_tokens?state=active
GET /personal_access_tokens?state=inactive GET /personal_access_tokens?state=inactive
``` ```
## Show
```
GET /personal_access_tokens/:personal_access_token_id
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `personal_access_token_id` | integer | yes | The ID of the personal access token |
## Create ## Create
``` ```
......
...@@ -858,7 +858,7 @@ An example: ...@@ -858,7 +858,7 @@ An example:
] ]
``` ```
In addition, you can filter users based on state: `all`, `active` and `inactive` In addition, you can filter tokens based on state: `all`, `active` and `inactive`
``` ```
GET /users/:user_id/personal_access_tokens?state=all GET /users/:user_id/personal_access_tokens?state=all
...@@ -878,12 +878,27 @@ Finally, you can filter based on impersonation: `true` or `false`. ...@@ -878,12 +878,27 @@ Finally, you can filter based on impersonation: `true` or `false`.
GET /users/:user_id/personal_access_tokens?impersonation=true GET /users/:user_id/personal_access_tokens?impersonation=true
``` ```
## Show a user personal access token
It shows a user's personal access token. Note that only administrators can do this.
```
GET /users/:user_id/personal_access_tokens/:personal_access_token_id
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `user_id` | integer | yes | The ID of the user |
| `personal_access_token_id` | integer | yes | The ID of the personal access token |
## Create a personal access token ## Create a personal access token
It creates a new personal access token. Note that only administrators can do this. It creates a new personal access token. Note that only administrators can do this.
If you set the impersonation flag to true, you can impersonate the user and You are only able to create impersonation tokens to impersonate the user and perform
performing both API calls and Git reads and writes. The user will not see these both API calls and Git reads and writes. The user will not see these tokens in his profile
tokens in his profile settings. settings page.
``` ```
POST /users/:user_id/personal_access_tokens POST /users/:user_id/personal_access_tokens
......
...@@ -3,7 +3,10 @@ module API ...@@ -3,7 +3,10 @@ module API
before { authenticate! } before { authenticate! }
resource :personal_access_tokens do resource :personal_access_tokens do
desc 'Retrieve personal access tokens' desc 'Retrieve personal access tokens' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::BasicPersonalAccessToken
end
params do params do
optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) personal_access_tokens' optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) personal_access_tokens'
end end
...@@ -20,7 +23,24 @@ module API ...@@ -20,7 +23,24 @@ module API
present personal_access_tokens, with: Entities::BasicPersonalAccessToken present personal_access_tokens, with: Entities::BasicPersonalAccessToken
end end
desc 'Create a personal access token' desc 'Retrieve personal access token' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::BasicPersonalAccessToken
end
params do
requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token'
end
get ':personal_access_token_id' do
personal_access_token = PersonalAccessToken.find_by(id: params[:personal_access_token_id], user_id: current_user.id)
not_found!('PersonalAccessToken') unless personal_access_token
present personal_access_token, with: Entities::BasicPersonalAccessToken
end
desc 'Create a personal access token' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::BasicPersonalAccessToken
end
params do params do
requires :name, type: String, desc: 'The name of the personal access token' requires :name, type: String, desc: 'The name of the personal access token'
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token' optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token'
...@@ -39,7 +59,10 @@ module API ...@@ -39,7 +59,10 @@ module API
end end
end end
desc 'Revoke a personal access token' desc 'Revoke a personal access token' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::BasicPersonalAccessToken
end
params do params do
requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token' requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token'
end end
...@@ -49,7 +72,7 @@ module API ...@@ -49,7 +72,7 @@ module API
personal_access_token.revoke! personal_access_token.revoke!
present personal_access_token, with: Entities::BasicPersonalAccessToken no_content!
end end
end end
end end
......
...@@ -363,15 +363,22 @@ module API ...@@ -363,15 +363,22 @@ module API
present paginate(events), with: Entities::Event present paginate(events), with: Entities::Event
end end
desc 'Retrieve personal access tokens. Available only for admins.'
params do params do
requires :user_id, type: Integer requires :user_id, type: Integer, desc: 'The ID of the user'
optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) personal_access_tokens'
optional :impersonation, type: Boolean, default: false, desc: 'Filters only impersonation personal_access_token'
end end
get ':user_id/personal_access_tokens' do segment ':user_id' do
authenticated_as_admin! resource :personal_access_tokens do
before { authenticated_as_admin! }
desc 'Retrieve personal access tokens. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::PersonalAccessToken
end
params do
optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) personal_access_tokens'
optional :impersonation, type: Boolean, default: false, desc: 'Filters only impersonation personal_access_tokens'
end
get do
user = User.find_by(id: params[:user_id]) user = User.find_by(id: params[:user_id])
not_found!('User') unless user not_found!('User') unless user
...@@ -388,21 +395,21 @@ module API ...@@ -388,21 +395,21 @@ module API
present personal_access_tokens, with: Entities::PersonalAccessToken present personal_access_tokens, with: Entities::PersonalAccessToken
end end
desc 'Create a personal access token. Available only for admins.' desc 'Create a personal access token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::PersonalAccessToken
end
params do params do
requires :user_id, type: Integer, desc: 'The ID of the user'
requires :name, type: String, desc: 'The name of the personal access token' requires :name, type: String, desc: 'The name of the personal access token'
optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token' optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token'
optional :scopes, type: Array, desc: 'The array of scopes of the personal access token' optional :scopes, type: Array, desc: 'The array of scopes of the personal access token'
optional :impersonation, type: Boolean, default: false, desc: 'The impersonation flag of the personal access token' optional :impersonation, type: Boolean, default: false, desc: 'The impersonation flag of the personal access token'
end end
post ':user_id/personal_access_tokens' do post do
authenticated_as_admin!
user = User.find_by(id: params[:user_id]) user = User.find_by(id: params[:user_id])
not_found!('User') unless user not_found!('User') unless user
personal_access_token = PersonalAccessToken.generate(declared_params(include_missing: false)) personal_access_token = PersonalAccessToken.generate(declared_params(include_missing: false, include_parent_namespaces: true))
if personal_access_token.save if personal_access_token.save
present personal_access_token, with: Entities::PersonalAccessToken present personal_access_token, with: Entities::PersonalAccessToken
...@@ -411,14 +418,31 @@ module API ...@@ -411,14 +418,31 @@ module API
end end
end end
desc 'Revoke a personal access token. Available only for admins.' desc 'Retrieve personal access token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::PersonalAccessToken
end
params do params do
requires :user_id, type: Integer, desc: 'The ID of the user'
requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token' requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token'
end end
delete ':user_id/personal_access_tokens/:personal_access_token_id' do get '/:personal_access_token_id' do
authenticated_as_admin! user = User.find_by(id: params[:user_id])
not_found!('User') unless user
personal_access_token = PersonalAccessToken.and_impersonation_tokens.find_by(user_id: user.id, id: params[:personal_access_token_id])
not_found!('PersonalAccessToken') unless personal_access_token
present personal_access_token, with: Entities::PersonalAccessToken
end
desc 'Revoke a personal access token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
success Entities::PersonalAccessToken
end
params do
requires :personal_access_token_id, type: Integer, desc: 'The ID of the personal access token'
end
delete '/:personal_access_token_id' do
user = User.find_by(id: params[:user_id]) user = User.find_by(id: params[:user_id])
not_found!('User') unless user not_found!('User') unless user
...@@ -427,7 +451,9 @@ module API ...@@ -427,7 +451,9 @@ module API
personal_access_token.revoke! personal_access_token.revoke!
present personal_access_token, with: Entities::PersonalAccessToken no_content!
end
end
end end
end end
......
...@@ -52,21 +52,17 @@ describe Profiles::PersonalAccessTokensController do ...@@ -52,21 +52,17 @@ describe Profiles::PersonalAccessTokensController do
let!(:inactive_personal_access_token) { create(:revoked_personal_access_token, user: user) } let!(:inactive_personal_access_token) { create(:revoked_personal_access_token, user: user) }
let!(:impersonation_personal_access_token) { create(:impersonation_personal_access_token, user: user) } let!(:impersonation_personal_access_token) { create(:impersonation_personal_access_token, user: user) }
it "retrieves active personal access tokens" do before { get :index }
get :index
it "retrieves active personal access tokens" do
expect(assigns(:active_personal_access_tokens)).to include(active_personal_access_token) expect(assigns(:active_personal_access_tokens)).to include(active_personal_access_token)
end end
it "retrieves inactive personal access tokens" do it "retrieves inactive personal access tokens" do
get :index
expect(assigns(:inactive_personal_access_tokens)).to include(inactive_personal_access_token) expect(assigns(:inactive_personal_access_tokens)).to include(inactive_personal_access_token)
end end
it "does not retrieve impersonation personal access tokens" do it "does not retrieve impersonation personal access tokens" do
get :index
expect(assigns(:active_personal_access_tokens)).not_to include(impersonation_personal_access_token) 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) expect(assigns(:inactive_personal_access_tokens)).not_to include(impersonation_personal_access_token)
end end
......
...@@ -22,9 +22,7 @@ describe 'Admin > Users > Personal Access Tokens', feature: true, js: true do ...@@ -22,9 +22,7 @@ describe 'Admin > Users > Personal Access Tokens', feature: true, js: true do
allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors) allow_any_instance_of(PersonalAccessToken).to receive(:errors).and_return(errors)
end end
before do before { login_as(admin) }
login_as(admin)
end
describe "token creation" do describe "token creation" do
it "allows creation of a token" do it "allows creation of a token" do
...@@ -35,15 +33,13 @@ describe 'Admin > Users > Personal Access Tokens', feature: true, js: true do ...@@ -35,15 +33,13 @@ describe 'Admin > Users > Personal Access Tokens', feature: true, js: true do
# Set date to 1st of next month # Set date to 1st of next month
find_field("Expires at").trigger('focus') find_field("Expires at").trigger('focus')
find("a[title='Next']").click find(".pika-next").click
click_on "1" click_on "1"
# Scopes # Scopes
check "api" check "api"
check "read_user" check "read_user"
check "You can impersonate the user"
click_on "Create Personal Access Token" click_on "Create Personal Access Token"
expect(active_personal_access_tokens).to have_text(name) 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('In')
......
...@@ -4,6 +4,7 @@ describe API::PersonalAccessTokens, api: true do ...@@ -4,6 +4,7 @@ describe API::PersonalAccessTokens, api: true do
include ApiHelpers include ApiHelpers
let(:user) { create(:user) } let(:user) { create(:user) }
let(:not_found_token) { (PersonalAccessToken.maximum('id') || 0) + 10 }
describe "GET /personal_access_tokens" do describe "GET /personal_access_tokens" do
let!(:active_personal_access_token) { create(:personal_access_token, user: user) } let!(:active_personal_access_token) { create(:personal_access_token, user: user) }
...@@ -76,12 +77,38 @@ describe API::PersonalAccessTokens, api: true do ...@@ -76,12 +77,38 @@ describe API::PersonalAccessTokens, api: true do
end end
end end
describe 'GET /personal_access_tokens/:personal_access_token_id' do
let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) }
let!(:personal_access_token_of_another_user) { create(:personal_access_token, revoked: false) }
it 'returns a 404 error if personal access token not found' do
get api("/personal_access_tokens/#{not_found_token}", user)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 PersonalAccessToken Not Found')
end
it 'returns a 404 error if personal access token exists but it is a personal access tokens of another user' do
get api("/personal_access_tokens/#{personal_access_token_of_another_user.id}", user)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 PersonalAccessToken Not Found')
end
it 'returns a personal access token and does not expose token in the json response' do
get api("/personal_access_tokens/#{personal_access_token.id}", user)
expect(response).to have_http_status(200)
expect(json_response['token']).not_to be_present
end
end
describe 'DELETE /personal_access_tokens/:personal_access_token_id' do describe 'DELETE /personal_access_tokens/:personal_access_token_id' do
let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) } let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) }
let!(:personal_access_token_of_another_user) { create(:personal_access_token, revoked: false) } let!(:personal_access_token_of_another_user) { create(:personal_access_token, revoked: false) }
it 'returns a 404 error if personal access token not found' do it 'returns a 404 error if personal access token not found' do
delete api("/personal_access_tokens/42", user) delete api("/personal_access_tokens/#{not_found_token}", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 PersonalAccessToken Not Found') expect(json_response['message']).to eq('404 PersonalAccessToken Not Found')
...@@ -97,11 +124,9 @@ describe API::PersonalAccessTokens, api: true do ...@@ -97,11 +124,9 @@ describe API::PersonalAccessTokens, api: true do
it 'revokes a personal access token and does not expose token in the json response' do it 'revokes a personal access token and does not expose token in the json response' do
delete api("/personal_access_tokens/#{personal_access_token.id}", user) delete api("/personal_access_tokens/#{personal_access_token.id}", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(204)
expect(personal_access_token.revoked).to eq(false) expect(personal_access_token.revoked).to eq(false)
expect(personal_access_token.reload.revoked).to eq(true) expect(personal_access_token.reload.revoked).to eq(true)
expect(json_response['revoked']).to eq(true)
expect(json_response['token']).not_to be_present
end end
end end
end end
...@@ -11,6 +11,7 @@ describe API::Users, api: true do ...@@ -11,6 +11,7 @@ describe API::Users, api: true do
let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') } let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') }
let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') } let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
let(:not_existing_user_id) { (User.maximum('id') || 0 ) + 10 } let(:not_existing_user_id) { (User.maximum('id') || 0 ) + 10 }
let(:not_existing_pat_id) { (PersonalAccessToken.maximum('id') || 0 ) + 10 }
describe "GET /users" do describe "GET /users" do
context "when unauthenticated" do context "when unauthenticated" do
...@@ -1268,7 +1269,47 @@ describe API::Users, api: true do ...@@ -1268,7 +1269,47 @@ describe API::Users, api: true do
end end
end end
describe 'DELETE /users/:id/personal_access_tokens/:personal_access_token_id' do describe 'GET /users/:user_id/personal_access_tokens/:personal_access_token_id' do
let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) }
let!(:impersonation_token) { create(:impersonation_personal_access_token, user: user, revoked: false) }
it 'returns 404 error if user not found' do
get api("/users/#{not_existing_user_id}/personal_access_tokens/1", admin)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
it 'returns a 404 error if personal access token not found' do
get api("/users/#{user.id}/personal_access_tokens/#{not_existing_pat_id}", admin)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 PersonalAccessToken Not Found')
end
it 'returns a 403 error when authenticated as normal user' do
get api("/users/#{user.id}/personal_access_tokens/#{personal_access_token.id}", user)
expect(response).to have_http_status(403)
expect(json_response['message']).to eq('403 Forbidden')
end
it 'returns a personal access token' do
get api("/users/#{user.id}/personal_access_tokens/#{personal_access_token.id}", admin)
expect(response).to have_http_status(200)
expect(json_response['token']).to be_present
end
it 'returns an impersonation token' do
get api("/users/#{user.id}/personal_access_tokens/#{impersonation_token.id}", admin)
expect(response).to have_http_status(200)
expect(json_response['impersonation']).to eq(true)
end
end
describe 'DELETE /users/:user_id/personal_access_tokens/:personal_access_token_id' do
let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) } let!(:personal_access_token) { create(:personal_access_token, user: user, revoked: false) }
let!(:impersonation_token) { create(:impersonation_personal_access_token, user: user, revoked: false) } let!(:impersonation_token) { create(:impersonation_personal_access_token, user: user, revoked: false) }
...@@ -1280,7 +1321,7 @@ describe API::Users, api: true do ...@@ -1280,7 +1321,7 @@ describe API::Users, api: true do
end end
it 'returns a 404 error if personal access token not found' do it 'returns a 404 error if personal access token not found' do
delete api("/users/#{user.id}/personal_access_tokens/42", admin) delete api("/users/#{user.id}/personal_access_tokens/#{not_existing_pat_id}", admin)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 PersonalAccessToken Not Found') expect(json_response['message']).to eq('404 PersonalAccessToken Not Found')
...@@ -1296,20 +1337,17 @@ describe API::Users, api: true do ...@@ -1296,20 +1337,17 @@ describe API::Users, api: true do
it 'revokes a personal access token' do it 'revokes a personal access token' do
delete api("/users/#{user.id}/personal_access_tokens/#{personal_access_token.id}", admin) delete api("/users/#{user.id}/personal_access_tokens/#{personal_access_token.id}", admin)
expect(response).to have_http_status(200) expect(response).to have_http_status(204)
expect(personal_access_token.revoked).to eq(false) expect(personal_access_token.revoked).to eq(false)
expect(personal_access_token.reload.revoked).to eq(true) expect(personal_access_token.reload.revoked).to eq(true)
expect(json_response['revoked']).to eq(true)
expect(json_response['token']).to be_present
end end
it 'revokes an impersonation token' do it 'revokes an impersonation token' do
delete api("/users/#{user.id}/personal_access_tokens/#{impersonation_token.id}", admin) delete api("/users/#{user.id}/personal_access_tokens/#{impersonation_token.id}", admin)
expect(response).to have_http_status(200) expect(response).to have_http_status(204)
expect(impersonation_token.revoked).to eq(false) expect(impersonation_token.revoked).to eq(false)
expect(impersonation_token.reload.revoked).to eq(true) expect(impersonation_token.reload.revoked).to eq(true)
expect(json_response['revoked']).to eq(true)
end 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