1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
# frozen_string_literal: true
# NPM Package Manager Client API
#
# These API endpoints are not consumed directly by users, so there is no documentation for the
# individual endpoints. They are called by the NPM package manager client when users run commands
# like `npm install` or `npm publish`. The usage of the GitLab NPM registry is documented here:
# https://docs.gitlab.com/ee/user/packages/npm_registry/
#
# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
module API
module Concerns
module Packages
module NpmEndpoints
extend ActiveSupport::Concern
included do
helpers ::API::Helpers::Packages::DependencyProxyHelpers
helpers ::API::Helpers::Packages::Npm
rescue_from ActiveRecord::RecordInvalid do |e|
render_structured_api_error!({ message: e.message, error: e.message }, 400)
end
before do
require_packages_enabled!
authenticate_non_get!
end
helpers do
params :package_name do
requires :package_name, type: String, file_path: true, desc: 'Package name',
documentation: { example: 'mypackage' }
end
def redirect_or_present_audit_report
redirect_registry_request(
forward_to_registry: true,
package_type: :npm,
path: options[:path][0],
body: Gitlab::Json.dump(request.POST),
target: project_or_nil,
method: route.request_method
) do
authorize_read_package!(project)
status :ok
present []
end
end
def generate_metadata_service(packages)
::Packages::Npm::GenerateMetadataService.new(params[:package_name], packages)
end
def bad_request_missing_attribute!(attribute)
reason = "\"#{attribute}\" not given"
message = "400 Bad request - #{reason}"
render_structured_api_error!({ message: message, error: reason }, 400)
end
end
params do
requires :package_name, type: String, desc: 'Package name'
end
namespace '-/package/*package_name' do
desc 'Get all tags for a given an NPM package' do
detail 'This feature was introduced in GitLab 12.7'
success [
{ code: 200, model: ::API::Entities::NpmPackageTag }
]
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true,
authenticate_non_public: true
get 'dist-tags', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
package_name = params[:package_name]
bad_request_missing_attribute!('Package Name') if package_name.blank?
authorize_read_package!(project)
packages = ::Packages::Npm::PackageFinder.new(project: project, params: { package_name: package_name })
.execute
not_found!('Package') if packages.empty?
track_package_event(:list_tags, :npm, project: project, namespace: project.namespace)
metadata = generate_metadata_service(packages).execute(only_dist_tags: true).payload
present metadata, with: ::API::Entities::NpmPackageTag
end
params do
requires :tag, type: String, desc: "Package dist-tag"
end
namespace 'dist-tags/:tag', requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
desc 'Create or Update the given tag for the given NPM package and version' do
detail 'This feature was introduced in GitLab 12.7'
success code: 204
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
put format: false do
package_name = params[:package_name]
version = env['api.request.body']
tag = params[:tag]
bad_request_missing_attribute!('Package Name') if package_name.blank?
bad_request_missing_attribute!('Version') if version.blank?
bad_request_missing_attribute!('Tag') if tag.blank?
authorize_create_package!(project)
package = ::Packages::Npm::PackageFinder.new(
project: project, params: { package_name: package_name, package_version: version }
).last
not_found!('Package') unless package
track_package_event(:create_tag, :npm, project: project, namespace: project.namespace)
enqueue_sync_metadata_cache_worker(project, package_name)
::Packages::Npm::CreateTagService.new(package, tag).execute
no_content!
end
desc 'Deletes the given tag' do
detail 'This feature was introduced in GitLab 12.7'
success code: 204
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
delete format: false do
package_name = params[:package_name]
tag = params[:tag]
bad_request_missing_attribute!('Package Name') if package_name.blank?
bad_request_missing_attribute!('Tag') if tag.blank?
authorize_destroy_package!(project)
package_tag = ::Packages::TagsFinder
.new(project, package_name, package_type: :npm)
.find_by_name(tag)
not_found!('Package tag') unless package_tag
track_package_event(:delete_tag, :npm, project: project, namespace: project.namespace)
enqueue_sync_metadata_cache_worker(project, package_name)
::Packages::RemoveTagService.new(package_tag).execute
no_content!
end
end
end
desc 'NPM registry bulk advisory endpoint' do
detail 'This feature was introduced in GitLab 15.6'
success [
{ code: 200, message: 'Ok' },
{ code: 307, message: 'Temporary Redirect' }
]
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
is_array true
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
post '-/npm/v1/security/advisories/bulk' do
redirect_or_present_audit_report
end
desc 'NPM registry quick audit endpoint' do
detail 'This feature was introduced in GitLab 15.6'
success [
{ code: 200, message: 'Ok' },
{ code: 307, message: 'Temporary Redirect' }
]
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' }
]
is_array true
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
post '-/npm/v1/security/audits/quick' do
redirect_or_present_audit_report
end
end
end
end
end
end
|