mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-03 16:04:30 +00:00
294 lines
9.5 KiB
Ruby
294 lines
9.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module API
|
|
class MarkdownUploads < ::API::Base
|
|
include PaginationParams
|
|
|
|
feature_category :team_planning
|
|
|
|
FILENAME_QUERY_PARAM_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(
|
|
filename: API::NO_SLASH_URL_PART_REGEX
|
|
)
|
|
|
|
before { authenticate_non_get! }
|
|
|
|
helpers do
|
|
def find_uploads(parent)
|
|
uploads = Banzai::UploadsFinder.new(parent: parent).execute
|
|
uploads.preload_uploaded_by_user
|
|
end
|
|
|
|
def find_upload(parent, upload_id: nil, secret: nil, filename: nil)
|
|
finder = Banzai::UploadsFinder.new(parent: parent)
|
|
|
|
if upload_id
|
|
finder.find(upload_id)
|
|
else
|
|
finder.find_by_secret_and_filename(secret, filename)
|
|
end
|
|
end
|
|
end
|
|
|
|
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
|
desc 'Workhorse authorize the file upload' do
|
|
detail 'This feature was introduced in GitLab 13.11'
|
|
success code: 200
|
|
failure [
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
post ':id/uploads/authorize' do
|
|
require_gitlab_workhorse!
|
|
|
|
status 200
|
|
content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
|
|
FileUploader.workhorse_authorize(has_length: false, maximum_size: user_project.max_attachment_size)
|
|
end
|
|
|
|
desc 'Upload a file' do
|
|
success code: 201, model: Entities::ProjectUpload
|
|
failure [
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile],
|
|
desc: 'The attachment file to be uploaded', documentation: { type: 'file' }
|
|
end
|
|
post ':id/uploads' do
|
|
upload = UploadService.new(user_project, params[:file], uploaded_by_user_id: current_user&.id).execute
|
|
|
|
present upload, with: Entities::ProjectUpload
|
|
end
|
|
|
|
desc 'Get the list of uploads of a project' do
|
|
success code: 200, model: Entities::MarkdownUploadAdmin
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
is_array true
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
use :pagination
|
|
end
|
|
get ':id/uploads' do
|
|
authorize! :admin_upload, user_project
|
|
|
|
uploads = find_uploads(user_project)
|
|
|
|
present paginate(uploads), with: Entities::MarkdownUploadAdmin
|
|
end
|
|
|
|
desc 'Download a single project upload by ID' do
|
|
success File
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
requires :upload_id, type: Integer, desc: 'The ID of a project upload'
|
|
end
|
|
get ':id/uploads/:upload_id' do
|
|
# Fetching uploads by ID is maintainer-only because it can be used to enumerate uploads
|
|
# even without the secret
|
|
authorize! :admin_upload, user_project
|
|
|
|
upload = find_upload(user_project, upload_id: params[:upload_id])
|
|
|
|
present_carrierwave_file!(upload.retrieve_uploader)
|
|
end
|
|
|
|
desc 'Download a single project upload by secret and filename' do
|
|
success File
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
requires :secret, type: String, desc: 'The 32-character secret of a project upload'
|
|
requires :filename, type: String, file_path: true, desc: 'The filename of a project upload'
|
|
end
|
|
get ':id/uploads/:secret/:filename', requirements: FILENAME_QUERY_PARAM_REQUIREMENTS do
|
|
authorize! :read_upload, user_project
|
|
|
|
upload = find_upload(user_project, secret: params[:secret], filename: params[:filename])
|
|
|
|
present_carrierwave_file!(upload&.retrieve_uploader)
|
|
end
|
|
|
|
desc 'Delete a single project upload by ID' do
|
|
success code: 204
|
|
failure [
|
|
{ code: 400, message: 'Bad request' },
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
requires :upload_id, type: Integer, desc: 'The ID of a project upload'
|
|
end
|
|
delete ':id/uploads/:upload_id' do
|
|
authorize! :destroy_upload, user_project
|
|
|
|
upload = find_upload(user_project, upload_id: params[:upload_id])
|
|
result = Uploads::DestroyService.new(user_project, current_user).execute(upload)
|
|
|
|
if result[:status] == :success
|
|
status 204
|
|
else
|
|
bad_request!(result[:message])
|
|
end
|
|
end
|
|
|
|
desc 'Delete a single project upload by secret and filename' do
|
|
success code: 204
|
|
failure [
|
|
{ code: 400, message: 'Bad request' },
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[projects]
|
|
end
|
|
params do
|
|
requires :secret, type: String, desc: 'The 32-character secret of a project upload'
|
|
requires :filename, type: String, file_path: true, desc: 'The filename of a project upload'
|
|
end
|
|
delete ':id/uploads/:secret/:filename', requirements: FILENAME_QUERY_PARAM_REQUIREMENTS do
|
|
authorize! :destroy_upload, user_project
|
|
|
|
upload = find_upload(user_project, secret: params[:secret], filename: params[:filename])
|
|
result = Uploads::DestroyService.new(user_project, current_user).execute(upload)
|
|
|
|
if result[:status] == :success
|
|
status 204
|
|
else
|
|
bad_request!(result[:message])
|
|
end
|
|
end
|
|
end
|
|
|
|
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
|
desc 'Get the list of uploads of a group' do
|
|
success code: 200, model: Entities::MarkdownUploadAdmin
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
is_array true
|
|
tags %w[groups]
|
|
end
|
|
params do
|
|
use :pagination
|
|
end
|
|
get ':id/uploads' do
|
|
authorize! :admin_upload, user_group
|
|
|
|
uploads = find_uploads(user_group)
|
|
|
|
present paginate(uploads), with: Entities::MarkdownUploadAdmin
|
|
end
|
|
|
|
desc 'Download a single group upload by ID' do
|
|
success File
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[groups]
|
|
end
|
|
params do
|
|
requires :upload_id, type: Integer, desc: 'The ID of a group upload'
|
|
end
|
|
get ':id/uploads/:upload_id' do
|
|
# Fetching uploads by ID is maintainer-only because it can be used to enumerate uploads
|
|
# even without the secret
|
|
authorize! :admin_upload, user_group
|
|
|
|
upload = find_upload(user_group, upload_id: params[:upload_id])
|
|
|
|
present_carrierwave_file!(upload.retrieve_uploader)
|
|
end
|
|
|
|
desc 'Download a single project upload by secret and filename' do
|
|
success File
|
|
failure [
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[groups]
|
|
end
|
|
params do
|
|
requires :secret, type: String, desc: 'The 32-character secret of a group upload'
|
|
requires :filename, type: String, file_path: true, desc: 'The filename of a group upload'
|
|
end
|
|
get ':id/uploads/:secret/:filename', requirements: FILENAME_QUERY_PARAM_REQUIREMENTS do
|
|
authorize! :read_upload, user_group
|
|
|
|
upload = find_upload(user_group, secret: params[:secret], filename: params[:filename])
|
|
|
|
present_carrierwave_file!(upload&.retrieve_uploader)
|
|
end
|
|
|
|
desc 'Delete a single group upload' do
|
|
success code: 204
|
|
failure [
|
|
{ code: 400, message: 'Bad request' },
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[groups]
|
|
end
|
|
params do
|
|
requires :upload_id, type: Integer, desc: 'The ID of a group upload'
|
|
end
|
|
delete ':id/uploads/:upload_id' do
|
|
authorize! :destroy_upload, user_group
|
|
|
|
upload = find_upload(user_group, upload_id: params[:upload_id])
|
|
result = Uploads::DestroyService.new(user_group, current_user).execute(upload)
|
|
|
|
if result[:status] == :success
|
|
status 204
|
|
else
|
|
bad_request!(result[:message])
|
|
end
|
|
end
|
|
|
|
desc 'Delete a single group upload by secret and filename' do
|
|
success code: 204
|
|
failure [
|
|
{ code: 400, message: 'Bad request' },
|
|
{ code: 403, message: 'Unauthenticated' },
|
|
{ code: 404, message: 'Not found' }
|
|
]
|
|
tags %w[groups]
|
|
end
|
|
params do
|
|
requires :secret, type: String, desc: 'The 32-character secret of a group upload'
|
|
requires :filename, type: String, file_path: true, desc: 'The filename of a group upload'
|
|
end
|
|
delete ':id/uploads/:secret/:filename', requirements: FILENAME_QUERY_PARAM_REQUIREMENTS do
|
|
authorize! :destroy_upload, user_group
|
|
|
|
upload = find_upload(user_group, secret: params[:secret], filename: params[:filename])
|
|
result = Uploads::DestroyService.new(user_group, current_user).execute(upload)
|
|
|
|
if result[:status] == :success
|
|
status 204
|
|
else
|
|
bad_request!(result[:message])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|