Commit d40d598b authored by James Lopez's avatar James Lopez

Merge branch '214727-composer-publish-package-branch-retrieve' into 'master'

Handle composer branch/tag retrieval

See merge request gitlab-org/gitlab!29991
parents 3ea8d5df 07fd8655
...@@ -74,11 +74,11 @@ module API ...@@ -74,11 +74,11 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do before do
unless ::Feature.enabled?(:composer_packages, authorized_user_project) unless ::Feature.enabled?(:composer_packages, unauthorized_user_project!)
not_found! not_found!
end end
authorize_packages_feature!(authorized_user_project) authorize_packages_feature!(unauthorized_user_project!)
end end
desc 'Composer packages endpoint for registering packages' desc 'Composer packages endpoint for registering packages'
...@@ -92,6 +92,14 @@ module API ...@@ -92,6 +92,14 @@ module API
post do post do
authorize_create_package!(authorized_user_project) authorize_create_package!(authorized_user_project)
if params[:branch].present?
find_branch!(params[:branch])
elsif params[:tag].present?
find_tag!(params[:tag])
else
bad_request!
end
created! created!
end end
end end
......
...@@ -7,7 +7,7 @@ describe API::ComposerPackages do ...@@ -7,7 +7,7 @@ describe API::ComposerPackages do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let_it_be(:group, reload: true) { create(:group, :public) } let_it_be(:group, reload: true) { create(:group, :public) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:project, reload: true) { create(:project, :public) } let_it_be(:project, reload: true) { create(:project, :repository, path: 'my.project') }
describe 'GET /api/v4/group/:id/-/packages/composer/packages' do describe 'GET /api/v4/group/:id/-/packages/composer/packages' do
let(:url) { "/group/#{group.id}/-/packages/composer/packages.json" } let(:url) { "/group/#{group.id}/-/packages/composer/packages.json" }
...@@ -175,54 +175,104 @@ describe API::ComposerPackages do ...@@ -175,54 +175,104 @@ describe API::ComposerPackages do
describe 'POST /api/v4/projects/:id/packages/composer' do describe 'POST /api/v4/projects/:id/packages/composer' do
let(:url) { "/projects/#{project.id}/packages/composer" } let(:url) { "/projects/#{project.id}/packages/composer" }
let(:params) { { branch: 'foobar' } } let(:params) { {} }
subject { post api(url), headers: headers } subject { post api(url), headers: headers, params: params }
shared_examples 'composer package publish' do
context 'with packages features enabled' do
before do
stub_licensed_features(packages: true)
end
context 'with valid project' do
using RSpec::Parameterized::TableSyntax
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process Composer api request' | :created
'PUBLIC' | :guest | true | true | 'process Composer api request' | :forbidden
'PUBLIC' | :developer | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process Composer api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process Composer api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process Composer api request' | :created
'PRIVATE' | :guest | true | true | 'process Composer api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process Composer api request' | :not_found
'PRIVATE' | :guest | false | true | 'process Composer api request' | :not_found
'PRIVATE' | :developer | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process Composer api request' | :unauthorized
end
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
it_behaves_like 'rejects Composer access with unknown project id'
end
end
it_behaves_like 'rejects Composer packages access with packages features disabled'
context 'with no tag or branch params' do
let(:headers) { build_basic_auth_header(user.username, personal_access_token.token) }
context 'with packages features enabled' do
before do before do
stub_licensed_features(packages: true) stub_licensed_features(packages: true)
end end
context 'with valid project' do it_behaves_like 'process Composer api request', :developer, :bad_request
using RSpec::Parameterized::TableSyntax end
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do context 'with a tag' do
'PUBLIC' | :developer | true | true | 'process Composer api request' | :created context 'with an existing branch' do
'PUBLIC' | :guest | true | true | 'process Composer api request' | :forbidden let(:params) { { tag: 'v1.0.0' } }
'PUBLIC' | :developer | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'process Composer api request' | :forbidden
'PUBLIC' | :guest | false | true | 'process Composer api request' | :forbidden
'PUBLIC' | :developer | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | true | true | 'process Composer api request' | :created
'PRIVATE' | :guest | true | true | 'process Composer api request' | :forbidden
'PRIVATE' | :developer | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process Composer api request' | :not_found
'PRIVATE' | :guest | false | true | 'process Composer api request' | :not_found
'PRIVATE' | :developer | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process Composer api request' | :unauthorized
end
with_them do it_behaves_like 'composer package publish'
let(:token) { user_token ? personal_access_token.token : 'wrong' } end
let(:headers) { user_role == :anonymous ? {} : build_basic_auth_header(user.username, token) }
before do context 'with a non existing tag' do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false)) let(:params) { { tag: 'non-existing-tag' } }
end let(:headers) { build_basic_auth_header(user.username, personal_access_token.token) }
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] before do
stub_licensed_features(packages: true)
end end
end
it_behaves_like 'rejects Composer access with unknown project id' it_behaves_like 'process Composer api request', :developer, :not_found
end
end end
it_behaves_like 'rejects Composer packages access with packages features disabled' context 'with a branch' do
context 'with an existing branch' do
let(:params) { { branch: 'feature' } }
it_behaves_like 'composer package publish'
end
context 'with a non existing branch' do
let(:params) { { branch: 'non-existing-branch' } }
let(:headers) { build_basic_auth_header(user.username, personal_access_token.token) }
before do
stub_licensed_features(packages: true)
end
it_behaves_like 'process Composer api request', :developer, :not_found
end
end
end end
end end
...@@ -42,7 +42,7 @@ RSpec.shared_examples 'rejects Composer access with unknown project id' do ...@@ -42,7 +42,7 @@ RSpec.shared_examples 'rejects Composer access with unknown project id' do
let(:project) { double(id: non_existing_record_id) } let(:project) { double(id: non_existing_record_id) }
context 'as anonymous' do context 'as anonymous' do
it_behaves_like 'process PyPi api request', :anonymous, :unauthorized it_behaves_like 'process PyPi api request', :anonymous, :not_found
end end
context 'as authenticated user' do context 'as authenticated user' do
......
...@@ -179,6 +179,14 @@ module API ...@@ -179,6 +179,14 @@ module API
end end
end end
def find_tag!(tag_name)
if Gitlab::GitRefValidator.validate(tag_name)
user_project.repository.find_tag(tag_name) || not_found!('Tag')
else
render_api_error!('The tag refname is invalid', 400)
end
end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def find_project_issue(iid, project_id = nil) def find_project_issue(iid, project_id = nil)
project = project_id ? find_project!(project_id) : user_project project = project_id ? find_project!(project_id) : user_project
......
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