debian-mirror-gitlab/app/services/projects/lfs_pointers/lfs_download_service.rb

85 lines
2.7 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2018-11-08 19:23:39 +05:30
# This service downloads and links lfs objects from a remote URL
module Projects
module LfsPointers
class LfsDownloadService < BaseService
2018-12-15 14:41:45 +05:30
VALID_PROTOCOLS = %w[http https].freeze
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2018-11-08 19:23:39 +05:30
def execute(oid, url)
return unless project&.lfs_enabled? && oid.present? && url.present?
return if LfsObject.exists?(oid: oid)
2019-01-03 12:48:30 +05:30
sanitized_uri = sanitize_url!(url)
2018-11-08 19:23:39 +05:30
with_tmp_file(oid) do |file|
2019-01-03 12:48:30 +05:30
download_and_save_file(file, sanitized_uri)
lfs_object = LfsObject.new(oid: oid, size: file.size, file: file)
2018-11-08 19:23:39 +05:30
project.all_lfs_objects << lfs_object
end
2019-01-03 12:48:30 +05:30
rescue Gitlab::UrlBlocker::BlockedUrlError => e
Rails.logger.error("LFS file with oid #{oid} couldn't be downloaded: #{e.message}")
2018-11-08 19:23:39 +05:30
rescue StandardError => e
2019-01-03 12:48:30 +05:30
Rails.logger.error("LFS file with oid #{oid} couldn't be downloaded from #{sanitized_uri.sanitized_url}: #{e.message}")
2018-11-08 19:23:39 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-11-08 19:23:39 +05:30
private
2019-01-03 12:48:30 +05:30
def sanitize_url!(url)
Gitlab::UrlSanitizer.new(url).tap do |sanitized_uri|
# Just validate that HTTP/HTTPS protocols are used. The
# subsequent Gitlab::HTTP.get call will do network checks
# based on the settings.
Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url,
protocols: VALID_PROTOCOLS)
end
end
2018-11-08 19:23:39 +05:30
def download_and_save_file(file, sanitized_uri)
2019-01-03 12:48:30 +05:30
response = Gitlab::HTTP.get(sanitized_uri.sanitized_url, headers(sanitized_uri)) do |fragment|
file.write(fragment)
end
raise StandardError, "Received error code #{response.code}" unless response.success?
2018-11-08 19:23:39 +05:30
end
def headers(sanitized_uri)
2019-01-03 12:48:30 +05:30
query_options.tap do |headers|
2018-11-08 19:23:39 +05:30
credentials = sanitized_uri.credentials
if credentials[:user].present? || credentials[:password].present?
# Using authentication headers in the request
headers[:http_basic_authentication] = [credentials[:user], credentials[:password]]
end
end
end
2019-01-03 12:48:30 +05:30
def query_options
{ stream_body: true }
end
2018-11-08 19:23:39 +05:30
def with_tmp_file(oid)
create_tmp_storage_dir
2019-01-03 12:48:30 +05:30
File.open(File.join(tmp_storage_dir, oid), 'wb') { |file| yield file }
2018-11-08 19:23:39 +05:30
end
def create_tmp_storage_dir
FileUtils.makedirs(tmp_storage_dir) unless Dir.exist?(tmp_storage_dir)
end
def tmp_storage_dir
@tmp_storage_dir ||= File.join(storage_dir, 'tmp', 'download')
end
def storage_dir
@storage_dir ||= Gitlab.config.lfs.storage_path
end
end
end
end