Commit a400e4bd authored by Steve Abrams's avatar Steve Abrams Committed by Bob Van Landuyt

Allow NPM package downloads with CI_JOB_TOKEN

Allow job tokens to be used for npm download endpoints
Add test coverage for npm uploads with job tokens
parent 63534f6e
---
title: Allow NPM package downloads with CI_JOB_TOKEN
merge_request: 20868
author:
type: added
......@@ -28,6 +28,7 @@ module API
params do
requires :package_name, type: String, desc: 'Package name'
end
route_setting :authentication, job_token_allowed: true
get 'packages/npm/*package_name', format: false, requirements: NPM_ENDPOINT_REQUIREMENTS do
package_name = params[:package_name]
......@@ -58,6 +59,7 @@ module API
requires :package_name, type: String, desc: 'Package name'
requires :file_name, type: String, desc: 'Package file name'
end
route_setting :authentication, job_token_allowed: true
get ':id/packages/npm/*package_name/-/*file_name', format: false do
authorize_read_package!(user_project)
......
# frozen_string_literal: true
require 'spec_helper'
describe API::NpmPackages do
......@@ -6,6 +7,7 @@ describe API::NpmPackages do
let(:user) { create(:user) }
let(:project) { create(:project, :public, namespace: group) }
let(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
let(:job) { create(:ci_build, user: user) }
before do
project.add_developer(user)
......@@ -19,6 +21,12 @@ describe API::NpmPackages do
expect_a_valid_package_response
end
it 'returns the package info with job token' do
get_package_with_job_token(package)
expect_a_valid_package_response
end
it 'denies request without oauth token' do
get_package(package)
......@@ -87,32 +95,53 @@ describe API::NpmPackages do
def get_package_with_token(package, params = {})
get_package(package, params.merge(access_token: token.token))
end
def get_package_with_job_token(package, params = {})
get_package(package, params.merge(job_token: job.token))
end
end
describe 'GET /api/v4/projects/:id/packages/npm/*package_name/-/*file_name' do
let(:package) { create(:npm_package, project: project) }
let(:package_file) { package.package_files.first }
context 'a public project' do
it 'returns the file' do
shared_examples 'a package file that requires auth' do
it 'returns the file with an access token' do
get_file_with_token(package_file)
expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream')
end
it 'returns the file with a job token' do
get_file_with_job_token(package_file)
expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream')
end
context 'private project' do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
it 'denies download with no token' do
get_file(package_file)
expect(response).to have_gitlab_http_status(404)
end
end
it 'returns the file' do
get_file_with_token(package_file)
context 'a public project' do
it 'returns the file with no token needed' do
get_file(package_file)
expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream')
end
end
context 'private project' do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it_behaves_like 'a package file that requires auth'
it 'denies download when not enough permissions' do
project.add_guest(user)
......@@ -121,12 +150,14 @@ describe API::NpmPackages do
expect(response).to have_gitlab_http_status(403)
end
end
it 'denies download when no private token' do
get_file(package_file)
expect(response).to have_gitlab_http_status(404)
context 'internal project' do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
it_behaves_like 'a package file that requires auth'
end
it 'rejects request if feature is not in the license' do
......@@ -145,6 +176,10 @@ describe API::NpmPackages do
def get_file_with_token(package_file, params = {})
get_file(package_file, params.merge(access_token: token.token))
end
def get_file_with_job_token(package_file, params = {})
get_file(package_file, params.merge(job_token: job.token))
end
end
describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
......@@ -179,13 +214,21 @@ describe API::NpmPackages do
let(:package_name) { "@#{group.path}/my_package_name" }
let(:params) { upload_params(package_name) }
it 'creates npm package with file' do
it 'creates npm package with file with access token' do
expect { upload_package_with_token(package_name, params) }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
expect(response).to have_gitlab_http_status(200)
end
it 'creates npm package with file with job token' do
expect { upload_package_with_job_token(package_name, params) }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
expect(response).to have_gitlab_http_status(200)
end
end
context 'package creation fails' do
......@@ -210,6 +253,10 @@ describe API::NpmPackages do
upload_package(package_name, params.merge(access_token: token.token))
end
def upload_package_with_job_token(package_name, params = {})
upload_package(package_name, params.merge(job_token: job.token))
end
def upload_params(package_name)
JSON.parse(
fixture_file('npm/payload.json', dir: 'ee')
......
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