Commit 47db8303 authored by Dmytro Zaporozhets's avatar Dmytro Zaporozhets

Merge branch '30595-api-for-protected-environments-2' into 'master'

Add create and delete methods for protected environments API

See merge request gitlab-org/gitlab!23784
parents e7e0abb0 ed757ec0
...@@ -38,10 +38,61 @@ module API ...@@ -38,10 +38,61 @@ module API
requires :name, type: String, desc: 'The name of the protected environment' requires :name, type: String, desc: 'The name of the protected environment'
end end
get ':id/protected_environments/:name', requirements: ENVIRONMENT_ENDPOINT_REQUIREMENTS do get ':id/protected_environments/:name', requirements: ENVIRONMENT_ENDPOINT_REQUIREMENTS do
protected_environment = user_project.protected_environments.find_by_name!(params[:name])
present protected_environment, with: ::EE::API::Entities::ProtectedEnvironment, project: user_project present protected_environment, with: ::EE::API::Entities::ProtectedEnvironment, project: user_project
end end
desc 'Protect a single environment' do
detail 'This feature is gated by the :protected_environments_api feature flag.'
success ::EE::API::Entities::ProtectedEnvironment
end
params do
requires :name, type: String, desc: 'The name of the protected environment'
requires :deploy_access_levels, type: Array, desc: 'An array of users/groups allowed to deploy environment' do
optional :access_level, type: Integer, values: ::ProtectedEnvironment::DeployAccessLevel::ALLOWED_ACCESS_LEVELS
optional :user_id, type: Integer
optional :group_id, type: Integer
end
end
post ':id/protected_environments' do
protected_environment = user_project.protected_environments.find_by_name(params[:name])
if protected_environment
conflict!("Protected environment '#{params[:name]}' already exists")
end
declared_params = declared_params(include_missing: false)
# TODO: replace with `as: :deploy_access_levels_attributes` after the Grape update:
# https://gitlab.com/gitlab-org/gitlab/issues/195960
# original issue - https://github.com/ruby-grape/grape/issues/1874
declared_params[:deploy_access_levels_attributes] = declared_params.delete(:deploy_access_levels)
protected_environment = ::ProtectedEnvironments::CreateService
.new(user_project, current_user, declared_params).execute
if protected_environment.persisted?
present protected_environment, with: ::EE::API::Entities::ProtectedEnvironment, project: user_project
else
render_api_error!(protected_environment.errors.full_messages, 422)
end
end
desc 'Unprotect a single environment' do
detail 'This feature is gated by the :protected_environments_api feature flag.'
end
params do
requires :name, type: String, desc: 'The name of the protected environment'
end
delete ':id/protected_environments/:name', requirements: ENVIRONMENT_ENDPOINT_REQUIREMENTS do
destroy_conditionally!(protected_environment) do
::ProtectedEnvironments::DestroyService.new(user_project, current_user).execute(protected_environment)
end
end
end
helpers do
def protected_environment
@protected_environment ||= user_project.protected_environments.find_by_name!(params[:name])
end
end end
end end
end end
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
describe API::ProtectedEnvironments do describe API::ProtectedEnvironments do
include AccessMatchersForRequest
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:protected_environment_name) { 'production' } let(:protected_environment_name) { 'production' }
...@@ -12,39 +14,10 @@ describe API::ProtectedEnvironments do ...@@ -12,39 +14,10 @@ describe API::ProtectedEnvironments do
end end
shared_examples 'requests for non-maintainers' do shared_examples 'requests for non-maintainers' do
context 'when authenticated as a guest' do it { expect { request }.to be_denied_for(:guest).of(project) }
before do it { expect { request }.to be_denied_for(:developer).of(project) }
project.add_guest(user) it { expect { request }.to be_denied_for(:reporter).of(project) }
end it { expect { request }.to be_denied_for(:anonymous) }
it_behaves_like '403 response'
end
context 'when authenticated as a developer' do
before do
project.add_developer(user)
end
it_behaves_like '403 response'
end
context 'when authenticated as a reporter' do
before do
project.add_reporter(user)
end
it_behaves_like '403 response'
end
context 'when user has no access to project' do
it_behaves_like '404 response'
end
context 'when unauthenticated' do
let(:user) { nil }
it_behaves_like '404 response'
end
end end
describe "GET /projects/:id/protected_environments" do describe "GET /projects/:id/protected_environments" do
...@@ -109,4 +82,92 @@ describe API::ProtectedEnvironments do ...@@ -109,4 +82,92 @@ describe API::ProtectedEnvironments do
it_behaves_like 'requests for non-maintainers' it_behaves_like 'requests for non-maintainers'
end end
describe 'POST /projects/:id/protected_environments/' do
let(:api_url) { api("/projects/#{project.id}/protected_environments/", user) }
context 'when authenticated as a maintainer' do
before do
project.add_maintainer(user)
end
it 'protects the environment with user allowed to deploy' do
deployer = create(:user)
project.add_developer(deployer)
post api_url, params: { name: 'staging', deploy_access_levels: [{ user_id: deployer.id }] }
expect(response).to have_gitlab_http_status(201)
expect(response).to match_response_schema('public_api/v4/protected_environment', dir: 'ee')
expect(json_response['name']).to eq('staging')
expect(json_response['deploy_access_levels'].first['user_id']).to eq(deployer.id)
end
it 'protects the environment with group allowed to deploy' do
group = create(:project_group_link, project: project).group
post api_url, params: { name: 'staging', deploy_access_levels: [{ group_id: group.id }] }
expect(response).to have_gitlab_http_status(201)
expect(response).to match_response_schema('public_api/v4/protected_environment', dir: 'ee')
expect(json_response['name']).to eq('staging')
expect(json_response['deploy_access_levels'].first['group_id']).to eq(group.id)
end
it 'protects the environment with maintainers allowed to deploy' do
post api_url, params: { name: 'staging', deploy_access_levels: [{ access_level: Gitlab::Access::MAINTAINER }] }
expect(response).to have_gitlab_http_status(201)
expect(response).to match_response_schema('public_api/v4/protected_environment', dir: 'ee')
expect(json_response['name']).to eq('staging')
expect(json_response['deploy_access_levels'].first['access_level']).to eq(Gitlab::Access::MAINTAINER)
end
it 'returns 409 error if environment is already protected' do
deployer = create(:user)
project.add_developer(deployer)
post api_url, params: { name: 'production', deploy_access_levels: [{ user_id: deployer.id }] }
expect(response).to have_gitlab_http_status(409)
end
context 'without deploy_access_levels' do
it_behaves_like '400 response' do
let(:request) { post api_url, params: { name: 'staging' } }
end
end
it 'returns error with invalid deploy access level' do
post api_url, params: { name: 'staging', deploy_access_levels: [{ access_level: nil }] }
expect(response).to have_gitlab_http_status(422)
end
end
it_behaves_like 'requests for non-maintainers' do
let(:request) { post api_url, params: { name: 'staging' } }
end
end
describe 'DELETE /projects/:id/protected_environments/:environment' do
let(:route) { "/projects/#{project.id}/protected_environments/production" }
let(:request) { delete api(route, user) }
context 'when authenticated as a maintainer' do
before do
project.add_maintainer(user)
end
it 'unprotects the environment' do
expect do
request
end.to change { project.protected_environments.count }.by(-1)
expect(response).to have_gitlab_http_status(204)
end
end
it_behaves_like 'requests for non-maintainers'
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