diff options
Diffstat (limited to 'lib/api')
-rw-r--r-- | lib/api/api.rb | 8 | ||||
-rw-r--r-- | lib/api/helpers.rb | 22 | ||||
-rw-r--r-- | lib/api/helpers/projects_helpers.rb | 38 | ||||
-rw-r--r-- | lib/api/project_import.rb | 12 | ||||
-rw-r--r-- | lib/api/projects.rb | 34 | ||||
-rw-r--r-- | lib/api/runner.rb | 36 |
6 files changed, 86 insertions, 64 deletions
diff --git a/lib/api/api.rb b/lib/api/api.rb index 62ffebeacb0..073471b4c4d 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -78,6 +78,14 @@ module API rack_response({ 'message' => '404 Not found' }.to_json, 404) end + rescue_from UploadedFile::InvalidPathError do |e| + rack_response({ 'message' => e.message }.to_json, 400) + end + + rescue_from ObjectStorage::RemoteStoreError do |e| + rack_response({ 'message' => e.message }.to_json, 500) + end + # Retain 405 error rather than a 500 error for Grape 0.15.0+. # https://github.com/ruby-grape/grape/blob/a3a28f5b5dfbb2797442e006dbffd750b27f2a76/UPGRADING.md#changes-to-method-not-allowed-routes rescue_from Grape::Exceptions::MethodNotAllowed do |e| diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 61c138a7dec..a582aa0ec2c 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -389,28 +389,6 @@ module API # file helpers - def uploaded_file(field, uploads_path) - if params[field] - bad_request!("#{field} is not a file") unless params[field][:filename] - return params[field] - end - - return nil unless params["#{field}.path"] && params["#{field}.name"] - - # sanitize file paths - # this requires all paths to exist - required_attributes! %W(#{field}.path) - uploads_path = File.realpath(uploads_path) - file_path = File.realpath(params["#{field}.path"]) - bad_request!('Bad file path') unless file_path.start_with?(uploads_path) - - UploadedFile.new( - file_path, - params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream' - ) - end - def present_disk_file!(path, filename, content_type = 'application/octet-stream') filename ||= File.basename(path) header['Content-Disposition'] = "attachment; filename=#{filename}" diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb new file mode 100644 index 00000000000..381d5e8968c --- /dev/null +++ b/lib/api/helpers/projects_helpers.rb @@ -0,0 +1,38 @@ +module API + module Helpers + module ProjectsHelpers + extend ActiveSupport::Concern + + included do + helpers do + params :optional_project_params_ce do + optional :description, type: String, desc: 'The description of the project' + optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' + optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled' + optional :merge_requests_enabled, type: Boolean, desc: 'Flag indication if merge requests are enabled' + optional :wiki_enabled, type: Boolean, desc: 'Flag indication if the wiki is enabled' + optional :jobs_enabled, type: Boolean, desc: 'Flag indication if jobs are enabled' + optional :snippets_enabled, type: Boolean, desc: 'Flag indication if snippets are enabled' + optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project' + optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diffs discussions on lines changed with a push' + optional :container_registry_enabled, type: Boolean, desc: 'Flag indication if the container registry is enabled for that project' + optional :lfs_enabled, type: Boolean, desc: 'Flag indication if Git LFS is enabled for that project' + optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the project.' + optional :public_builds, type: Boolean, desc: 'Perform public builds' + optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access' + optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed' + optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved' + optional :tag_list, type: Array[String], desc: 'The list of tags for a project' + optional :avatar, type: File, desc: 'Avatar image for project' + optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line' + optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests' + end + + params :optional_project_params do + use :optional_project_params_ce + end + end + end + end + end +end diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb index a509c1f32c1..303b58a5942 100644 --- a/lib/api/project_import.rb +++ b/lib/api/project_import.rb @@ -1,6 +1,7 @@ module API class ProjectImport < Grape::API include PaginationParams + include Helpers::ProjectsHelpers helpers do def import_params @@ -25,6 +26,11 @@ module API requires :path, type: String, desc: 'The new project path and name' requires :file, type: File, desc: 'The project export file to be imported' optional :namespace, type: String, desc: "The ID or name of the namespace that the project will be imported into. Defaults to the current user's namespace." + optional :override_params, + type: Hash, + desc: 'New project params to override values in the export' do + use :optional_project_params + end end desc 'Create a new project import' do detail 'This feature was introduced in GitLab 10.6.' @@ -47,7 +53,11 @@ module API file: import_params[:file]['tempfile'] } - project = ::Projects::GitlabProjectsImportService.new(current_user, project_params).execute + override_params = import_params.delete(:override_params) + + project = ::Projects::GitlabProjectsImportService.new( + current_user, project_params, override_params + ).execute render_api_error!(project.errors.full_messages&.first, 400) unless project.saved? diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 3d5b3c5a535..d0a4a23e074 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -4,37 +4,11 @@ module API class Projects < Grape::API include PaginationParams include Helpers::CustomAttributes + include Helpers::ProjectsHelpers before { authenticate_non_get! } helpers do - params :optional_params_ce do - optional :description, type: String, desc: 'The description of the project' - optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' - optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled' - optional :merge_requests_enabled, type: Boolean, desc: 'Flag indication if merge requests are enabled' - optional :wiki_enabled, type: Boolean, desc: 'Flag indication if the wiki is enabled' - optional :jobs_enabled, type: Boolean, desc: 'Flag indication if jobs are enabled' - optional :snippets_enabled, type: Boolean, desc: 'Flag indication if snippets are enabled' - optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project' - optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diffs discussions on lines changed with a push' - optional :container_registry_enabled, type: Boolean, desc: 'Flag indication if the container registry is enabled for that project' - optional :lfs_enabled, type: Boolean, desc: 'Flag indication if Git LFS is enabled for that project' - optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the project.' - optional :public_builds, type: Boolean, desc: 'Perform public builds' - optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access' - optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed' - optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved' - optional :tag_list, type: Array[String], desc: 'The list of tags for a project' - optional :avatar, type: File, desc: 'Avatar image for project' - optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line' - optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests' - end - - params :optional_params do - use :optional_params_ce - end - params :statistics_params do optional :statistics, type: Boolean, default: false, desc: 'Include project statistics' end @@ -144,7 +118,7 @@ module API optional :name, type: String, desc: 'The name of the project' optional :path, type: String, desc: 'The path of the repository' at_least_one_of :name, :path - use :optional_params + use :optional_project_params use :create_params end post do @@ -172,7 +146,7 @@ module API requires :user_id, type: Integer, desc: 'The ID of a user' optional :path, type: String, desc: 'The path of the repository' optional :default_branch, type: String, desc: 'The default branch of the project' - use :optional_params + use :optional_project_params use :create_params end post "user/:user_id" do @@ -293,7 +267,7 @@ module API optional :default_branch, type: String, desc: 'The default branch of the project' optional :path, type: String, desc: 'The path of the repository' - use :optional_params + use :optional_project_params at_least_one_of(*at_least_one_of_ce) end put ':id' do diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 834253d8e94..60aeb69e10a 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -186,7 +186,7 @@ module API status 200 content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE - Gitlab::Workhorse.artifact_upload_ok + JobArtifactUploader.workhorse_authorize end desc 'Upload artifacts for job' do @@ -201,14 +201,15 @@ module API requires :id, type: Integer, desc: %q(Job's ID) optional :token, type: String, desc: %q(Job's authentication token) optional :expire_in, type: String, desc: %q(Specify when artifacts should expire) - optional :file, type: File, desc: %q(Artifact's file) optional 'file.path', type: String, desc: %q(path to locally stored body (generated by Workhorse)) optional 'file.name', type: String, desc: %q(real filename as send in Content-Disposition (generated by Workhorse)) optional 'file.type', type: String, desc: %q(real content type as send in Content-Type (generated by Workhorse)) - optional 'file.sha256', type: String, desc: %q(sha256 checksum of the file) + optional 'file.size', type: Integer, desc: %q(real size of file (generated by Workhorse)) + optional 'file.sha256', type: String, desc: %q(sha256 checksum of the file (generated by Workhorse)) optional 'metadata.path', type: String, desc: %q(path to locally stored body (generated by Workhorse)) optional 'metadata.name', type: String, desc: %q(filename (generated by Workhorse)) - optional 'metadata.sha256', type: String, desc: %q(sha256 checksum of the file) + optional 'metadata.size', type: Integer, desc: %q(real size of metadata (generated by Workhorse)) + optional 'metadata.sha256', type: String, desc: %q(sha256 checksum of metadata (generated by Workhorse)) end post '/:id/artifacts' do not_allowed! unless Gitlab.config.artifacts.enabled @@ -217,21 +218,34 @@ module API job = authenticate_job! forbidden!('Job is not running!') unless job.running? - workhorse_upload_path = JobArtifactUploader.workhorse_upload_path - artifacts = uploaded_file(:file, workhorse_upload_path) - metadata = uploaded_file(:metadata, workhorse_upload_path) + artifacts = UploadedFile.from_params(params, :file, JobArtifactUploader.workhorse_local_upload_path) + metadata = UploadedFile.from_params(params, :metadata, JobArtifactUploader.workhorse_local_upload_path) bad_request!('Missing artifacts file!') unless artifacts file_to_large! unless artifacts.size < max_artifacts_size + bad_request!("Already uploaded") if job.job_artifacts_archive + expire_in = params['expire_in'] || Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in - job.build_job_artifacts_archive(project: job.project, file_type: :archive, file: artifacts, file_sha256: params['file.sha256'], expire_in: expire_in) - job.build_job_artifacts_metadata(project: job.project, file_type: :metadata, file: metadata, file_sha256: params['metadata.sha256'], expire_in: expire_in) if metadata - job.artifacts_expire_in = expire_in + job.build_job_artifacts_archive( + project: job.project, + file: artifacts, + file_type: :archive, + file_sha256: artifacts.sha256, + expire_in: expire_in) + + if metadata + job.build_job_artifacts_metadata( + project: job.project, + file: metadata, + file_type: :metadata, + file_sha256: metadata.sha256, + expire_in: expire_in) + end - if job.save + if job.update(artifacts_expire_in: expire_in) present job, with: Entities::JobRequest::Response else render_validation_error!(job) |