2020-02-20 03:08:57 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-06-24 06:09:01 +00:00
|
|
|
RSpec.describe API::DeployTokens do
|
2020-03-09 00:08:14 +00:00
|
|
|
let_it_be(:user) { create(:user) }
|
|
|
|
let_it_be(:creator) { create(:user) }
|
|
|
|
let_it_be(:project) { create(:project, creator_id: creator.id) }
|
|
|
|
let_it_be(:group) { create(:group) }
|
2020-02-20 03:08:57 +00:00
|
|
|
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
|
2020-03-09 00:08:14 +00:00
|
|
|
let!(:group_deploy_token) { create(:deploy_token, :group, groups: [group]) }
|
2020-02-20 03:08:57 +00:00
|
|
|
|
2020-03-11 06:10:11 +00:00
|
|
|
shared_examples 'with feature flag disabled' do
|
|
|
|
context 'disabled feature flag' do
|
|
|
|
before do
|
|
|
|
stub_feature_flags(deploy_tokens_api: false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:service_unavailable) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-02-20 03:08:57 +00:00
|
|
|
describe 'GET /deploy_tokens' do
|
2020-02-28 12:09:05 +00:00
|
|
|
subject do
|
|
|
|
get api('/deploy_tokens', user)
|
|
|
|
response
|
|
|
|
end
|
2020-02-20 03:08:57 +00:00
|
|
|
|
2020-03-11 06:10:11 +00:00
|
|
|
it_behaves_like 'with feature flag disabled'
|
|
|
|
|
2020-02-20 03:08:57 +00:00
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
|
|
|
|
2020-02-28 12:09:05 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:unauthorized) }
|
2020-02-20 03:08:57 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
let(:user) { creator }
|
|
|
|
|
2020-02-28 12:09:05 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
2020-02-20 03:08:57 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as admin' do
|
|
|
|
let(:user) { create(:admin) }
|
|
|
|
|
2020-02-28 12:09:05 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:ok) }
|
|
|
|
|
2020-02-20 03:08:57 +00:00
|
|
|
it 'returns all deploy tokens' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(response).to include_pagination_headers
|
2020-02-28 12:09:05 +00:00
|
|
|
expect(response).to match_response_schema('public_api/v4/deploy_tokens')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'GET /projects/:id/deploy_tokens' do
|
|
|
|
subject do
|
|
|
|
get api("/projects/#{project.id}/deploy_tokens", user)
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:not_found) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
before do
|
|
|
|
project.add_developer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as maintainer' do
|
|
|
|
let!(:other_deploy_token) { create(:deploy_token) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
project.add_maintainer(user)
|
|
|
|
end
|
|
|
|
|
2020-03-11 06:10:11 +00:00
|
|
|
it_behaves_like 'with feature flag disabled'
|
|
|
|
|
2020-02-28 12:09:05 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:ok) }
|
|
|
|
|
|
|
|
it 'returns all deploy tokens for the project' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(response).to include_pagination_headers
|
|
|
|
expect(response).to match_response_schema('public_api/v4/deploy_tokens')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not return deploy tokens for other projects' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
token_ids = json_response.map { |token| token['id'] }
|
|
|
|
expect(token_ids).not_to include(other_deploy_token.id)
|
2020-02-20 03:08:57 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-03-09 00:08:14 +00:00
|
|
|
|
2020-03-11 06:10:11 +00:00
|
|
|
describe 'GET /groups/:id/deploy_tokens' do
|
|
|
|
subject do
|
|
|
|
get api("/groups/#{group.id}/deploy_tokens", user)
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
before do
|
|
|
|
group.add_developer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as maintainer' do
|
|
|
|
let!(:other_deploy_token) { create(:deploy_token, :group) }
|
|
|
|
|
|
|
|
before do
|
|
|
|
group.add_maintainer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_behaves_like 'with feature flag disabled'
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:ok) }
|
|
|
|
|
|
|
|
it 'returns all deploy tokens for the group' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(response).to include_pagination_headers
|
|
|
|
expect(response).to match_response_schema('public_api/v4/deploy_tokens')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not return deploy tokens for other groups' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
token_ids = json_response.map { |token| token['id'] }
|
|
|
|
expect(token_ids).not_to include(other_deploy_token.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-12 12:09:17 +00:00
|
|
|
describe 'DELETE /projects/:id/deploy_tokens/:token_id' do
|
2020-03-09 00:08:14 +00:00
|
|
|
subject do
|
2020-03-12 12:09:17 +00:00
|
|
|
delete api("/projects/#{project.id}/deploy_tokens/#{deploy_token.id}", user)
|
2020-03-09 00:08:14 +00:00
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
|
|
|
|
2020-03-12 12:09:17 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:not_found) }
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
before do
|
2020-03-12 12:09:17 +00:00
|
|
|
project.add_developer(user)
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as maintainer' do
|
|
|
|
before do
|
2020-03-12 12:09:17 +00:00
|
|
|
project.add_maintainer(user)
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
|
2020-03-12 12:09:17 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:no_content) }
|
2020-03-09 00:08:14 +00:00
|
|
|
|
2020-04-02 12:08:18 +00:00
|
|
|
it 'calls the deploy token destroy service' do
|
|
|
|
expect(::Projects::DeployTokens::DestroyService).to receive(:new)
|
|
|
|
.with(project, user, token_id: deploy_token.id)
|
|
|
|
.and_return(true)
|
|
|
|
|
|
|
|
subject
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'invalid request' do
|
2020-03-11 06:10:11 +00:00
|
|
|
it 'returns not found with invalid group id' do
|
2020-03-12 12:09:17 +00:00
|
|
|
delete api("/projects/bad_id/deploy_tokens/#{group_deploy_token.id}", user)
|
2020-03-09 00:08:14 +00:00
|
|
|
|
2020-03-11 06:10:11 +00:00
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
|
2020-03-12 12:09:17 +00:00
|
|
|
it 'returns bad_request with invalid token id' do
|
2020-04-02 12:08:18 +00:00
|
|
|
expect(::Projects::DeployTokens::DestroyService).to receive(:new)
|
|
|
|
.with(project, user, token_id: 999)
|
|
|
|
.and_raise(ActiveRecord::RecordNotFound)
|
|
|
|
|
|
|
|
delete api("/projects/#{project.id}/deploy_tokens/999", user)
|
2020-03-09 00:08:14 +00:00
|
|
|
|
2020-04-02 12:08:18 +00:00
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
2020-03-09 00:08:14 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
context 'deploy token creation' do
|
2020-07-01 21:08:51 +00:00
|
|
|
shared_examples 'creating a deploy token' do |entity, unauthenticated_response, authorized_role|
|
2020-04-21 15:21:10 +00:00
|
|
|
let(:expires_time) { 1.year.from_now }
|
2020-03-11 21:09:19 +00:00
|
|
|
let(:params) do
|
|
|
|
{
|
|
|
|
name: 'Foo',
|
2020-04-21 15:21:10 +00:00
|
|
|
expires_at: expires_time,
|
2020-03-11 21:09:19 +00:00
|
|
|
scopes: [
|
|
|
|
'read_repository'
|
|
|
|
],
|
|
|
|
username: 'Bar'
|
|
|
|
}
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(unauthenticated_response) }
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
before do
|
|
|
|
send(entity).add_developer(user)
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
2020-03-10 09:08:10 +00:00
|
|
|
end
|
|
|
|
|
2020-07-01 21:08:51 +00:00
|
|
|
context "when authenticated as #{authorized_role}" do
|
2020-03-11 21:09:19 +00:00
|
|
|
before do
|
2020-07-01 21:08:51 +00:00
|
|
|
send(entity).send("add_#{authorized_role}", user)
|
2020-03-11 21:09:19 +00:00
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
it 'creates the deploy token' do
|
|
|
|
expect { subject }.to change { DeployToken.count }.by(1)
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
expect(response).to have_gitlab_http_status(:created)
|
|
|
|
expect(response).to match_response_schema('public_api/v4/deploy_token')
|
2020-04-21 15:21:10 +00:00
|
|
|
expect(json_response['name']).to eq('Foo')
|
|
|
|
expect(json_response['scopes']).to eq(['read_repository'])
|
|
|
|
expect(json_response['username']).to eq('Bar')
|
|
|
|
expect(json_response['expires_at'].to_time.to_i).to eq(expires_time.to_i)
|
2020-03-11 21:09:19 +00:00
|
|
|
end
|
2020-03-26 18:08:03 +00:00
|
|
|
|
|
|
|
context 'with no optional params given' do
|
|
|
|
let(:params) do
|
|
|
|
{
|
|
|
|
name: 'Foo',
|
|
|
|
scopes: [
|
|
|
|
'read_repository'
|
|
|
|
]
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'creates the deploy token with default values' do
|
|
|
|
subject
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:created)
|
|
|
|
expect(json_response['username']).to match(/gitlab\+deploy-token-\d+/)
|
|
|
|
expect(json_response['expires_at']).to eq(nil)
|
|
|
|
end
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
context 'with an invalid scope' do
|
|
|
|
before do
|
|
|
|
params[:scopes] = %w[read_repository all_access]
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:bad_request) }
|
2020-03-10 09:08:10 +00:00
|
|
|
end
|
2020-03-11 21:09:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'POST /projects/:id/deploy_tokens' do
|
|
|
|
subject do
|
|
|
|
post api("/projects/#{project.id}/deploy_tokens", user), params: params
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
2020-07-01 21:08:51 +00:00
|
|
|
it_behaves_like 'creating a deploy token', :project, :not_found, :maintainer
|
2020-03-11 21:09:19 +00:00
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
|
2020-03-11 21:09:19 +00:00
|
|
|
describe 'POST /groups/:id/deploy_tokens' do
|
|
|
|
subject do
|
|
|
|
post api("/groups/#{group.id}/deploy_tokens", user), params: params
|
|
|
|
response
|
2020-03-10 09:08:10 +00:00
|
|
|
end
|
2020-03-11 21:09:19 +00:00
|
|
|
|
2020-07-01 21:08:51 +00:00
|
|
|
it_behaves_like 'creating a deploy token', :group, :forbidden, :owner
|
|
|
|
|
|
|
|
context 'when authenticated as maintainer' do
|
|
|
|
before do
|
|
|
|
group.add_maintainer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:params) { { name: 'test', scopes: ['read_repository'] } }
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
2020-03-10 09:08:10 +00:00
|
|
|
end
|
|
|
|
end
|
2020-03-12 12:09:17 +00:00
|
|
|
|
|
|
|
describe 'DELETE /groups/:id/deploy_tokens/:token_id' do
|
|
|
|
subject do
|
|
|
|
delete api("/groups/#{group.id}/deploy_tokens/#{group_deploy_token.id}", user)
|
|
|
|
response
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when unauthenticated' do
|
|
|
|
let(:user) { nil }
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as non-admin user' do
|
|
|
|
before do
|
|
|
|
group.add_developer(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as maintainer' do
|
|
|
|
before do
|
|
|
|
group.add_maintainer(user)
|
|
|
|
end
|
|
|
|
|
2020-07-01 21:08:51 +00:00
|
|
|
it { is_expected.to have_gitlab_http_status(:forbidden) }
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when authenticated as owner' do
|
|
|
|
before do
|
|
|
|
group.add_owner(user)
|
|
|
|
end
|
|
|
|
|
2020-04-02 12:08:18 +00:00
|
|
|
it 'calls the deploy token destroy service' do
|
|
|
|
expect(::Groups::DeployTokens::DestroyService).to receive(:new)
|
|
|
|
.with(group, user, token_id: group_deploy_token.id)
|
|
|
|
.and_return(true)
|
2020-03-12 12:09:17 +00:00
|
|
|
|
2020-04-02 12:08:18 +00:00
|
|
|
subject
|
2020-03-12 12:09:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'invalid request' do
|
|
|
|
it 'returns bad request with invalid group id' do
|
|
|
|
delete api("/groups/bad_id/deploy_tokens/#{group_deploy_token.id}", user)
|
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns not found with invalid deploy token id' do
|
2020-04-02 12:08:18 +00:00
|
|
|
expect(::Groups::DeployTokens::DestroyService).to receive(:new)
|
|
|
|
.with(group, user, token_id: 999)
|
|
|
|
.and_raise(ActiveRecord::RecordNotFound)
|
|
|
|
|
|
|
|
delete api("/groups/#{group.id}/deploy_tokens/999", user)
|
2020-03-12 12:09:17 +00:00
|
|
|
|
|
|
|
expect(response).to have_gitlab_http_status(:not_found)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2020-02-20 03:08:57 +00:00
|
|
|
end
|