aboutsummaryrefslogtreecommitdiffstats
path: root/activestorage/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activestorage/lib')
-rw-r--r--activestorage/lib/active_storage.rb5
-rw-r--r--activestorage/lib/active_storage/analyzer.rb4
-rw-r--r--activestorage/lib/active_storage/analyzer/image_analyzer.rb15
-rw-r--r--activestorage/lib/active_storage/analyzer/video_analyzer.rb2
-rw-r--r--activestorage/lib/active_storage/attached/changes/create_one.rb1
-rw-r--r--activestorage/lib/active_storage/downloader.rb29
-rw-r--r--activestorage/lib/active_storage/engine.rb24
-rw-r--r--activestorage/lib/active_storage/gem_version.rb2
-rw-r--r--activestorage/lib/active_storage/previewer.rb8
-rw-r--r--activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb2
-rw-r--r--activestorage/lib/active_storage/service.rb4
-rw-r--r--activestorage/lib/active_storage/service/azure_storage_service.rb14
-rw-r--r--activestorage/lib/active_storage/service/disk_service.rb28
-rw-r--r--activestorage/lib/active_storage/service/gcs_service.rb52
-rw-r--r--activestorage/lib/active_storage/service/mirror_service.rb2
-rw-r--r--activestorage/lib/active_storage/service/s3_service.rb28
-rw-r--r--activestorage/lib/active_storage/transformers/image_processing_transformer.rb2
-rw-r--r--activestorage/lib/tasks/activestorage.rake7
18 files changed, 123 insertions, 106 deletions
diff --git a/activestorage/lib/active_storage.rb b/activestorage/lib/active_storage.rb
index 19c7f6be2a..5c5da551ae 100644
--- a/activestorage/lib/active_storage.rb
+++ b/activestorage/lib/active_storage.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#--
-# Copyright (c) 2017-2018 David Heinemeier Hansson, Basecamp
+# Copyright (c) 2017-2019 David Heinemeier Hansson, Basecamp
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -26,6 +26,7 @@
require "active_record"
require "active_support"
require "active_support/rails"
+require "active_support/core_ext/numeric/time"
require "active_storage/version"
require "active_storage/errors"
@@ -42,7 +43,7 @@ module ActiveStorage
mattr_accessor :logger
mattr_accessor :verifier
- mattr_accessor :queue
+ mattr_accessor :queues, default: {}
mattr_accessor :previewers, default: []
mattr_accessor :analyzers, default: []
mattr_accessor :variant_processor, default: :mini_magick
diff --git a/activestorage/lib/active_storage/analyzer.rb b/activestorage/lib/active_storage/analyzer.rb
index caa25418a5..26414ffbc2 100644
--- a/activestorage/lib/active_storage/analyzer.rb
+++ b/activestorage/lib/active_storage/analyzer.rb
@@ -24,14 +24,14 @@ module ActiveStorage
private
# Downloads the blob to a tempfile on disk. Yields the tempfile.
def download_blob_to_tempfile(&block) #:doc:
- blob.open tempdir: tempdir, &block
+ blob.open tmpdir: tmpdir, &block
end
def logger #:doc:
ActiveStorage.logger
end
- def tempdir #:doc:
+ def tmpdir #:doc:
Dir.tmpdir
end
end
diff --git a/activestorage/lib/active_storage/analyzer/image_analyzer.rb b/activestorage/lib/active_storage/analyzer/image_analyzer.rb
index 3b39de91be..c8bc8fe953 100644
--- a/activestorage/lib/active_storage/analyzer/image_analyzer.rb
+++ b/activestorage/lib/active_storage/analyzer/image_analyzer.rb
@@ -25,17 +25,24 @@ module ActiveStorage
{ width: image.width, height: image.height }
end
end
- rescue LoadError
- logger.info "Skipping image analysis because the mini_magick gem isn't installed"
- {}
end
private
def read_image
download_blob_to_tempfile do |file|
require "mini_magick"
- yield MiniMagick::Image.new(file.path)
+ image = MiniMagick::Image.new(file.path)
+
+ if image.valid?
+ yield image
+ else
+ logger.info "Skipping image analysis because ImageMagick doesn't support the file"
+ {}
+ end
end
+ rescue LoadError
+ logger.info "Skipping image analysis because the mini_magick gem isn't installed"
+ {}
end
def rotated_image?(image)
diff --git a/activestorage/lib/active_storage/analyzer/video_analyzer.rb b/activestorage/lib/active_storage/analyzer/video_analyzer.rb
index 18d8ff8237..e56c97f4f5 100644
--- a/activestorage/lib/active_storage/analyzer/video_analyzer.rb
+++ b/activestorage/lib/active_storage/analyzer/video_analyzer.rb
@@ -11,7 +11,7 @@ module ActiveStorage
#
# Example:
#
- # ActiveStorage::VideoAnalyzer.new(blob).metadata
+ # ActiveStorage::Analyzer::VideoAnalyzer.new(blob).metadata
# # => { width: 640.0, height: 480.0, duration: 5.0, angle: 0, display_aspect_ratio: [4, 3] }
#
# When a video's angle is 90 or 270 degrees, its width and height are automatically swapped for convenience.
diff --git a/activestorage/lib/active_storage/attached/changes/create_one.rb b/activestorage/lib/active_storage/attached/changes/create_one.rb
index 5812fd2b08..89cccfb58a 100644
--- a/activestorage/lib/active_storage/attached/changes/create_one.rb
+++ b/activestorage/lib/active_storage/attached/changes/create_one.rb
@@ -30,6 +30,7 @@ module ActiveStorage
def save
record.public_send("#{name}_attachment=", attachment)
+ record.public_send("#{name}_blob=", blob)
end
private
diff --git a/activestorage/lib/active_storage/downloader.rb b/activestorage/lib/active_storage/downloader.rb
index 87be6efb05..4d7e832af5 100644
--- a/activestorage/lib/active_storage/downloader.rb
+++ b/activestorage/lib/active_storage/downloader.rb
@@ -2,24 +2,23 @@
module ActiveStorage
class Downloader #:nodoc:
- def initialize(blob, tempdir: nil)
- @blob = blob
- @tempdir = tempdir
+ attr_reader :service
+
+ def initialize(service)
+ @service = service
end
- def download_blob_to_tempfile
- open_tempfile do |file|
- download_blob_to file
- verify_integrity_of file
+ def open(key, checksum:, name: "ActiveStorage-", tmpdir: nil)
+ open_tempfile(name, tmpdir) do |file|
+ download key, file
+ verify_integrity_of file, checksum: checksum
yield file
end
end
private
- attr_reader :blob, :tempdir
-
- def open_tempfile
- file = Tempfile.open([ "ActiveStorage-#{blob.id}-", blob.filename.extension_with_delimiter ], tempdir)
+ def open_tempfile(name, tmpdir = nil)
+ file = Tempfile.open(name, tmpdir)
begin
yield file
@@ -28,15 +27,15 @@ module ActiveStorage
end
end
- def download_blob_to(file)
+ def download(key, file)
file.binmode
- blob.download { |chunk| file.write(chunk) }
+ service.download(key) { |chunk| file.write(chunk) }
file.flush
file.rewind
end
- def verify_integrity_of(file)
- unless Digest::MD5.file(file).base64digest == blob.checksum
+ def verify_integrity_of(file, checksum:)
+ unless Digest::MD5.file(file).base64digest == checksum
raise ActiveStorage::IntegrityError
end
end
diff --git a/activestorage/lib/active_storage/engine.rb b/activestorage/lib/active_storage/engine.rb
index b3bcf48d6f..cbb205627e 100644
--- a/activestorage/lib/active_storage/engine.rb
+++ b/activestorage/lib/active_storage/engine.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
require "rails"
+require "action_controller/railtie"
+require "active_job/railtie"
+require "active_record/railtie"
+
require "active_storage"
require "active_storage/previewer/poppler_pdf_previewer"
@@ -20,6 +24,7 @@ module ActiveStorage
config.active_storage.previewers = [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer, ActiveStorage::Analyzer::VideoAnalyzer ]
config.active_storage.paths = ActiveSupport::OrderedOptions.new
+ config.active_storage.queues = ActiveSupport::OrderedOptions.new
config.active_storage.variable_content_types = %w(
image/png
@@ -27,6 +32,8 @@ module ActiveStorage
image/jpg
image/jpeg
image/pjpeg
+ image/tiff
+ image/bmp
image/vnd.adobe.photoshop
image/vnd.microsoft.icon
)
@@ -49,6 +56,8 @@ module ActiveStorage
image/gif
image/jpg
image/jpeg
+ image/tiff
+ image/bmp
image/vnd.adobe.photoshop
image/vnd.microsoft.icon
application/pdf
@@ -59,7 +68,6 @@ module ActiveStorage
initializer "active_storage.configs" do
config.after_initialize do |app|
ActiveStorage.logger = app.config.active_storage.logger || Rails.logger
- ActiveStorage.queue = app.config.active_storage.queue
ActiveStorage.variant_processor = app.config.active_storage.variant_processor || :mini_magick
ActiveStorage.previewers = app.config.active_storage.previewers || []
ActiveStorage.analyzers = app.config.active_storage.analyzers || []
@@ -115,6 +123,20 @@ module ActiveStorage
end
end
+ initializer "active_storage.queues" do
+ config.after_initialize do |app|
+ if queue = app.config.active_storage.queue
+ ActiveSupport::Deprecation.warn \
+ "config.active_storage.queue is deprecated and will be removed in Rails 6.1. " \
+ "Set config.active_storage.queues.purge and config.active_storage.queues.analysis instead."
+
+ ActiveStorage.queues = { purge: queue, analysis: queue }
+ else
+ ActiveStorage.queues = app.config.active_storage.queues || {}
+ end
+ end
+ end
+
initializer "active_storage.reflection" do
ActiveSupport.on_load(:active_record) do
include Reflection::ActiveRecordExtensions
diff --git a/activestorage/lib/active_storage/gem_version.rb b/activestorage/lib/active_storage/gem_version.rb
index 492620731b..5ef5d09f28 100644
--- a/activestorage/lib/active_storage/gem_version.rb
+++ b/activestorage/lib/active_storage/gem_version.rb
@@ -8,7 +8,7 @@ module ActiveStorage
module VERSION
MAJOR = 6
- MINOR = 0
+ MINOR = 1
TINY = 0
PRE = "alpha"
diff --git a/activestorage/lib/active_storage/previewer.rb b/activestorage/lib/active_storage/previewer.rb
index 95a041fd16..af6bcadd4c 100644
--- a/activestorage/lib/active_storage/previewer.rb
+++ b/activestorage/lib/active_storage/previewer.rb
@@ -26,7 +26,7 @@ module ActiveStorage
private
# Downloads the blob to a tempfile on disk. Yields the tempfile.
def download_blob_to_tempfile(&block) #:doc:
- blob.open tempdir: tempdir, &block
+ blob.open tmpdir: tmpdir, &block
end
# Executes a system command, capturing its binary output in a tempfile. Yields the tempfile.
@@ -42,7 +42,7 @@ module ActiveStorage
# end
# end
#
- # The output tempfile is opened in the directory returned by #tempdir.
+ # The output tempfile is opened in the directory returned by #tmpdir.
def draw(*argv) #:doc:
open_tempfile do |file|
instrument :preview, key: blob.key do
@@ -54,7 +54,7 @@ module ActiveStorage
end
def open_tempfile
- tempfile = Tempfile.open("ActiveStorage-", tempdir)
+ tempfile = Tempfile.open("ActiveStorage-", tmpdir)
begin
yield tempfile
@@ -77,7 +77,7 @@ module ActiveStorage
ActiveStorage.logger
end
- def tempdir #:doc:
+ def tmpdir #:doc:
Dir.tmpdir
end
end
diff --git a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb
index 69eb617d7b..6bf501a607 100644
--- a/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb
+++ b/activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb
@@ -28,7 +28,7 @@ module ActiveStorage
private
def draw_first_page_from(file, &block)
- # use 72 dpi to match thumbnail dimesions of the PDF
+ # use 72 dpi to match thumbnail dimensions of the PDF
draw self.class.pdftoppm_path, "-singlefile", "-r", "72", "-png", file.path, &block
end
end
diff --git a/activestorage/lib/active_storage/service.rb b/activestorage/lib/active_storage/service.rb
index c18fccbb1d..aac1e62e7f 100644
--- a/activestorage/lib/active_storage/service.rb
+++ b/activestorage/lib/active_storage/service.rb
@@ -82,6 +82,10 @@ module ActiveStorage
raise NotImplementedError
end
+ def open(*args, &block)
+ ActiveStorage::Downloader.new(self).open(*args, &block)
+ end
+
# Delete the file at the +key+.
def delete(key)
raise NotImplementedError
diff --git a/activestorage/lib/active_storage/service/azure_storage_service.rb b/activestorage/lib/active_storage/service/azure_storage_service.rb
index a2c4b4d57c..993cc0e5f7 100644
--- a/activestorage/lib/active_storage/service/azure_storage_service.rb
+++ b/activestorage/lib/active_storage/service/azure_storage_service.rb
@@ -10,8 +10,8 @@ module ActiveStorage
class Service::AzureStorageService < Service
attr_reader :client, :blobs, :container, :signer
- def initialize(storage_account_name:, storage_access_key:, container:)
- @client = Azure::Storage::Client.create(storage_account_name: storage_account_name, storage_access_key: storage_access_key)
+ def initialize(storage_account_name:, storage_access_key:, container:, **options)
+ @client = Azure::Storage::Client.create(storage_account_name: storage_account_name, storage_access_key: storage_access_key, **options)
@signer = Azure::Storage::Core::Auth::SharedAccessSignature.new(storage_account_name, storage_access_key)
@blobs = client.blob_client
@container = container
@@ -51,12 +51,10 @@ module ActiveStorage
def delete(key)
instrument :delete, key: key do
- begin
- blobs.delete_blob(container, key)
- rescue Azure::Core::Http::HTTPError => e
- raise unless e.type == "BlobNotFound"
- # Ignore files already deleted
- end
+ blobs.delete_blob(container, key)
+ rescue Azure::Core::Http::HTTPError => e
+ raise unless e.type == "BlobNotFound"
+ # Ignore files already deleted
end
end
diff --git a/activestorage/lib/active_storage/service/disk_service.rb b/activestorage/lib/active_storage/service/disk_service.rb
index 2588c41760..67892d43b2 100644
--- a/activestorage/lib/active_storage/service/disk_service.rb
+++ b/activestorage/lib/active_storage/service/disk_service.rb
@@ -29,35 +29,29 @@ module ActiveStorage
end
else
instrument :download, key: key do
- begin
- File.binread path_for(key)
- rescue Errno::ENOENT
- raise ActiveStorage::FileNotFoundError
- end
+ File.binread path_for(key)
+ rescue Errno::ENOENT
+ raise ActiveStorage::FileNotFoundError
end
end
end
def download_chunk(key, range)
instrument :download_chunk, key: key, range: range do
- begin
- File.open(path_for(key), "rb") do |file|
- file.seek range.begin
- file.read range.size
- end
- rescue Errno::ENOENT
- raise ActiveStorage::FileNotFoundError
+ File.open(path_for(key), "rb") do |file|
+ file.seek range.begin
+ file.read range.size
end
+ rescue Errno::ENOENT
+ raise ActiveStorage::FileNotFoundError
end
end
def delete(key)
instrument :delete, key: key do
- begin
- File.delete path_for(key)
- rescue Errno::ENOENT
- # Ignore files already deleted
- end
+ File.delete path_for(key)
+ rescue Errno::ENOENT
+ # Ignore files already deleted
end
end
diff --git a/activestorage/lib/active_storage/service/gcs_service.rb b/activestorage/lib/active_storage/service/gcs_service.rb
index e2590aa35d..09abc613f3 100644
--- a/activestorage/lib/active_storage/service/gcs_service.rb
+++ b/activestorage/lib/active_storage/service/gcs_service.rb
@@ -13,16 +13,14 @@ module ActiveStorage
def upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil)
instrument :upload, key: key, checksum: checksum do
- begin
- # GCS's signed URLs don't include params such as response-content-type response-content_disposition
- # in the signature, which means an attacker can modify them and bypass our effort to force these to
- # binary and attachment when the file's content type requires it. The only way to force them is to
- # store them as object's metadata.
- content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
- bucket.create_file(io, key, md5: checksum, content_type: content_type, content_disposition: content_disposition)
- rescue Google::Cloud::InvalidArgumentError
- raise ActiveStorage::IntegrityError
- end
+ # GCS's signed URLs don't include params such as response-content-type response-content_disposition
+ # in the signature, which means an attacker can modify them and bypass our effort to force these to
+ # binary and attachment when the file's content type requires it. The only way to force them is to
+ # store them as object's metadata.
+ content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+ bucket.create_file(io, key, md5: checksum, content_type: content_type, content_disposition: content_disposition)
+ rescue Google::Cloud::InvalidArgumentError
+ raise ActiveStorage::IntegrityError
end
end
@@ -33,11 +31,9 @@ module ActiveStorage
end
else
instrument :download, key: key do
- begin
- file_for(key).download.string
- rescue Google::Cloud::NotFoundError
- raise ActiveStorage::FileNotFoundError
- end
+ file_for(key).download.string
+ rescue Google::Cloud::NotFoundError
+ raise ActiveStorage::FileNotFoundError
end
end
end
@@ -53,32 +49,26 @@ module ActiveStorage
def download_chunk(key, range)
instrument :download_chunk, key: key, range: range do
- begin
- file_for(key).download(range: range).string
- rescue Google::Cloud::NotFoundError
- raise ActiveStorage::FileNotFoundError
- end
+ file_for(key).download(range: range).string
+ rescue Google::Cloud::NotFoundError
+ raise ActiveStorage::FileNotFoundError
end
end
def delete(key)
instrument :delete, key: key do
- begin
- file_for(key).delete
- rescue Google::Cloud::NotFoundError
- # Ignore files already deleted
- end
+ file_for(key).delete
+ rescue Google::Cloud::NotFoundError
+ # Ignore files already deleted
end
end
def delete_prefixed(prefix)
instrument :delete_prefixed, prefix: prefix do
bucket.files(prefix: prefix).all do |file|
- begin
- file.delete
- rescue Google::Cloud::NotFoundError
- # Ignore concurrently-deleted files
- end
+ file.delete
+ rescue Google::Cloud::NotFoundError
+ # Ignore concurrently-deleted files
end
end
end
@@ -141,7 +131,7 @@ module ActiveStorage
end
def bucket
- @bucket ||= client.bucket(config.fetch(:bucket))
+ @bucket ||= client.bucket(config.fetch(:bucket), skip_lookup: true)
end
def client
diff --git a/activestorage/lib/active_storage/service/mirror_service.rb b/activestorage/lib/active_storage/service/mirror_service.rb
index 75274f81b3..aa41df304e 100644
--- a/activestorage/lib/active_storage/service/mirror_service.rb
+++ b/activestorage/lib/active_storage/service/mirror_service.rb
@@ -9,7 +9,7 @@ module ActiveStorage
class Service::MirrorService < Service
attr_reader :primary, :mirrors
- delegate :download, :download_chunk, :exist?, :url, to: :primary
+ delegate :download, :download_chunk, :exist?, :url, :path_for, to: :primary
# Stitch together from named services.
def self.build(primary:, mirrors:, configurator:, **options) #:nodoc:
diff --git a/activestorage/lib/active_storage/service/s3_service.rb b/activestorage/lib/active_storage/service/s3_service.rb
index 90c3ae1b62..c7e4ec96a2 100644
--- a/activestorage/lib/active_storage/service/s3_service.rb
+++ b/activestorage/lib/active_storage/service/s3_service.rb
@@ -16,13 +16,11 @@ module ActiveStorage
@upload_options = upload
end
- def upload(key, io, checksum: nil, **)
+ def upload(key, io, checksum: nil, content_type: nil, **)
instrument :upload, key: key, checksum: checksum do
- begin
- object_for(key).put(upload_options.merge(body: io, content_md5: checksum))
- rescue Aws::S3::Errors::BadDigest
- raise ActiveStorage::IntegrityError
- end
+ object_for(key).put(upload_options.merge(body: io, content_md5: checksum, content_type: content_type))
+ rescue Aws::S3::Errors::BadDigest
+ raise ActiveStorage::IntegrityError
end
end
@@ -33,22 +31,18 @@ module ActiveStorage
end
else
instrument :download, key: key do
- begin
- object_for(key).get.body.string.force_encoding(Encoding::BINARY)
- rescue Aws::S3::Errors::NoSuchKey
- raise ActiveStorage::FileNotFoundError
- end
+ object_for(key).get.body.string.force_encoding(Encoding::BINARY)
+ rescue Aws::S3::Errors::NoSuchKey
+ raise ActiveStorage::FileNotFoundError
end
end
end
def download_chunk(key, range)
instrument :download_chunk, key: key, range: range do
- begin
- object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.read.force_encoding(Encoding::BINARY)
- rescue Aws::S3::Errors::NoSuchKey
- raise ActiveStorage::FileNotFoundError
- end
+ object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.string.force_encoding(Encoding::BINARY)
+ rescue Aws::S3::Errors::NoSuchKey
+ raise ActiveStorage::FileNotFoundError
end
end
@@ -114,7 +108,7 @@ module ActiveStorage
raise ActiveStorage::FileNotFoundError unless object.exists?
while offset < object.content_length
- yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.read.force_encoding(Encoding::BINARY)
+ yield object.get(range: "bytes=#{offset}-#{offset + chunk_size - 1}").body.string.force_encoding(Encoding::BINARY)
offset += chunk_size
end
end
diff --git a/activestorage/lib/active_storage/transformers/image_processing_transformer.rb b/activestorage/lib/active_storage/transformers/image_processing_transformer.rb
index 7f8685b72d..506150576c 100644
--- a/activestorage/lib/active_storage/transformers/image_processing_transformer.rb
+++ b/activestorage/lib/active_storage/transformers/image_processing_transformer.rb
@@ -22,7 +22,7 @@ module ActiveStorage
def operations
transformations.each_with_object([]) do |(name, argument), list|
if name.to_s == "combine_options"
- ActiveSupport::Deprecation.warn <<~WARNING
+ ActiveSupport::Deprecation.warn <<~WARNING.squish
Active Storage's ImageProcessing transformer doesn't support :combine_options,
as it always generates a single ImageMagick command. Passing :combine_options will
not be supported in Rails 6.1.
diff --git a/activestorage/lib/tasks/activestorage.rake b/activestorage/lib/tasks/activestorage.rake
index ac254d717f..6b0469636c 100644
--- a/activestorage/lib/tasks/activestorage.rake
+++ b/activestorage/lib/tasks/activestorage.rake
@@ -12,4 +12,11 @@ namespace :active_storage do
Rake::Task["app:active_storage:install:migrations"].invoke
end
end
+
+ # desc "Copy over the migrations needed to the application upgrading"
+ task update: :environment do
+ ENV["MIGRATIONS_PATH"] = "db/update_migrate"
+
+ Rake::Task["active_storage:install"].invoke
+ end
end