2021-01-29 00:20:46 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2023-06-20 00:43:36 +05:30
|
|
|
RSpec.describe API::PersonalAccessTokens, :aggregate_failures, feature_category: :system_access do
|
2021-01-29 00:20:46 +05:30
|
|
|
let_it_be(:path) { '/personal_access_tokens' }
|
|
|
|
|
|
|
|
describe 'GET /personal_access_tokens' do
|
2022-11-25 23:54:43 +05:30
|
|
|
using RSpec::Parameterized::TableSyntax
|
|
|
|
|
|
|
|
def map_id(json_resonse)
|
|
|
|
json_response.map { |pat| pat['id'] }
|
|
|
|
end
|
|
|
|
|
|
|
|
shared_examples 'response as expected' do |params|
|
|
|
|
subject { get api(path, personal_access_token: current_users_token), params: params }
|
|
|
|
|
|
|
|
it "status, count and result as expected" do
|
|
|
|
subject
|
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
case status
|
|
|
|
when :bad_request
|
2022-11-25 23:54:43 +05:30
|
|
|
expect(json_response).to eq(result)
|
2023-01-13 00:05:48 +05:30
|
|
|
when :ok
|
2022-11-25 23:54:43 +05:30
|
|
|
expect(map_id(json_response)).to a_collection_containing_exactly(*result)
|
|
|
|
end
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(status)
|
|
|
|
expect(json_response.count).to eq(result_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-06-20 00:43:36 +05:30
|
|
|
# Since all user types pass the same test successfully, we can avoid using
|
|
|
|
# shared examples and test each user type separately for its expected
|
|
|
|
# returned value.
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
context 'logged in as an Administrator' do
|
|
|
|
let_it_be(:current_user) { create(:admin) }
|
2023-06-20 00:43:36 +05:30
|
|
|
let_it_be(:current_users_token) { create(:personal_access_token, :admin_mode, user: current_user) }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
it 'returns all PATs by default' do
|
|
|
|
get api(path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response.count).to eq(PersonalAccessToken.all.count)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filtered with user_id parameter' do
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:token) { create(:personal_access_token) }
|
|
|
|
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: token.user) }
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
it 'returns only PATs belonging to that user' do
|
2023-06-20 00:43:36 +05:30
|
|
|
get api(path, current_user, admin_mode: true), params: { user_id: token.user.id }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
2021-08-04 16:29:09 +05:30
|
|
|
expect(json_response.count).to eq(2)
|
2022-11-25 23:54:43 +05:30
|
|
|
expect(json_response.first['user_id']).to eq(token.user.id)
|
2021-08-04 16:29:09 +05:30
|
|
|
expect(json_response.last['id']).to eq(token_impersonated.id)
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
context 'filter with revoked parameter' do
|
|
|
|
let_it_be(:revoked_token) { create(:personal_access_token, revoked: true) }
|
|
|
|
let_it_be(:not_revoked_token1) { create(:personal_access_token, revoked: false) }
|
|
|
|
let_it_be(:not_revoked_token2) { create(:personal_access_token, revoked: false) }
|
|
|
|
|
|
|
|
where(:revoked, :status, :result_count, :result) do
|
|
|
|
true | :ok | 1 | lazy { [revoked_token.id] }
|
|
|
|
false | :ok | 3 | lazy { [not_revoked_token1.id, not_revoked_token2.id, current_users_token.id] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "revoked is invalid" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', revoked: params[:revoked]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter with active parameter' do
|
|
|
|
let_it_be(:inactive_token1) { create(:personal_access_token, revoked: true) }
|
|
|
|
let_it_be(:inactive_token2) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
|
|
|
|
let_it_be(:active_token) { create(:personal_access_token) }
|
|
|
|
|
|
|
|
where(:state, :status, :result_count, :result) do
|
|
|
|
'inactive' | :ok | 2 | lazy { [inactive_token1.id, inactive_token2.id] }
|
|
|
|
'active' | :ok | 2 | lazy { [active_token.id, current_users_token.id] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "state does not have a valid value" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', state: params[:state]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter with created parameter' do
|
2023-01-13 00:05:48 +05:30
|
|
|
let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 01, 12, 30, 25)) }
|
2022-11-25 23:54:43 +05:30
|
|
|
|
|
|
|
context 'test created_before' do
|
|
|
|
where(:created_at, :status, :result_count, :result) do
|
|
|
|
'2022-01-02' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'2022-01-01' | :ok | 0 | lazy { [] }
|
|
|
|
'2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
|
|
|
|
'2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'2022-01-01T:12:30:26' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "created_before is invalid" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', created_before: params[:created_at]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'test created_after' do
|
|
|
|
where(:created_at, :status, :result_count, :result) do
|
|
|
|
'2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
'2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
'2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
'2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
(DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "created_after is invalid" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', created_after: params[:created_at]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter with last_used parameter' do
|
2023-01-13 00:05:48 +05:30
|
|
|
let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25)) }
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:never_used_token) { create(:personal_access_token) }
|
|
|
|
|
|
|
|
context 'test last_used_before' do
|
|
|
|
where(:last_used_at, :status, :result_count, :result) do
|
|
|
|
'2022-01-02' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'2022-01-01' | :ok | 0 | lazy { [] }
|
|
|
|
'2022-01-01T12:30:24' | :ok | 0 | lazy { [] }
|
|
|
|
'2022-01-01T12:30:25' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'2022-01-01T12:30:26' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "last_used_before is invalid" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', last_used_before: params[:last_used_at]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'test last_used_after' do
|
|
|
|
where(:last_used_at, :status, :result_count, :result) do
|
|
|
|
'2022-01-03' | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
'2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
'2022-01-01T12:30:26' | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
'2022-01-01T12:30:25' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
(DateTime.now + 1).to_s | :ok | 0 | lazy { [] }
|
|
|
|
'asdf' | :bad_request | 1 | { "error" => "last_used_after is invalid" }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', last_used_after: params[:last_used_at]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter with search parameter' do
|
|
|
|
let_it_be(:token1) { create(:personal_access_token, name: 'test_1') }
|
|
|
|
let_it_be(:token2) { create(:personal_access_token, name: 'test_2') }
|
|
|
|
let_it_be(:token3) { create(:personal_access_token, name: '') }
|
|
|
|
|
|
|
|
where(:pattern, :status, :result_count, :result) do
|
|
|
|
'test' | :ok | 2 | lazy { [token1.id, token2.id] }
|
|
|
|
'' | :ok | 4 | lazy { [token1.id, token2.id, token3.id, current_users_token.id] }
|
|
|
|
'test_1' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'asdf' | :ok | 0 | lazy { [] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', search: params[:pattern]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter created_before/created_after combined with last_used_before/last_used_after' do
|
|
|
|
let_it_be(:date) { DateTime.new(2022, 01, 02) }
|
|
|
|
let_it_be(:token1) { create(:personal_access_token, created_at: date, last_used_at: date) }
|
|
|
|
|
|
|
|
where(:date_before, :date_after, :status, :result_count, :result) do
|
|
|
|
'2022-01-03' | '2022-01-01' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'2022-01-01' | '2022-01-03' | :ok | 0 | lazy { [] }
|
|
|
|
'2022-01-03' | nil | :ok | 1 | lazy { [token1.id] }
|
|
|
|
nil | '2022-01-01' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', { created_before: params[:date_before],
|
|
|
|
created_after: params[:date_after] }
|
|
|
|
it_behaves_like 'response as expected', { last_used_before: params[:date_before],
|
|
|
|
last_used_after: params[:date_after] }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter created_before and created_after combined is valid' do
|
|
|
|
let_it_be(:token1) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02)) }
|
|
|
|
|
|
|
|
where(:created_before, :created_after, :status, :result) do
|
|
|
|
'2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
|
|
|
|
'2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
|
|
|
|
'2022-01-01' | '2022-01-03' | :ok | lazy { [] }
|
|
|
|
'2022-01-03' | nil | :ok | lazy { [token1.id] }
|
|
|
|
nil | '2022-01-01' | :ok | lazy { [token1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it "returns all valid tokens" do
|
|
|
|
get api(path, personal_access_token: current_users_token),
|
|
|
|
params: { created_before: created_before, created_after: created_after }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(status)
|
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
expect(json_response.map { |pat| pat['id'] }).to include(*result) if status == :ok
|
2022-11-25 23:54:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filter last_used_before and last_used_after combined is valid' do
|
2023-01-13 00:05:48 +05:30
|
|
|
let_it_be(:token1) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 02)) }
|
2022-11-25 23:54:43 +05:30
|
|
|
|
|
|
|
where(:last_used_before, :last_used_after, :status, :result) do
|
|
|
|
'2022-01-02' | '2022-01-02' | :ok | lazy { [token1.id] }
|
|
|
|
'2022-01-03' | '2022-01-01' | :ok | lazy { [token1.id] }
|
|
|
|
'2022-01-01' | '2022-01-03' | :ok | lazy { [] }
|
|
|
|
'2022-01-03' | nil | :ok | lazy { [token1.id] }
|
|
|
|
nil | '2022-01-01' | :ok | lazy { [token1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it "returns all valid tokens" do
|
|
|
|
get api(path, personal_access_token: current_users_token),
|
|
|
|
params: { last_used_before: last_used_before, last_used_after: last_used_after }
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(status)
|
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
expect(json_response.map { |pat| pat['id'] }).to include(*result) if status == :ok
|
2022-11-25 23:54:43 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'logged in as a non-Administrator' do
|
|
|
|
let_it_be(:current_user) { create(:user) }
|
|
|
|
let_it_be(:current_users_token) { create(:personal_access_token, user: current_user) }
|
|
|
|
|
|
|
|
it 'returns all PATs belonging to the signed-in user' do
|
|
|
|
get api(path, personal_access_token: current_users_token)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response.count).to eq(1)
|
|
|
|
expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
|
|
|
|
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'filtered with user_id parameter' do
|
2021-01-29 00:20:46 +05:30
|
|
|
let_it_be(:user) { create(:user) }
|
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
it 'returns PATs belonging to the specific user' do
|
|
|
|
get api(path, current_user, personal_access_token: current_users_token), params: { user_id: current_user.id }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response.count).to eq(1)
|
2022-11-25 23:54:43 +05:30
|
|
|
expect(json_response.map { |r| r['id'] }.uniq).to contain_exactly(current_users_token.id)
|
2021-01-29 00:20:46 +05:30
|
|
|
expect(json_response.map { |r| r['user_id'] }.uniq).to contain_exactly(current_user.id)
|
|
|
|
end
|
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
it 'is unauthorized if filtered by a user other than current_user' do
|
|
|
|
get api(path, current_user, personal_access_token: current_users_token), params: { user_id: user.id }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
|
|
|
end
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
context 'filter with revoked parameter' do
|
|
|
|
let_it_be(:users_revoked_token) { create(:personal_access_token, revoked: true, user: current_user) }
|
|
|
|
let_it_be(:not_revoked_token) { create(:personal_access_token, revoked: false) }
|
|
|
|
let_it_be(:oter_revoked_token) { create(:personal_access_token, revoked: true) }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
where(:revoked, :status, :result_count, :result) do
|
|
|
|
true | :ok | 1 | lazy { [users_revoked_token.id] }
|
|
|
|
false | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', revoked: params[:revoked]
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
context 'filter with active parameter' do
|
|
|
|
let_it_be(:users_inactive_token) { create(:personal_access_token, revoked: true, user: current_user) }
|
|
|
|
let_it_be(:inactive_token) { create(:personal_access_token, expires_at: Time.new(2022, 01, 01, 00, 00, 00)) }
|
|
|
|
let_it_be(:other_active_token) { create(:personal_access_token) }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
2022-11-25 23:54:43 +05:30
|
|
|
where(:state, :status, :result_count, :result) do
|
|
|
|
'inactive' | :ok | 1 | lazy { [users_inactive_token.id] }
|
|
|
|
'active' | :ok | 1 | lazy { [current_users_token.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', state: params[:state]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# The created_before filter has been extensively tested in the 'logged in as administrator' section.
|
|
|
|
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
|
|
|
|
context 'filter with created parameter' do
|
|
|
|
let_it_be(:token1) do
|
2023-01-13 00:05:48 +05:30
|
|
|
create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25), user: current_user)
|
2022-11-25 23:54:43 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
let_it_be(:token2) { create(:personal_access_token, created_at: DateTime.new(2022, 01, 02, 12, 30, 25)) }
|
|
|
|
let_it_be(:status) { :ok }
|
|
|
|
|
|
|
|
context 'created_before' do
|
|
|
|
let_it_be(:result_count) { 1 }
|
|
|
|
let_it_be(:result) { [token1.id] }
|
|
|
|
|
|
|
|
it_behaves_like 'response as expected', created_before: '2022-01-03'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'created_after' do
|
|
|
|
let_it_be(:result_count) { 2 }
|
|
|
|
let_it_be(:result) { [token1.id, current_users_token.id] }
|
|
|
|
|
|
|
|
it_behaves_like 'response as expected', created_after: '2022-01-01'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# The last_used_before filter has been extensively tested in the 'logged in as administrator' section.
|
|
|
|
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
|
|
|
|
context 'filter with last_used' do
|
|
|
|
let_it_be(:token1) do
|
|
|
|
create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25), user: current_user)
|
|
|
|
end
|
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
let_it_be(:token2) { create(:personal_access_token, last_used_at: DateTime.new(2022, 01, 01, 12, 30, 25)) }
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:never_used_token) { create(:personal_access_token) }
|
|
|
|
let_it_be(:status) { :ok }
|
|
|
|
|
|
|
|
context 'last_used_before' do
|
|
|
|
let_it_be(:result_count) { 1 }
|
|
|
|
let_it_be(:result) { [token1.id] }
|
|
|
|
|
|
|
|
it_behaves_like 'response as expected', last_used_before: '2022-01-02'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'last_used_after' do
|
|
|
|
let_it_be(:result_count) { 2 }
|
|
|
|
let_it_be(:result) { [token1.id, current_users_token.id] }
|
|
|
|
|
|
|
|
it_behaves_like 'response as expected', last_used_after: '2022-01-01'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# The search filter has been extensively tested in the 'logged in as administrator' section.
|
|
|
|
# Here it is only tested whether PATs to which the user has no access right are excluded from the filter function.
|
|
|
|
context 'filter with search parameter' do
|
|
|
|
let_it_be(:token1) { create(:personal_access_token, name: 'test_1', user: current_user) }
|
|
|
|
let_it_be(:token2) { create(:personal_access_token, name: 'test_1') }
|
|
|
|
let_it_be(:token3) { create(:personal_access_token, name: '') }
|
|
|
|
|
|
|
|
where(:pattern, :status, :result_count, :result) do
|
|
|
|
'test' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
'' | :ok | 2 | lazy { [token1.id, current_users_token.id] }
|
|
|
|
'test_1' | :ok | 1 | lazy { [token1.id] }
|
|
|
|
end
|
|
|
|
|
|
|
|
with_them do
|
|
|
|
it_behaves_like 'response as expected', search: params[:pattern]
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2022-11-25 23:54:43 +05:30
|
|
|
|
|
|
|
context 'not authenticated' do
|
|
|
|
it 'is forbidden' do
|
|
|
|
get api(path)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
|
|
|
end
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
|
2022-07-23 23:45:48 +05:30
|
|
|
describe 'GET /personal_access_tokens/:id' do
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:current_user) { create(:user) }
|
2022-07-23 23:45:48 +05:30
|
|
|
let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:token1) { create(:personal_access_token) }
|
2022-10-11 01:57:18 +05:30
|
|
|
let_it_be(:user_read_only_token) { create(:personal_access_token, scopes: ['read_repository'], user: current_user) }
|
2022-07-23 23:45:48 +05:30
|
|
|
let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
|
|
|
|
let_it_be(:invalid_path) { "/personal_access_tokens/#{non_existing_record_id}" }
|
|
|
|
|
|
|
|
context 'when current_user is an administrator', :enable_admin_mode do
|
|
|
|
let_it_be(:admin_user) { create(:admin) }
|
|
|
|
let_it_be(:admin_token) { create(:personal_access_token, user: admin_user) }
|
|
|
|
let_it_be(:admin_path) { "/personal_access_tokens/#{admin_token.id}" }
|
|
|
|
|
|
|
|
it 'returns admins own PAT by id' do
|
|
|
|
get api(admin_path, admin_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response['id']).to eq(admin_token.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns a different users PAT by id' do
|
|
|
|
get api(user_token_path, admin_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response['id']).to eq(user_token.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails to return PAT because no PAT exists with this id' do
|
|
|
|
get api(invalid_path, admin_user)
|
|
|
|
|
2022-08-27 11:52:29 +05:30
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
2022-07-23 23:45:48 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when current_user is not an administrator' do
|
|
|
|
let_it_be(:other_users_path) { "/personal_access_tokens/#{token1.id}" }
|
|
|
|
|
|
|
|
it 'returns users own PAT by id' do
|
|
|
|
get api(user_token_path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:ok)
|
|
|
|
expect(json_response['id']).to eq(user_token.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails to return other users PAT by id' do
|
|
|
|
get api(other_users_path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'fails to return PAT because no PAT exists with this id' do
|
|
|
|
get api(invalid_path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
|
|
|
end
|
2022-07-16 23:28:13 +05:30
|
|
|
|
2022-10-11 01:57:18 +05:30
|
|
|
it 'fails to return own PAT by id with read_repository token' do
|
|
|
|
get api(user_token_path, current_user, personal_access_token: user_read_only_token)
|
2022-07-16 23:28:13 +05:30
|
|
|
|
2022-10-11 01:57:18 +05:30
|
|
|
expect(response).to have_gitlab_http_status(:forbidden)
|
2022-07-16 23:28:13 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
describe 'DELETE /personal_access_tokens/:id' do
|
2022-11-25 23:54:43 +05:30
|
|
|
let_it_be(:current_user) { create(:user) }
|
|
|
|
let_it_be(:token1) { create(:personal_access_token) }
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
let(:path) { "/personal_access_tokens/#{token1.id}" }
|
|
|
|
|
|
|
|
context 'when current_user is an administrator', :enable_admin_mode do
|
|
|
|
let_it_be(:admin_user) { create(:admin) }
|
|
|
|
let_it_be(:admin_token) { create(:personal_access_token, user: admin_user) }
|
|
|
|
let_it_be(:admin_path) { "/personal_access_tokens/#{admin_token.id}" }
|
2022-10-11 01:57:18 +05:30
|
|
|
let_it_be(:admin_read_only_token) do
|
|
|
|
create(:personal_access_token, scopes: ['read_repository'], user: admin_user)
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
it 'revokes a different users token' do
|
|
|
|
delete api(path, admin_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:no_content)
|
|
|
|
expect(token1.reload.revoked?).to be true
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'revokes their own token' do
|
|
|
|
delete api(admin_path, admin_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:no_content)
|
|
|
|
end
|
2022-10-11 01:57:18 +05:30
|
|
|
|
|
|
|
it 'fails to revoke a different user token using a readonly scope' do
|
|
|
|
delete api(path, personal_access_token: admin_read_only_token)
|
|
|
|
|
|
|
|
expect(token1.reload.revoked?).to be false
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context 'when current_user is not an administrator' do
|
|
|
|
let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
|
|
|
|
let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
|
2021-08-04 16:29:09 +05:30
|
|
|
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: current_user) }
|
2021-01-29 00:20:46 +05:30
|
|
|
|
|
|
|
it 'fails revokes a different users token' do
|
|
|
|
delete api(path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:bad_request)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'revokes their own token' do
|
|
|
|
delete api(user_token_path, current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:no_content)
|
|
|
|
end
|
2021-08-04 16:29:09 +05:30
|
|
|
|
|
|
|
it 'cannot revoke impersonation token' do
|
|
|
|
delete api("/personal_access_tokens/#{token_impersonated.id}", current_user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:bad_request)
|
|
|
|
end
|
2021-01-29 00:20:46 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|