aboutsummaryrefslogtreecommitdiffstats
path: root/activestorage/app
diff options
context:
space:
mode:
Diffstat (limited to 'activestorage/app')
-rw-r--r--activestorage/app/assets/javascripts/activestorage.js5
-rw-r--r--activestorage/app/javascript/activestorage/blob_record.js7
-rw-r--r--activestorage/app/jobs/active_storage/analyze_job.rb2
-rw-r--r--activestorage/app/jobs/active_storage/base_job.rb1
-rw-r--r--activestorage/app/jobs/active_storage/purge_job.rb2
-rw-r--r--activestorage/app/models/active_storage/blob.rb16
-rw-r--r--activestorage/app/models/active_storage/blob/representable.rb10
-rw-r--r--activestorage/app/models/active_storage/preview.rb2
-rw-r--r--activestorage/app/models/active_storage/variant.rb8
-rw-r--r--activestorage/app/models/active_storage/variation.rb2
10 files changed, 38 insertions, 17 deletions
diff --git a/activestorage/app/assets/javascripts/activestorage.js b/activestorage/app/assets/javascripts/activestorage.js
index b71e251a11..e2bcb520b9 100644
--- a/activestorage/app/assets/javascripts/activestorage.js
+++ b/activestorage/app/assets/javascripts/activestorage.js
@@ -560,7 +560,10 @@
this.xhr.setRequestHeader("Content-Type", "application/json");
this.xhr.setRequestHeader("Accept", "application/json");
this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
- this.xhr.setRequestHeader("X-CSRF-Token", getMetaValue("csrf-token"));
+ var csrfToken = getMetaValue("csrf-token");
+ if (csrfToken != undefined) {
+ this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
+ }
this.xhr.addEventListener("load", function(event) {
return _this.requestDidLoad(event);
});
diff --git a/activestorage/app/javascript/activestorage/blob_record.js b/activestorage/app/javascript/activestorage/blob_record.js
index ff847892b2..7fbe315f76 100644
--- a/activestorage/app/javascript/activestorage/blob_record.js
+++ b/activestorage/app/javascript/activestorage/blob_record.js
@@ -17,7 +17,12 @@ export class BlobRecord {
this.xhr.setRequestHeader("Content-Type", "application/json")
this.xhr.setRequestHeader("Accept", "application/json")
this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
- this.xhr.setRequestHeader("X-CSRF-Token", getMetaValue("csrf-token"))
+
+ const csrfToken = getMetaValue("csrf-token")
+ if (csrfToken != undefined) {
+ this.xhr.setRequestHeader("X-CSRF-Token", csrfToken)
+ }
+
this.xhr.addEventListener("load", event => this.requestDidLoad(event))
this.xhr.addEventListener("error", event => this.requestDidError(event))
}
diff --git a/activestorage/app/jobs/active_storage/analyze_job.rb b/activestorage/app/jobs/active_storage/analyze_job.rb
index 804ee4557a..35d043d508 100644
--- a/activestorage/app/jobs/active_storage/analyze_job.rb
+++ b/activestorage/app/jobs/active_storage/analyze_job.rb
@@ -2,6 +2,8 @@
# Provides asynchronous analysis of ActiveStorage::Blob records via ActiveStorage::Blob#analyze_later.
class ActiveStorage::AnalyzeJob < ActiveStorage::BaseJob
+ queue_as { ActiveStorage.queues[:analysis] }
+
retry_on ActiveStorage::IntegrityError, attempts: 10, wait: :exponentially_longer
def perform(blob)
diff --git a/activestorage/app/jobs/active_storage/base_job.rb b/activestorage/app/jobs/active_storage/base_job.rb
index 6caab42a2d..7bc2064dc5 100644
--- a/activestorage/app/jobs/active_storage/base_job.rb
+++ b/activestorage/app/jobs/active_storage/base_job.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
class ActiveStorage::BaseJob < ActiveJob::Base
- queue_as { ActiveStorage.queue }
end
diff --git a/activestorage/app/jobs/active_storage/purge_job.rb b/activestorage/app/jobs/active_storage/purge_job.rb
index 2604977bf1..5ceb222005 100644
--- a/activestorage/app/jobs/active_storage/purge_job.rb
+++ b/activestorage/app/jobs/active_storage/purge_job.rb
@@ -2,6 +2,8 @@
# Provides asynchronous purging of ActiveStorage::Blob records via ActiveStorage::Blob#purge_later.
class ActiveStorage::PurgeJob < ActiveStorage::BaseJob
+ queue_as { ActiveStorage.queues[:purge] }
+
discard_on ActiveRecord::RecordNotFound
retry_on ActiveRecord::Deadlocked, attempts: 10, wait: :exponentially_longer
diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb
index 04f9dbff9f..6ca7d49bc1 100644
--- a/activestorage/app/models/active_storage/blob.rb
+++ b/activestorage/app/models/active_storage/blob.rb
@@ -79,6 +79,15 @@ class ActiveStorage::Blob < ActiveRecord::Base
def create_before_direct_upload!(filename:, byte_size:, checksum:, content_type: nil, metadata: nil)
create! filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, metadata: metadata
end
+
+ # To prevent problems with case-insensitive filesystems, especially in combination
+ # with databases which treat indices as case-sensitive, all blob keys generated are going
+ # to only contain the base-36 character alphabet and will therefore be lowercase. To maintain
+ # the same or higher amount of entropy as in the base-58 encoding used by `has_secure_token`
+ # the number of bytes used is increased to 28 from the standard 24
+ def generate_unique_secure_token
+ SecureRandom.base36(28)
+ end
end
# Returns a signed ID for this blob that's suitable for reference on the client-side without fear of tampering.
@@ -87,9 +96,10 @@ class ActiveStorage::Blob < ActiveRecord::Base
ActiveStorage.verifier.generate(id, purpose: :blob_id)
end
- # Returns the key pointing to the file on the service that's associated with this blob. The key is in the
- # standard secure-token format from Rails. So it'll look like: XTAPjJCJiuDrLk3TmwyJGpUo. This key is not intended
- # to be revealed directly to the user. Always refer to blobs using the signed_id or a verified form of the key.
+ # Returns the key pointing to the file on the service that's associated with this blob. The key is the
+ # secure-token format from Rails in lower case. So it'll look like: xtapjjcjiudrlk3tmwyjgpuobabd.
+ # This key is not intended to be revealed directly to the user.
+ # Always refer to blobs using the signed_id or a verified form of the key.
def key
# We can't wait until the record is first saved to have a key for it
self[:key] ||= self.class.generate_unique_secure_token
diff --git a/activestorage/app/models/active_storage/blob/representable.rb b/activestorage/app/models/active_storage/blob/representable.rb
index 03d5511481..32e8fcefdf 100644
--- a/activestorage/app/models/active_storage/blob/representable.rb
+++ b/activestorage/app/models/active_storage/blob/representable.rb
@@ -10,7 +10,7 @@ module ActiveStorage::Blob::Representable
# Returns an ActiveStorage::Variant instance with the set of +transformations+ provided. This is only relevant for image
# files, and it allows any image to be transformed for size, colors, and the like. Example:
#
- # avatar.variant(resize_to_fit: [100, 100]).processed.service_url
+ # avatar.variant(resize_to_limit: [100, 100]).processed.service_url
#
# This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
# Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
@@ -18,7 +18,7 @@ module ActiveStorage::Blob::Representable
# Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
# specific variant that can be created by a controller on-demand. Like so:
#
- # <%= image_tag Current.user.avatar.variant(resize_to_fit: [100, 100]) %>
+ # <%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
#
# This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController
# can then produce on-demand.
@@ -43,13 +43,13 @@ module ActiveStorage::Blob::Representable
# from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
# extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
#
- # blob.preview(resize_to_fit: [100, 100]).processed.service_url
+ # blob.preview(resize_to_limit: [100, 100]).processed.service_url
#
# Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
# Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
# how to use the built-in version:
#
- # <%= image_tag video.preview(resize_to_fit: [100, 100]) %>
+ # <%= image_tag video.preview(resize_to_limit: [100, 100]) %>
#
# This method raises ActiveStorage::UnpreviewableError if no previewer accepts the receiving blob. To determine
# whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.
@@ -69,7 +69,7 @@ module ActiveStorage::Blob::Representable
# Returns an ActiveStorage::Preview for a previewable blob or an ActiveStorage::Variant for a variable image blob.
#
- # blob.representation(resize_to_fit: [100, 100]).processed.service_url
+ # blob.representation(resize_to_limit: [100, 100]).processed.service_url
#
# Raises ActiveStorage::UnrepresentableError if the receiving blob is neither variable nor previewable. Call
# ActiveStorage::Blob#representable? to determine whether a blob is representable.
diff --git a/activestorage/app/models/active_storage/preview.rb b/activestorage/app/models/active_storage/preview.rb
index dd50494799..bb9d960443 100644
--- a/activestorage/app/models/active_storage/preview.rb
+++ b/activestorage/app/models/active_storage/preview.rb
@@ -38,7 +38,7 @@ class ActiveStorage::Preview
# Processes the preview if it has not been processed yet. Returns the receiving Preview instance for convenience:
#
- # blob.preview(resize_to_fit: [100, 100]).processed.service_url
+ # blob.preview(resize_to_limit: [100, 100]).processed.service_url
#
# Processing a preview generates an image from its blob and attaches the preview image to the blob. Because the preview
# image is stored with the blob, it is only generated once.
diff --git a/activestorage/app/models/active_storage/variant.rb b/activestorage/app/models/active_storage/variant.rb
index ea57fa5f78..bc0058967a 100644
--- a/activestorage/app/models/active_storage/variant.rb
+++ b/activestorage/app/models/active_storage/variant.rb
@@ -27,7 +27,7 @@ require "ostruct"
# To refer to such a delayed on-demand variant, simply link to the variant through the resolved route provided
# by Active Storage like so:
#
-# <%= image_tag Current.user.avatar.variant(resize_to_fit: [100, 100]) %>
+# <%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
#
# This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController
# can then produce on-demand.
@@ -36,15 +36,15 @@ require "ostruct"
# has already been processed and uploaded to the service, and, if so, just return that. Otherwise it will perform
# the transformations, upload the variant to the service, and return itself again. Example:
#
-# avatar.variant(resize_to_fit: [100, 100]).processed.service_url
+# avatar.variant(resize_to_limit: [100, 100]).processed.service_url
#
# This will create and process a variant of the avatar blob that's constrained to a height and width of 100.
# Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
#
# You can combine any number of ImageMagick/libvips operations into a variant, as well as any macros provided by the
-# ImageProcessing gem (such as +resize_to_fit+):
+# ImageProcessing gem (such as +resize_to_limit+):
#
-# avatar.variant(resize_to_fit: [800, 800], monochrome: true, rotate: "-90")
+# avatar.variant(resize_to_limit: [800, 800], monochrome: true, rotate: "-90")
#
# Visit the following links for a list of available ImageProcessing commands and ImageMagick/libvips operations:
#
diff --git a/activestorage/app/models/active_storage/variation.rb b/activestorage/app/models/active_storage/variation.rb
index 3adc2407e5..67568772da 100644
--- a/activestorage/app/models/active_storage/variation.rb
+++ b/activestorage/app/models/active_storage/variation.rb
@@ -6,7 +6,7 @@
# In case you do need to use this directly, it's instantiated using a hash of transformations where
# the key is the command and the value is the arguments. Example:
#
-# ActiveStorage::Variation.new(resize_to_fit: [100, 100], monochrome: true, trim: true, rotate: "-90")
+# ActiveStorage::Variation.new(resize_to_limit: [100, 100], monochrome: true, trim: true, rotate: "-90")
#
# The options map directly to {ImageProcessing}[https://github.com/janko-m/image_processing] commands.
class ActiveStorage::Variation