# frozen_string_literal: true module API class NpmPackages < ::API::Base helpers ::API::Helpers::PackagesHelpers helpers ::API::Helpers::Packages::DependencyProxyHelpers feature_category :package_registry NPM_ENDPOINT_REQUIREMENTS = { package_name: API::NO_SLASH_URL_PART_REGEX }.freeze rescue_from ActiveRecord::RecordInvalid do |e| render_api_error!(e.message, 400) end before do require_packages_enabled! authenticate_non_get! end helpers do def project_by_package_name strong_memoize(:project_by_package_name) do ::Packages::Package.npm.with_name(params[:package_name]).first&.project end end end desc 'Get all tags for a given an NPM package' do detail 'This feature was introduced in GitLab 12.7' success ::API::Entities::NpmPackageTag end params do requires :package_name, type: String, desc: 'Package name' end get 'packages/npm/-/package/*package_name/dist-tags', format: false, requirements: NPM_ENDPOINT_REQUIREMENTS do package_name = params[:package_name] bad_request!('Package Name') if package_name.blank? authorize_read_package!(project_by_package_name) packages = ::Packages::Npm::PackageFinder.new(project_by_package_name, package_name) .execute present ::Packages::Npm::PackagePresenter.new(package_name, packages), with: ::API::Entities::NpmPackageTag end params do requires :package_name, type: String, desc: 'Package name' requires :tag, type: String, desc: "Package dist-tag" end namespace 'packages/npm/-/package/*package_name/dist-tags/:tag', requirements: 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' end put format: false do package_name = params[:package_name] version = env['api.request.body'] tag = params[:tag] bad_request!('Package Name') if package_name.blank? bad_request!('Version') if version.blank? bad_request!('Tag') if tag.blank? authorize_create_package!(project_by_package_name) package = ::Packages::Npm::PackageFinder .new(project_by_package_name, package_name) .find_by_version(version) not_found!('Package') unless package ::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' end delete format: false do package_name = params[:package_name] tag = params[:tag] bad_request!('Package Name') if package_name.blank? bad_request!('Tag') if tag.blank? authorize_destroy_package!(project_by_package_name) package_tag = ::Packages::TagsFinder .new(project_by_package_name, package_name, package_type: :npm) .find_by_name(tag) not_found!('Package tag') unless package_tag ::Packages::RemoveTagService.new(package_tag).execute no_content! end end desc 'NPM registry endpoint at instance level' do detail 'This feature was introduced in GitLab 11.8' end params do requires :package_name, type: String, desc: 'Package name' end route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true get 'packages/npm/*package_name', format: false, requirements: NPM_ENDPOINT_REQUIREMENTS do package_name = params[:package_name] redirect_registry_request(project_by_package_name.blank?, :npm, package_name: package_name) do authorize_read_package!(project_by_package_name) packages = ::Packages::Npm::PackageFinder .new(project_by_package_name, package_name).execute present ::Packages::Npm::PackagePresenter.new(package_name, packages), with: ::API::Entities::NpmPackage end end params do requires :id, type: String, desc: 'The ID of a project' end resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do desc 'Download the NPM tarball' do detail 'This feature was introduced in GitLab 11.8' end params do 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, deploy_token_allowed: true get ':id/packages/npm/*package_name/-/*file_name', format: false do authorize_read_package!(user_project) package = user_project.packages.npm .by_name_and_file_name(params[:package_name], params[:file_name]) package_file = ::Packages::PackageFileFinder .new(package, params[:file_name]).execute! track_package_event('pull_package', package) present_carrierwave_file!(package_file.file) end desc 'Create NPM package' do detail 'This feature was introduced in GitLab 11.8' end params do requires :package_name, type: String, desc: 'Package name' requires :versions, type: Hash, desc: 'Package version info' end route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true put ':id/packages/npm/:package_name', requirements: NPM_ENDPOINT_REQUIREMENTS do authorize_create_package!(user_project) track_package_event('push_package', :npm) created_package = ::Packages::Npm::CreatePackageService .new(user_project, current_user, params.merge(build: current_authenticated_job)).execute if created_package[:status] == :error render_api_error!(created_package[:message], created_package[:http_status]) else created_package end end end end end