Commit 524506e9 authored by Steve Abrams's avatar Steve Abrams

Deploy key list API endpoint for projects

API endpoint for viewing all deploy tokens for a project
Remove token from DeployToken entity
Add api schema fixture for deploy tokens.
parent c118dd50
......@@ -312,6 +312,7 @@ class ProjectPolicy < BasePolicy
enable :destroy_artifacts
enable :daily_statistics
enable :admin_operations
enable :read_deploy_token
end
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
......
---
title: Add endpoint for listing all deploy tokens for a project
merge_request: 25186
author:
type: added
......@@ -2,15 +2,14 @@
## List all deploy tokens
Get a list of all deploy tokens across all projects of the GitLab instance.
Get a list of all deploy tokens across the GitLab instance. This endpoint requires admin access.
>**Note:**
> This endpoint requires admin access.
```
```plaintext
GET /deploy_tokens
```
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/deploy_tokens"
```
......@@ -24,7 +23,47 @@ Example response:
"name": "MyToken",
"username": "gitlab+deploy-token-1",
"expires_at": "2020-02-14T00:00:00.000Z",
"token": "jMRvtPNxrn3crTAGukpZ",
"scopes": [
"read_repository",
"read_registry"
]
}
]
```
## Project deploy tokens
Project deploy token API endpoints require project maintainer access or higher.
### List project deploy tokens
Get a list of a project's deploy tokens.
```plaintext
GET /projects/:id/deploy_tokens
```
Parameters:
| Attribute | Type | Required | Description |
|:---------------|:---------------|:---------|:-----------------------------------------------------------------------------|
| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deploy_tokens"
```
Example response:
```json
[
{
"id": 1,
"name": "MyToken",
"username": "gitlab+deploy-token-1",
"expires_at": "2020-02-14T00:00:00.000Z",
"scopes": [
"read_repository",
"read_registry"
......
......@@ -4,8 +4,6 @@ module API
class DeployTokens < Grape::API
include PaginationParams
before { authenticated_as_admin! }
desc 'Return all deploy tokens' do
detail 'This feature was introduced in GitLab 12.9.'
success Entities::DeployToken
......@@ -14,7 +12,27 @@ module API
use :pagination
end
get 'deploy_tokens' do
authenticated_as_admin!
present paginate(DeployToken.all), with: Entities::DeployToken
end
params do
requires :id, type: Integer, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
params do
use :pagination
end
desc 'List deploy tokens for a project' do
detail 'This feature was introduced in GitLab 12.9'
success Entities::DeployToken
end
get ':id/deploy_tokens' do
authorize!(:read_deploy_token, user_project)
present paginate(user_project.deploy_tokens), with: Entities::DeployToken
end
end
end
end
......@@ -3,7 +3,8 @@
module API
module Entities
class DeployToken < Grape::Entity
expose :id, :name, :username, :expires_at, :token, :scopes
# exposing :token is a security risk and should be avoided
expose :id, :name, :username, :expires_at, :scopes
end
end
end
{
"type": "object",
"required": [
"id",
"name",
"username",
"expires_at",
"scopes"
],
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"username": {
"type": "string"
},
"expires_at": {
"type": "date"
},
"scopes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
\ No newline at end of file
{
"type": "array",
"items": {
"$ref": "deploy_token.json"
}
}
\ No newline at end of file
......@@ -52,7 +52,7 @@ describe ProjectPolicy do
admin_snippet admin_project_member admin_note admin_wiki admin_project
admin_commit_status admin_build admin_container_image
admin_pipeline admin_environment admin_deployment destroy_release add_cluster
daily_statistics
daily_statistics read_deploy_token
]
end
......
......@@ -3,43 +3,84 @@
require 'spec_helper'
describe API::DeployTokens do
let(:user) { create(:user) }
let(:creator) { create(:user) }
let(:project) { create(:project, creator_id: creator.id) }
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
describe 'GET /deploy_tokens' do
subject { get api('/deploy_tokens', user) }
subject do
get api('/deploy_tokens', user)
response
end
context 'when unauthenticated' do
let(:user) { nil }
it 'rejects the response as unauthorized' do
subject
expect(response).to have_gitlab_http_status(:unauthorized)
end
it { is_expected.to have_gitlab_http_status(:unauthorized) }
end
context 'when authenticated as non-admin user' do
let(:user) { creator }
it 'rejects the response as forbidden' do
subject
expect(response).to have_gitlab_http_status(:forbidden)
end
it { is_expected.to have_gitlab_http_status(:forbidden) }
end
context 'when authenticated as admin' do
let(:user) { create(:admin) }
it { is_expected.to have_gitlab_http_status(:ok) }
it 'returns all deploy tokens' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['id']).to eq(deploy_token.id)
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
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)
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