debian-mirror-gitlab/app/controllers/concerns/uploads_actions.rb

164 lines
4 KiB
Ruby
Raw Normal View History

2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2017-08-17 22:00:37 +05:30
module UploadsActions
2020-01-01 13:55:28 +05:30
extend ActiveSupport::Concern
2018-03-17 18:26:18 +05:30
include Gitlab::Utils::StrongMemoize
2018-05-09 12:01:36 +05:30
include SendFileUpload
2018-03-17 18:26:18 +05:30
2018-11-08 19:23:39 +05:30
UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze
2020-01-01 13:55:28 +05:30
included do
prepend_before_action :set_request_format_from_path_extension
2020-03-07 23:17:34 +05:30
rescue_from FileUploader::InvalidSecret, with: :render_404
2020-01-01 13:55:28 +05:30
end
2017-08-17 22:00:37 +05:30
def create
2019-02-15 15:39:39 +05:30
uploader = UploadService.new(model, params[:file], uploader_class).execute
2017-08-17 22:00:37 +05:30
respond_to do |format|
2019-02-15 15:39:39 +05:30
if uploader
2017-08-17 22:00:37 +05:30
format.json do
2019-02-15 15:39:39 +05:30
render json: { link: uploader.to_h }
2017-08-17 22:00:37 +05:30
end
else
format.json do
2019-07-07 11:18:12 +05:30
render json: _('Invalid file.'), status: :unprocessable_entity
2017-08-17 22:00:37 +05:30
end
end
end
end
2018-03-17 18:26:18 +05:30
# This should either
# - send the file directly
# - or redirect to its URL
#
2017-08-17 22:00:37 +05:30
def show
2018-03-17 18:26:18 +05:30
return render_404 unless uploader&.exists?
2019-12-21 20:55:43 +05:30
# We need to reset caching from the applications controller to get rid of the no-store value
headers['Cache-Control'] = ''
headers['Pragma'] = ''
ttl, directives = *cache_settings
ttl ||= 0
directives ||= { private: true, must_revalidate: true }
expires_in ttl, directives
2018-03-17 18:26:18 +05:30
2020-01-01 13:55:28 +05:30
file_uploader = [uploader, *uploader.versions.values].find do |version|
version.filename == params[:filename]
end
2018-11-08 19:23:39 +05:30
2020-01-01 13:55:28 +05:30
return render_404 unless file_uploader
2018-11-08 19:23:39 +05:30
2019-02-15 15:39:39 +05:30
workhorse_set_content_type!
2020-01-01 13:55:28 +05:30
send_upload(file_uploader, attachment: file_uploader.filename, disposition: content_disposition)
2018-03-17 18:26:18 +05:30
end
2018-11-08 19:23:39 +05:30
def authorize
set_workhorse_internal_api_content_type
authorized = uploader_class.workhorse_authorize(
has_length: false,
maximum_size: Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i)
render json: authorized
2018-11-20 20:47:30 +05:30
rescue SocketError
2019-07-07 11:18:12 +05:30
render json: _("Error uploading file"), status: :internal_server_error
2018-11-08 19:23:39 +05:30
end
2018-03-17 18:26:18 +05:30
private
2017-08-17 22:00:37 +05:30
2020-01-01 13:55:28 +05:30
# Based on ActionDispatch::Http::MimeNegotiation. We have an
# initializer that monkey-patches this method out (so that repository
# paths don't guess a format based on extension), but we do want this
# behavior when serving uploads.
def set_request_format_from_path_extension
path = request.headers['action_dispatch.original_path'] || request.headers['PATH_INFO']
if match = path&.match(/\.(\w+)\z/)
format = Mime[match.captures.first]
request.format = format.symbol if format
end
end
def content_disposition
if uploader.embeddable? || uploader.pdf?
'inline'
else
'attachment'
end
end
2018-03-17 18:26:18 +05:30
def uploader_class
raise NotImplementedError
end
def upload_mount
mounted_as = params[:mounted_as]
mounted_as if UPLOAD_MOUNTS.include?(mounted_as)
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
def uploader_mounted?
upload_model_class < CarrierWave::Mount::Extension && !upload_mount.nil?
end
def uploader
strong_memoize(:uploader) do
if uploader_mounted?
model.public_send(upload_mount) # rubocop:disable GitlabSecurity/PublicSend
else
build_uploader_from_upload || build_uploader_from_params
end
end
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
def build_uploader_from_upload
2018-05-09 12:01:36 +05:30
return unless uploader = build_uploader
2018-03-17 18:26:18 +05:30
2018-05-09 12:01:36 +05:30
upload_paths = uploader.upload_paths(params[:filename])
2019-09-04 21:01:54 +05:30
upload = Upload.find_by(model: model, uploader: uploader_class.to_s, path: upload_paths)
2019-12-21 20:55:43 +05:30
upload&.retrieve_uploader
2018-03-17 18:26:18 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
def build_uploader_from_params
2018-05-09 12:01:36 +05:30
return unless uploader = build_uploader
uploader.retrieve_from_store!(params[:filename])
uploader
end
def build_uploader
return unless params[:secret] && params[:filename]
2018-03-17 18:26:18 +05:30
uploader = uploader_class.new(model, secret: params[:secret])
2018-05-09 12:01:36 +05:30
return unless uploader.model_valid?
2018-03-17 18:26:18 +05:30
uploader
end
2019-12-21 20:55:43 +05:30
def embeddable?
uploader && uploader.exists? && uploader.embeddable?
2018-03-17 18:26:18 +05:30
end
def find_model
nil
end
2017-08-17 22:00:37 +05:30
2019-12-21 20:55:43 +05:30
def cache_settings
[]
2019-03-02 22:35:43 +05:30
end
2018-03-17 18:26:18 +05:30
def model
strong_memoize(:model) { find_model }
2017-08-17 22:00:37 +05:30
end
2019-09-04 21:01:54 +05:30
def workhorse_authorize_request?
action_name == 'authorize'
end
2017-08-17 22:00:37 +05:30
end