Commit 505adfc2 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Restrict npm packages feature to scoped packages only

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent fadd54bb
......@@ -8,7 +8,7 @@ project can have its own space to store its NPM packages.
![GitLab NPM Registry](img/npm_package_view.png)
NOTE: **Note:**
Only scoped packages are supported.
Only [scoped](https://docs.npmjs.com/misc/scope) packages are supported.
## Enabling NPM Registry
......@@ -71,11 +71,13 @@ To do this, you need to add next section to the bottom of `package.json`:
```json
"publishConfig": {
"registry":"https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/"
"@foo:registry":"https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/"
}
```
Replace `YOUR_PROJECT_ID` with a project you want your package uploaded to.
And replace `@foo` with your own scope.
Once you added it and have set up the [authorization](#authorizing-with-the-gitlab-npm-registry),
Once you did it and have set up the [authorization](#authorizing-with-the-gitlab-npm-registry),
test to upload an NPM package from a project of yours:
```sh
......
......@@ -16,6 +16,14 @@ module API
def find_project_by_package_name(name)
Project.find_by_full_path(name.sub('@', ''))
end
def project_package_name_match?
"@#{user_project.full_path}" == params[:package_name]
end
def ensure_project_package_match!
bad_request!(:package_name) unless project_package_name_match?
end
end
desc 'NPM registry endpoint at instance level' do
......@@ -24,13 +32,10 @@ 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', requirements: NPM_ENDPOINT_REQUIREMENTS do
package_name = params[:package_name]
# To avoid name collision we require project path and project package be the same.
# For packages that have different name from the project we should use
# the endpoint that includes project id
project = find_project_by_package_name(package_name)
authorize!(:read_package, project)
......@@ -51,6 +56,7 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorize_packages_feature!
ensure_project_package_match!
end
desc 'Download the NPM tarball' do
......@@ -60,7 +66,6 @@ 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_download_package!
......@@ -79,7 +84,6 @@ module API
params do
requires :package_name, type: String, desc: 'Package name'
end
route_setting :authentication, job_token_allowed: true
put ':id/packages/npm/:package_name', requirements: NPM_ENDPOINT_REQUIREMENTS do
authorize_create_package!
......
......@@ -150,22 +150,23 @@ describe API::NpmPackages do
describe 'PUT /api/v4/projects/:id/packages/npm/:package_name' do
context 'when params are correct' do
context 'unscoped package' do
let(:params) { upload_params('foo') }
let(:package_name) { project.path }
let(:params) { upload_params(package_name) }
it 'creates npm package with file' do
expect { upload_package_with_token('foo', params) }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
it 'denies the request with 400 error' do
expect { upload_package_with_token(package_name, params) }
.not_to change { project.packages.count }
expect(response).to have_gitlab_http_status(200)
expect(response).to have_gitlab_http_status(400)
end
end
context 'scoped package' do
let(:params) { upload_params('@foo/bar') }
let(:package_name) { "@#{project.full_path}" }
let(:params) { upload_params(package_name) }
it 'creates npm package with file' do
expect { upload_package_with_token('@bar%2Ffoo', params) }
expect { upload_package_with_token(package_name, params) }
.to change { project.packages.count }.by(1)
.and change { Packages::PackageFile.count }.by(1)
......@@ -175,7 +176,7 @@ describe API::NpmPackages do
end
def upload_package(package_name, params = {})
put api("/projects/#{project.id}/packages/npm/#{package_name}"), params
put api("/projects/#{project.id}/packages/npm/#{package_name.sub('/', '%2f')}"), params
end
def upload_package_with_token(package_name, params = {})
......
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