shrine 2.19.3 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +523 -41
- data/LICENSE.txt +1 -1
- data/README.md +83 -979
- data/doc/advantages.md +231 -204
- data/doc/attacher.md +304 -153
- data/doc/carrierwave.md +297 -226
- data/doc/changing_derivatives.md +308 -0
- data/doc/changing_location.md +103 -21
- data/doc/changing_storage.md +110 -0
- data/doc/creating_persistence_plugins.md +132 -0
- data/doc/creating_plugins.md +43 -23
- data/doc/creating_storages.md +19 -5
- data/doc/design.md +147 -97
- data/doc/direct_s3.md +38 -28
- data/doc/external/articles.md +63 -0
- data/doc/external/extensions.md +53 -0
- data/doc/external/misc.md +32 -0
- data/doc/getting_started.md +1156 -0
- data/doc/metadata.md +190 -109
- data/doc/multiple_files.md +93 -30
- data/doc/paperclip.md +384 -262
- data/doc/plugins/activerecord.md +177 -46
- data/doc/plugins/add_metadata.md +139 -38
- data/doc/plugins/atomic_helpers.md +217 -0
- data/doc/plugins/backgrounding.md +156 -98
- data/doc/plugins/cached_attachment_data.md +7 -5
- data/doc/plugins/column.md +121 -0
- data/doc/plugins/data_uri.md +23 -22
- data/doc/plugins/default_storage.md +36 -10
- data/doc/plugins/default_url.md +30 -13
- data/doc/plugins/delete_raw.md +4 -2
- data/doc/plugins/derivation_endpoint.md +186 -101
- data/doc/plugins/derivatives.md +839 -0
- data/doc/plugins/determine_mime_type.md +4 -2
- data/doc/plugins/download_endpoint.md +64 -8
- data/doc/plugins/dynamic_storage.md +5 -3
- data/doc/plugins/entity.md +263 -0
- data/doc/plugins/form_assign.md +55 -0
- data/doc/plugins/included.md +31 -8
- data/doc/plugins/infer_extension.md +21 -10
- data/doc/plugins/instrumentation.md +38 -16
- data/doc/plugins/keep_files.md +16 -17
- data/doc/plugins/metadata_attributes.md +42 -13
- data/doc/plugins/mirroring.md +118 -0
- data/doc/plugins/model.md +210 -0
- data/doc/plugins/module_include.md +4 -2
- data/doc/plugins/multi_cache.md +24 -0
- data/doc/plugins/persistence.md +101 -0
- data/doc/plugins/presign_endpoint.md +9 -4
- data/doc/plugins/pretty_location.md +16 -3
- data/doc/plugins/processing.md +4 -2
- data/doc/plugins/rack_file.md +8 -2
- data/doc/plugins/rack_response.md +6 -2
- data/doc/plugins/recache.md +4 -2
- data/doc/plugins/refresh_metadata.md +49 -9
- data/doc/plugins/remote_url.md +84 -47
- data/doc/plugins/remove_attachment.md +27 -6
- data/doc/plugins/remove_invalid.md +21 -6
- data/doc/plugins/restore_cached_data.md +11 -3
- data/doc/plugins/sequel.md +159 -35
- data/doc/plugins/signature.md +16 -5
- data/doc/plugins/store_dimensions.md +14 -2
- data/doc/plugins/tempfile.md +4 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +13 -13
- data/doc/plugins/upload_options.md +6 -4
- data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
- data/doc/plugins/validation.md +97 -0
- data/doc/plugins/validation_helpers.md +16 -13
- data/doc/plugins/versions.md +15 -19
- data/doc/processing.md +438 -221
- data/doc/refile.md +188 -170
- data/doc/release_notes/1.0.0.md +4 -0
- data/doc/release_notes/1.1.0.md +6 -2
- data/doc/release_notes/1.2.0.md +4 -0
- data/doc/release_notes/1.3.0.md +4 -0
- data/doc/release_notes/1.4.0.md +4 -0
- data/doc/release_notes/1.4.1.md +4 -0
- data/doc/release_notes/1.4.2.md +4 -0
- data/doc/release_notes/2.0.0.md +4 -0
- data/doc/release_notes/2.0.1.md +4 -0
- data/doc/release_notes/2.1.0.md +5 -1
- data/doc/release_notes/2.1.1.md +4 -0
- data/doc/release_notes/2.10.0.md +4 -0
- data/doc/release_notes/2.10.1.md +4 -0
- data/doc/release_notes/2.11.0.md +4 -0
- data/doc/release_notes/2.12.0.md +4 -0
- data/doc/release_notes/2.13.0.md +4 -0
- data/doc/release_notes/2.14.0.md +5 -1
- data/doc/release_notes/2.15.0.md +11 -7
- data/doc/release_notes/2.16.0.md +4 -0
- data/doc/release_notes/2.17.0.md +4 -0
- data/doc/release_notes/2.18.0.md +4 -0
- data/doc/release_notes/2.19.0.md +6 -3
- data/doc/release_notes/2.2.0.md +4 -0
- data/doc/release_notes/2.3.0.md +4 -0
- data/doc/release_notes/2.3.1.md +4 -0
- data/doc/release_notes/2.4.0.md +4 -0
- data/doc/release_notes/2.4.1.md +4 -0
- data/doc/release_notes/2.5.0.md +4 -0
- data/doc/release_notes/2.6.0.md +4 -0
- data/doc/release_notes/2.6.1.md +4 -0
- data/doc/release_notes/2.7.0.md +4 -0
- data/doc/release_notes/2.8.0.md +4 -0
- data/doc/release_notes/2.9.0.md +4 -0
- data/doc/release_notes/3.0.0.md +981 -0
- data/doc/release_notes/3.0.1.md +22 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/release_notes/3.4.0.md +35 -0
- data/doc/release_notes/3.5.0.md +63 -0
- data/doc/release_notes/3.6.0.md +23 -0
- data/doc/retrieving_uploads.md +5 -2
- data/doc/securing_uploads.md +60 -37
- data/doc/storage/file_system.md +20 -3
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +122 -78
- data/doc/testing.md +141 -133
- data/doc/upgrading_to_3.md +708 -0
- data/doc/validation.md +54 -90
- data/lib/shrine/attacher.rb +292 -169
- data/lib/shrine/attachment.rb +13 -46
- data/lib/shrine/plugins/_persistence.rb +93 -0
- data/lib/shrine/plugins/activerecord.rb +77 -34
- data/lib/shrine/plugins/add_metadata.rb +25 -17
- data/lib/shrine/plugins/atomic_helpers.rb +119 -0
- data/lib/shrine/plugins/backgrounding.rb +77 -113
- data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
- data/lib/shrine/plugins/column.rb +102 -0
- data/lib/shrine/plugins/data_uri.rb +38 -36
- data/lib/shrine/plugins/default_storage.rb +45 -15
- data/lib/shrine/plugins/default_url.rb +12 -24
- data/lib/shrine/plugins/default_url_options.rb +3 -30
- data/lib/shrine/plugins/delete_raw.rb +10 -16
- data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
- data/lib/shrine/plugins/derivatives.rb +645 -0
- data/lib/shrine/plugins/determine_mime_type.rb +9 -21
- data/lib/shrine/plugins/download_endpoint.rb +118 -133
- data/lib/shrine/plugins/dynamic_storage.rb +5 -11
- data/lib/shrine/plugins/entity.rb +158 -0
- data/lib/shrine/plugins/form_assign.rb +108 -0
- data/lib/shrine/plugins/included.rb +6 -6
- data/lib/shrine/plugins/infer_extension.rb +17 -20
- data/lib/shrine/plugins/instrumentation.rb +59 -43
- data/lib/shrine/plugins/keep_files.rb +3 -15
- data/lib/shrine/plugins/metadata_attributes.rb +28 -19
- data/lib/shrine/plugins/mirroring.rb +142 -0
- data/lib/shrine/plugins/model.rb +160 -0
- data/lib/shrine/plugins/module_include.rb +3 -3
- data/lib/shrine/plugins/multi_cache.rb +27 -0
- data/lib/shrine/plugins/presign_endpoint.rb +27 -28
- data/lib/shrine/plugins/pretty_location.rb +15 -9
- data/lib/shrine/plugins/processing.rb +22 -9
- data/lib/shrine/plugins/rack_file.rb +2 -42
- data/lib/shrine/plugins/rack_response.rb +21 -10
- data/lib/shrine/plugins/recache.rb +6 -5
- data/lib/shrine/plugins/refresh_metadata.rb +13 -11
- data/lib/shrine/plugins/remote_url.rb +49 -49
- data/lib/shrine/plugins/remove_attachment.rb +12 -6
- data/lib/shrine/plugins/remove_invalid.rb +19 -8
- data/lib/shrine/plugins/restore_cached_data.rb +13 -7
- data/lib/shrine/plugins/sequel.rb +86 -36
- data/lib/shrine/plugins/signature.rb +10 -16
- data/lib/shrine/plugins/store_dimensions.rb +35 -40
- data/lib/shrine/plugins/tempfile.rb +1 -3
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +28 -24
- data/lib/shrine/plugins/upload_options.rb +14 -15
- data/lib/shrine/plugins/url_options.rb +31 -0
- data/lib/shrine/plugins/validation.rb +80 -0
- data/lib/shrine/plugins/validation_helpers.rb +35 -58
- data/lib/shrine/plugins/versions.rb +107 -87
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/storage/file_system.rb +46 -64
- data/lib/shrine/storage/linter.rb +42 -7
- data/lib/shrine/storage/memory.rb +49 -0
- data/lib/shrine/storage/s3.rb +173 -160
- data/lib/shrine/uploaded_file.rb +32 -32
- data/lib/shrine/version.rb +3 -3
- data/lib/shrine.rb +87 -150
- data/shrine.gemspec +11 -12
- metadata +92 -82
- data/doc/migrating_storage.md +0 -76
- data/doc/plugins/backup.md +0 -31
- data/doc/plugins/copy.md +0 -24
- data/doc/plugins/delete_promoted.md +0 -12
- data/doc/plugins/direct_upload.md +0 -172
- data/doc/plugins/hooks.md +0 -58
- data/doc/plugins/logging.md +0 -42
- data/doc/plugins/migration_helpers.md +0 -60
- data/doc/plugins/moving.md +0 -19
- data/doc/plugins/multi_delete.md +0 -20
- data/doc/plugins/parallelize.md +0 -16
- data/doc/plugins/parsed_json.md +0 -23
- data/doc/regenerating_versions.md +0 -143
- data/lib/shrine/plugins/background_helpers.rb +0 -5
- data/lib/shrine/plugins/backup.rb +0 -90
- data/lib/shrine/plugins/copy.rb +0 -50
- data/lib/shrine/plugins/delete_promoted.rb +0 -20
- data/lib/shrine/plugins/direct_upload.rb +0 -217
- data/lib/shrine/plugins/hooks.rb +0 -90
- data/lib/shrine/plugins/logging.rb +0 -142
- data/lib/shrine/plugins/migration_helpers.rb +0 -70
- data/lib/shrine/plugins/moving.rb +0 -57
- data/lib/shrine/plugins/multi_delete.rb +0 -32
- data/lib/shrine/plugins/parallelize.rb +0 -78
- data/lib/shrine/plugins/parsed_json.rb +0 -29
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.0.1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Regressions
|
|
6
|
+
|
|
7
|
+
* Fixed `metadata_attributes` plugin raising an exception when the attachment
|
|
8
|
+
is removed (assigned to `nil`).
|
|
9
|
+
|
|
10
|
+
## Improvements
|
|
11
|
+
|
|
12
|
+
* Simplified `UploadedFile#inspect` output:
|
|
13
|
+
|
|
14
|
+
```rb
|
|
15
|
+
# before
|
|
16
|
+
uploaded_file.inspect
|
|
17
|
+
#=> #<Shrine::UploadedFile:0x00007fa4e4140d30 @id="cda84bbdab12b2bd41ea34590060a807", @storage_key=:memory, @metadata={"filename"=>nil, "size"=>0, "mime_type"=>nil}>
|
|
18
|
+
|
|
19
|
+
# after
|
|
20
|
+
uploaded_file.inspect
|
|
21
|
+
#=> #<Shrine::UploadedFile id="488b887dd792b4c82d3fc445140c5a38" storage=:memory metadata={"filename"=>nil, "size"=>0, "mime_type"=>nil}>
|
|
22
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.1.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## New features
|
|
6
|
+
|
|
7
|
+
* The `Attacher#create_derivatives` method now accepts a `:storage` option for
|
|
8
|
+
specifying the storage to which derivatives should be uploaded.
|
|
9
|
+
|
|
10
|
+
```rb
|
|
11
|
+
# with attachment module
|
|
12
|
+
photo.image_derivatives!(storage: :other_store)
|
|
13
|
+
|
|
14
|
+
# with attacher
|
|
15
|
+
attacher.create_derivatives(storage: :other_store)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
* The `Shrine.calculate_signature` now accepts a `:rewind` boolean option for
|
|
19
|
+
choosing whether the IO object should be rewinded after reading. This is
|
|
20
|
+
useful if you want to calculate signature from non-rewindable IO objects,
|
|
21
|
+
such as `IO.pipe`, `Socket`, non-rewindable `Down::ChunkedIO` etc.
|
|
22
|
+
|
|
23
|
+
```rb
|
|
24
|
+
Shrine.signature(io, rewind: false)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Improvements
|
|
28
|
+
|
|
29
|
+
* The derivatives processor can now be registered with `Attacher.derivatives`,
|
|
30
|
+
which is just an alias for `Attacher.derivatives_processor`.
|
|
31
|
+
|
|
32
|
+
```rb
|
|
33
|
+
class ImageUploader < Shrine
|
|
34
|
+
Attacher.derivatives_processor do |original|
|
|
35
|
+
# ...
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# can now be written as
|
|
40
|
+
|
|
41
|
+
class ImageUploader < Shrine
|
|
42
|
+
Attacher.derivatives do |original|
|
|
43
|
+
# ...
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
* The `Attacher#cached?` and `Attacher#stored?` methods now work correctly if
|
|
49
|
+
temporary/permanent storage identifiers were specified as strings.
|
|
50
|
+
|
|
51
|
+
* The `store_dimensions` plugin now properly propagates exceptions when loading
|
|
52
|
+
the `ruby-vips` gem in `:vips` analyzer.
|
|
53
|
+
|
|
54
|
+
* The `add_metadata` plugin now respects inheritance again when defining
|
|
55
|
+
metadata methods on the `Shrine::UploadedFile` class. In 2.19.0, the
|
|
56
|
+
`add_metadata` plugin was changed to define metadata methods on the internal
|
|
57
|
+
`FileMethods` plugin module, which is shared across all uploaders. This
|
|
58
|
+
change has now been reverted.
|
|
59
|
+
|
|
60
|
+
## Backwards compatibility
|
|
61
|
+
|
|
62
|
+
* The `Attacher#cache_key` and `Attacher#store_key` methods now always return
|
|
63
|
+
symbol keys, even if the storage key that was specified was a string key.
|
|
64
|
+
|
|
65
|
+
```rb
|
|
66
|
+
attacher = Shrine::Attacher.new(cache: "cache", store: "store")
|
|
67
|
+
attacher.cache_key #=> :cache (previously "cache")
|
|
68
|
+
attacher.store_key #=> :store (previously "store")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
* The `add_metadata` plugin now defines metadata methods directly on the
|
|
72
|
+
`UploadedFile` class, which means that if you happen to have been overriding
|
|
73
|
+
these metadata methods and calling `super`, this won't work anymore.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.2.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## New features
|
|
6
|
+
|
|
7
|
+
* The `type_predicates` plugin has been added, which adds convenient predicate
|
|
8
|
+
methods to `Shrine::UploadedFile` based on the MIME type.
|
|
9
|
+
|
|
10
|
+
```rb
|
|
11
|
+
# Gemfile
|
|
12
|
+
gem "mini_mime" # default dependency of type_predicates
|
|
13
|
+
```
|
|
14
|
+
```rb
|
|
15
|
+
Shrine.plugin :type_predicates
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The plugin adds four predicate methods based on the general type of the file:
|
|
19
|
+
|
|
20
|
+
```rb
|
|
21
|
+
file.image? # returns true for any "image/*" MIME type
|
|
22
|
+
file.video? # returns true for any "video/*" MIME type
|
|
23
|
+
file.audio? # returns true for any "audio/*" MIME type
|
|
24
|
+
file.text? # returns true for any "text/*" MIME type
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can also check for specific MIME type using the extension name:
|
|
28
|
+
|
|
29
|
+
```rb
|
|
30
|
+
file.type?(:jpg) # returns true if MIME type is "image/jpeg"
|
|
31
|
+
file.type?(:svg) # returns true if MIME type is "image/svg+xml"
|
|
32
|
+
file.type?(:mov) # returns true if MIME type is "video/quicktime"
|
|
33
|
+
file.type?(:ppt) # returns true if MIME type is "application/vnd.ms-powerpoint"
|
|
34
|
+
...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For convenience, you can create predicate methods for specific file types:
|
|
38
|
+
|
|
39
|
+
```rb
|
|
40
|
+
Shrine.plugin :type_predicates, methods: %i[jpg svg mov ppt]
|
|
41
|
+
```
|
|
42
|
+
```rb
|
|
43
|
+
file.jpg? # returns true if MIME type is "image/jpeg"
|
|
44
|
+
file.svg? # returns true if MIME type is "image/svg+xml"
|
|
45
|
+
file.mov? # returns true if MIME type is "video/quicktime"
|
|
46
|
+
file.ppt? # returns true if MIME type is "application/vnd.ms-powerpoint"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
* The `#add_metadata` method has been added to the `add_metadata` plugin for
|
|
50
|
+
adding new metadata to an existing file/attachment.
|
|
51
|
+
|
|
52
|
+
```rb
|
|
53
|
+
attacher.file.metadata #=> { ... }
|
|
54
|
+
attacher.add_metadata("foo" => "bar")
|
|
55
|
+
attacher.file.metadata #=> { ..., "foo" => "bar" }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Other improvements
|
|
59
|
+
|
|
60
|
+
* The `remove_invalid` plugin now works correctly with `derivatives` plugin.
|
|
61
|
+
|
|
62
|
+
* The `remove_invalid` plugin is now also activated when `Attacher#validate`
|
|
63
|
+
is called manually.
|
|
64
|
+
|
|
65
|
+
* The current attached file data can now be assigned back to the attachment
|
|
66
|
+
attribute, and this operation will be a no-op.
|
|
67
|
+
|
|
68
|
+
```rb
|
|
69
|
+
photo.image #=> #<Shrine::UploadedFile id="foo" storage=:store metadata={...}>
|
|
70
|
+
photo.image = { "id" => "foo", "storage" => "store", "metadata" => { ... } } # no-op
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This allows treating the attachment attribute as a persistent attribute,
|
|
74
|
+
where the current value can be assigned back on record updates.
|
|
75
|
+
|
|
76
|
+
* When promoting derivatives, the `:derivative` parameter value was being
|
|
77
|
+
passed to the uploader as an array. This has been fixed, and the value is now
|
|
78
|
+
the same as when uploading derivatives directly to permanent storage.
|
|
79
|
+
|
|
80
|
+
* The `derivatives` plugin now includes additional `:io` and `:attacher` values
|
|
81
|
+
in the instrumentation event payload.
|
|
82
|
+
|
|
83
|
+
## Backwards compatibility
|
|
84
|
+
|
|
85
|
+
* The `validation` plugin now runs validations on `Attacher#attach` and
|
|
86
|
+
`Attacher#attach_cached`. If you were using `Attacher#change` directly and
|
|
87
|
+
expecting the validations to be run automatically, you will need to update
|
|
88
|
+
your code.
|
|
89
|
+
|
|
90
|
+
* If you were updating the cached file metadata via file data assignment, this
|
|
91
|
+
will no longer work.
|
|
92
|
+
|
|
93
|
+
```rb
|
|
94
|
+
photo.image #=> #<Shrine::UploadedFile id="foo" storage=:cache metadata={...}>
|
|
95
|
+
photo.image = { "id" => "foo", "storage" => "cache", "metadata" => { ... } } # no-op
|
|
96
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.2.1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Ruby 2.7 compatibility
|
|
6
|
+
|
|
7
|
+
* Shrine doesn't trigger [Ruby 2.7 warnings for separation of positional and
|
|
8
|
+
keyword arguments][kwargs] anymore.
|
|
9
|
+
|
|
10
|
+
* Down 5.1.0 has been released, which resolves warnings and a `FrozenError`
|
|
11
|
+
exception on Ruby 2.7. Shrine now requires at least this version of Down.
|
|
12
|
+
|
|
13
|
+
If you're using `Down::Http`, make sure you're using http.rb 4.3.0 or newer.
|
|
14
|
+
|
|
15
|
+
* ImageProcessing 1.10.3 gem has been released which resolves Ruby 2.7 warnings
|
|
16
|
+
as well. If you're using it for image processing, make sure to upgrade to
|
|
17
|
+
this version:
|
|
18
|
+
|
|
19
|
+
```rb
|
|
20
|
+
gem "image_processing", ">= 1.10.3", "< 2"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Rack 2.1 compatibility
|
|
24
|
+
|
|
25
|
+
* The `derivation_endpoint` plugin now uses `Rack::Files` on Rack 2.1 or newer.
|
|
26
|
+
|
|
27
|
+
## Other improvements
|
|
28
|
+
|
|
29
|
+
* The `S3#open` method now handles empty S3 objects.
|
|
30
|
+
|
|
31
|
+
[kwargs]: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.2.2
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Bug fixes
|
|
6
|
+
|
|
7
|
+
* aws-sdk-core 3.104.0 introduced a backwards incompatible changes that caused
|
|
8
|
+
`Shrine::Storage::S3#open` to start raising an exception.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
NoMethodError: undefined method `bytesize' for #<Array:0x000000000a721be0>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This has now been fixed.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.3.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## New features
|
|
6
|
+
|
|
7
|
+
* The `:create_on_promote` option has been added to the `derivatives` plugin
|
|
8
|
+
for automatically creating derivatives after the attached cached file is
|
|
9
|
+
promoted to permanent storage.
|
|
10
|
+
|
|
11
|
+
```rb
|
|
12
|
+
Shrine.plugin :derivatives, create_on_promote: true
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
* The `:auto_extraction` option has been added to the `store_dimensions` plugin
|
|
16
|
+
for skipping automatically extracting dimensions on upload.
|
|
17
|
+
|
|
18
|
+
```rb
|
|
19
|
+
Shrine.plugin :store_dimensions, auto_extraction: false
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
* The `:skip_nil` option has been added to the `add_metadata` plugin for
|
|
23
|
+
excluding metadata keys whose values are nil.
|
|
24
|
+
|
|
25
|
+
```rb
|
|
26
|
+
class PdfUploader < Shrine
|
|
27
|
+
add_metadata :pages, skip_nil: true do |io|
|
|
28
|
+
if is_pdf?(io)
|
|
29
|
+
reader = PDF::Reader.new(io)
|
|
30
|
+
reader.page_count
|
|
31
|
+
else
|
|
32
|
+
# If this is not a PDF, then the pages metadata will not be stored
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
* The `:download` option has been added to derivatives processors in
|
|
40
|
+
`derivatives` plugin for skipping converting the source IO object into a
|
|
41
|
+
file. This can be used to avoid a potentially expensive download/copy when
|
|
42
|
+
the derivatives processor doesn't need the file.
|
|
43
|
+
|
|
44
|
+
```rb
|
|
45
|
+
Attacher.derivatives :my_processor, download: false do |source|
|
|
46
|
+
source #=> Could be File, Shrine::UploadedFile, or other IO-like object
|
|
47
|
+
shrine_class.with_file(source) do |file|
|
|
48
|
+
# can force download/copy if necessary with `with_file`,
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Bug fixes
|
|
54
|
+
|
|
55
|
+
* The `upload_endpoint` now handles calling `Shrine.upload_response` method
|
|
56
|
+
from a Rails controller.
|
|
57
|
+
|
|
58
|
+
* The `derivation_endpoint` plugin now applies the `version` query parameter
|
|
59
|
+
to the derivation when creating the response.
|
|
60
|
+
|
|
61
|
+
## Other improvements
|
|
62
|
+
|
|
63
|
+
* The new `Aws:S3::EncryptionV2::Client` is now supported by the S3 storage for
|
|
64
|
+
client-side encryption.
|
|
65
|
+
|
|
66
|
+
* The `derivation_endpoint` now reduces the possibility of timing attacks by
|
|
67
|
+
comparing URL signatures in constant time using `Rack::Utils.secure_compare`.
|
|
68
|
+
|
|
69
|
+
* The `derivatives` plugin now copies non-file source IO objects to disk before
|
|
70
|
+
passing them to the processor. This is consistent with how a
|
|
71
|
+
`Shrine::UploadedFile` object is downloaded to disk.
|
|
72
|
+
|
|
73
|
+
* The `sequel` and `activerecord` plugins now call `Attacher#reload` when
|
|
74
|
+
reloading the model, which reloads the attached files but keeps other
|
|
75
|
+
attacher state.
|
|
76
|
+
|
|
77
|
+
* The `derivatives` plugin doesn't download the attached file anymore if
|
|
78
|
+
attempting to process derivatives when no derivatives processor was defined.
|
|
79
|
+
|
|
80
|
+
* The `mirroring` plugin now forwards attacher options when uploading to mirror
|
|
81
|
+
storages.
|
|
82
|
+
|
|
83
|
+
* The `presign_endpoint` plugin now handles the `OPTIONS` HTTP verb, which
|
|
84
|
+
newer versions of Uppy are requesting.
|
|
85
|
+
|
|
86
|
+
* `Shrine::Storage::Memory#open` now always returns a `StringIO` in the file
|
|
87
|
+
content's original encoding, instead of the encoding set by
|
|
88
|
+
`Encoding.default_internal`. This works around a [bug][ruby-lang #16497]
|
|
89
|
+
in `StringIO` introduced in Ruby 2.7.0.
|
|
90
|
+
|
|
91
|
+
* The `remove_attachment` plugin now deletes the removed file if a new file was
|
|
92
|
+
attached right after removal.
|
|
93
|
+
|
|
94
|
+
## Backwards compatibility
|
|
95
|
+
|
|
96
|
+
* If you were passing a non-file IO object to the derivatives processor, Shrine
|
|
97
|
+
will now convert it into a file beforehand. If you're currently doing this
|
|
98
|
+
and are converting the IO object into a file inside the processor, you can
|
|
99
|
+
now remove the conversion code to avoid doubling the amount of disk writes.
|
|
100
|
+
|
|
101
|
+
* When reloading a Sequel/ActiveRecord model, any attacher state other than
|
|
102
|
+
uploaded files will now be retained after the reload. If you were relying on
|
|
103
|
+
all the attacher state being re-initialized, you'll need to update your code.
|
|
104
|
+
|
|
105
|
+
[ruby-lang #16497]: https://bugs.ruby-lang.org/issues/16497
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.4.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
* Passing attacher options to `Shrine.Attachment` method now works on Ruby 3.0.
|
|
6
|
+
|
|
7
|
+
* Defining validation errors as an array of I18n key and options in
|
|
8
|
+
`activerecord` plugin now works on Ruby 3.0.
|
|
9
|
+
|
|
10
|
+
* The `:fastimage` MIME type analyzer now correctly detects SVGs as
|
|
11
|
+
`image/svg+html` in the `determine_mime_type` plugin.
|
|
12
|
+
|
|
13
|
+
* The `Shrine::Attacher#read` method provided by the `entity` plugin is now
|
|
14
|
+
public. This is consistent with `Shrine::Attacher#write` from `model` plugin
|
|
15
|
+
being public as well.
|
|
16
|
+
|
|
17
|
+
* The `Shrine::Attacher#reload` method now resets attachment's dirty state.
|
|
18
|
+
This means that for a model whose `Attacher#changed?` returns `true`, calling
|
|
19
|
+
`#reload` on the model will make `Attacher#changed?` return `false`. This was
|
|
20
|
+
the behaviour before Shrine 3.3.0.
|
|
21
|
+
|
|
22
|
+
```rb
|
|
23
|
+
# before
|
|
24
|
+
model.file_attacher.changed? #=> true
|
|
25
|
+
model.reload
|
|
26
|
+
model.file_attacher.changed? #=> true
|
|
27
|
+
|
|
28
|
+
# after
|
|
29
|
+
model.file_attacher.changed? #=> true
|
|
30
|
+
model.reload
|
|
31
|
+
model.file_attacher.changed? #=> false
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
* Calling `#reload` on the model will not initialize a `Shrine::Attacher`
|
|
35
|
+
instance anymore if one hasn't previously been initialized.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.5.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## New features
|
|
6
|
+
|
|
7
|
+
* The website has been migrated to Docusaurus v2. :sparkles:
|
|
8
|
+
|
|
9
|
+
* The `:signer` option has been added to the `derivation_endpoint` plugin, for when you want to use custom URL signing. This is useful when using `:expires_in`, and wanting to have expiring URLs work with CDN caching.
|
|
10
|
+
|
|
11
|
+
```rb
|
|
12
|
+
require "aws-sdk-cloudfront"
|
|
13
|
+
signer = Aws::CloudFront::UrlSigner.new(key_pair_id: "...", private_key: "...")
|
|
14
|
+
|
|
15
|
+
plugin :derivation_endpoint,
|
|
16
|
+
expires_in: 90,
|
|
17
|
+
signer: -> (url, expires_in:) do
|
|
18
|
+
signer.signed_url(url, expires: Time.now.to_i + expires_in)
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
* The S3 storage now supports `:max_multipart_parts` option for specifying the maximum number of concurrent parts in which a large file will get uploaded. This number defaults to `10_000`.
|
|
23
|
+
|
|
24
|
+
```rb
|
|
25
|
+
Shrine::Storage::S3.new(max_multipart_parts: 1000, ...)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
* The `:encoding` option can now be passed to `S3#open`, which is applied to downloaded chunks.
|
|
29
|
+
|
|
30
|
+
```rb
|
|
31
|
+
io = uploaded_file.open(encoding: Encoding::UTF_8)
|
|
32
|
+
csv = CSV.new(io)
|
|
33
|
+
# ...
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Other improvements
|
|
37
|
+
|
|
38
|
+
* Passing a boolean value to the `#remove_attachment=` setter now works on Ruby 3.2. Previously this would raise an error, because Shrine would try to call `=~` on it, but `Object#=~` method has been removed in Ruby 3.2.
|
|
39
|
+
|
|
40
|
+
* When duplicating a model instance, the duplicated attacher now references the duplicated model instance instead of the original one.
|
|
41
|
+
|
|
42
|
+
* The download endpoint now returns a `400 Bad Request` response when the serialized file component is invalid.
|
|
43
|
+
|
|
44
|
+
* The `derivatives` plugin now supports passing `mutex: false` option to disable usage of a mutex. This makes the `Shrine::Attacher` object marshallable, which should enable using `Marshal.dump` and `Marshal.load` on model instances with attachments. This should be safe unless you're adding derivatives on the same attacher object concurrently.
|
|
45
|
+
|
|
46
|
+
* When loading the `derivatives` plugin with `versions_compatibility: true`, this setting doesn't leak to other uploaders anymore. Previously if other uploaders would load `derivatives` plugin without this option, versions compatibility would still get enabled for them. This change also fixes behavior on JRuby.
|
|
47
|
+
|
|
48
|
+
* When S3 storage copies files, the AWS tag are not inherited anymore. This allows passing the `:tagging` upload option when promoting from temporary to permanent storage, and have it take effect.
|
|
49
|
+
|
|
50
|
+
* The `UploadedFile#url` method doesn't call the obsolete `URI.regexp` method anymore, which should avoid warnings.
|
|
51
|
+
|
|
52
|
+
* The `infer_extension` plugin now defines `infer_extension` instance method (in addition to class method) on the uploader for convenience, so that it can be easily called at the uploader instance level.
|
|
53
|
+
|
|
54
|
+
```rb
|
|
55
|
+
class MyUploader < Shrine
|
|
56
|
+
plugin :infer_extension
|
|
57
|
+
|
|
58
|
+
def generate_location(io, metadata:, **)
|
|
59
|
+
extension = infer_extension(metadata["mime_type"])
|
|
60
|
+
# ...
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.6.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## New features
|
|
6
|
+
|
|
7
|
+
* The S3 storage now accepts `:copy_options` when initializing. This can be used for supporting Cloudflare R2 by removing `:tagging_directive` when copying file from temporary to permanent storage.
|
|
8
|
+
|
|
9
|
+
```rb
|
|
10
|
+
Shrine::Storage::S3.new(bucket: BUCKET, copy_options: {}, **s3_options)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Other improvements
|
|
14
|
+
|
|
15
|
+
* Rack 3 is now supported.
|
|
16
|
+
|
|
17
|
+
* When duplicating the attacher, the `Attacher#context` hash is now copied as well, instead of being kept the same between the two attachers.
|
|
18
|
+
|
|
19
|
+
* After `UploadedFile#close` was called, `UploadedFile#opened?` will return `false` and the uploaded file can be implicitly re-opened again.
|
|
20
|
+
|
|
21
|
+
## Backwards compatibility
|
|
22
|
+
|
|
23
|
+
* Shrine API that is returning a rack response triple will now return headers as an instance of `Rack::Headers` on Rack 3, which is a subclass of `Hash`. This should keep user code that references header names in mixed case working (in addition to lowercase), but could theoretically cause issues for code explicitly requiring headers to be an instance of `Hash`.
|
data/doc/retrieving_uploads.md
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
id: retrieving-uploads
|
|
3
|
+
title: Retrieving Uploads
|
|
4
|
+
---
|
|
2
5
|
|
|
3
6
|
Uploaded file content is typically retrieved from the storage using a
|
|
4
7
|
`Shrine::UploadedFile` object. This guide explains the various methods of
|
|
@@ -121,7 +124,7 @@ end # underlying IO object is closed
|
|
|
121
124
|
```
|
|
122
125
|
|
|
123
126
|
`Shrine::UploadedFile#open` will return the result of a given block.
|
|
124
|
-
|
|
127
|
+
We can use that to safely retrieve the whole content of a file, without
|
|
125
128
|
leaving any temporary files lying around.
|
|
126
129
|
|
|
127
130
|
```rb
|
data/doc/securing_uploads.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
id: securing-uploads
|
|
3
|
+
title: Securing Uploads
|
|
4
|
+
---
|
|
2
5
|
|
|
3
6
|
Shrine does a lot to make your file uploads secure, but there are still a lot
|
|
4
7
|
of security measures that could be added by the user on the application's side.
|
|
5
|
-
This guide will try to cover
|
|
6
|
-
|
|
8
|
+
This guide will try to cover some well-known security issues, ranging from the
|
|
9
|
+
obvious ones to not-so-obvious ones, and try to provide solutions.
|
|
7
10
|
|
|
8
11
|
## Validate file type
|
|
9
12
|
|
|
@@ -12,17 +15,21 @@ idea to create a whitelist (or a blacklist) of extensions and MIME types.
|
|
|
12
15
|
|
|
13
16
|
By default Shrine stores the MIME type derived from the extension, which means
|
|
14
17
|
it's not guaranteed to hold the actual MIME type of the the file. However, you
|
|
15
|
-
can load the `determine_mime_type` plugin
|
|
16
|
-
|
|
18
|
+
can load the `determine_mime_type` plugin to determine MIME type from magic
|
|
19
|
+
file headers.
|
|
17
20
|
|
|
21
|
+
```rb
|
|
22
|
+
# Gemfile
|
|
23
|
+
gem "marcel", "~> 0.3"
|
|
24
|
+
```
|
|
18
25
|
```rb
|
|
19
26
|
class MyUploader < Shrine
|
|
27
|
+
plugin :determine_mime_type, analyzer: :marcel
|
|
20
28
|
plugin :validation_helpers
|
|
21
|
-
plugin :determine_mime_type
|
|
22
29
|
|
|
23
30
|
Attacher.validate do
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
validate_extension %w[jpg jpeg png webp]
|
|
32
|
+
validate_mime_type %w[image/jpeg image/png image/webp]
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
```
|
|
@@ -31,22 +38,23 @@ end
|
|
|
31
38
|
|
|
32
39
|
It's a good idea to generally limit the filesize of uploaded files, so that
|
|
33
40
|
attackers cannot easily flood your storage. There are various layers at which
|
|
34
|
-
you can apply filesize limits, depending on how you're accepting uploads.
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
you can apply filesize limits, depending on how you're accepting uploads. For
|
|
42
|
+
starters you can add a filesize validation to prevent large files from being
|
|
43
|
+
uploaded to `:store`:
|
|
37
44
|
|
|
38
45
|
```rb
|
|
39
46
|
class MyUploader < Shrine
|
|
40
47
|
plugin :validation_helpers
|
|
41
48
|
|
|
42
49
|
Attacher.validate do
|
|
43
|
-
validate_max_size
|
|
50
|
+
validate_max_size 100*1024*1024 # 100 MB
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
```
|
|
47
54
|
|
|
48
|
-
In the following sections we talk about various strategies to prevent files
|
|
49
|
-
being uploaded to
|
|
55
|
+
In the following sections we talk about various strategies to prevent files
|
|
56
|
+
from being uploaded to Shrine's temporary storage and the system's temporary
|
|
57
|
+
directory.
|
|
50
58
|
|
|
51
59
|
### Limiting filesize in direct uploads
|
|
52
60
|
|
|
@@ -55,7 +63,7 @@ in the `:max_size` option to reject files that are larger than the specified
|
|
|
55
63
|
limit:
|
|
56
64
|
|
|
57
65
|
```rb
|
|
58
|
-
plugin :upload_endpoint, max_size:
|
|
66
|
+
plugin :upload_endpoint, max_size: 100*1024*1024 # 100 MB
|
|
59
67
|
```
|
|
60
68
|
|
|
61
69
|
If you're doing direct uploads to Amazon S3 using the `presign_endpoint`
|
|
@@ -63,7 +71,7 @@ plugin, you can pass in the `:content_length_range` presign option:
|
|
|
63
71
|
|
|
64
72
|
```rb
|
|
65
73
|
plugin :presign_endpoint, presign_options: -> (request) do
|
|
66
|
-
{ content_length_range: 0..
|
|
74
|
+
{ content_length_range: 0..100*1024*1024 }
|
|
67
75
|
end
|
|
68
76
|
```
|
|
69
77
|
|
|
@@ -92,20 +100,17 @@ loading the `remove_invalid` plugin.
|
|
|
92
100
|
plugin :remove_invalid
|
|
93
101
|
```
|
|
94
102
|
|
|
95
|
-
###
|
|
103
|
+
### Failsafe filesize limiting
|
|
96
104
|
|
|
97
|
-
If you want to make sure that no large files ever get to your storages, and
|
|
98
|
-
|
|
99
|
-
and raise an error:
|
|
105
|
+
If you want to make sure that no large files ever get to your storages, and you
|
|
106
|
+
don't really care about the error message, you can override `Shrine#upload`:
|
|
100
107
|
|
|
101
108
|
```rb
|
|
102
|
-
class MyUploader
|
|
103
|
-
|
|
109
|
+
class MyUploader < Shrine
|
|
110
|
+
def upload(io, **options)
|
|
111
|
+
fail FileTooLarge if io.size >= 100*1024*1024
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
if io.respond_to?(:read)
|
|
107
|
-
raise FileTooLarge if io.size >= 20*1024*1024
|
|
108
|
-
end
|
|
113
|
+
super
|
|
109
114
|
end
|
|
110
115
|
end
|
|
111
116
|
```
|
|
@@ -118,24 +123,43 @@ image processing, since processing them can take a lot of time and memory. This
|
|
|
118
123
|
makes it trivial to DoS the application which doesn't have any protection
|
|
119
124
|
against them.
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
you still need to prevent those files from being attached and processed:
|
|
126
|
+
So, in addition to validating filesize, we should also validate image
|
|
127
|
+
dimensions:
|
|
124
128
|
|
|
125
129
|
```rb
|
|
126
|
-
|
|
130
|
+
# Gemfile
|
|
131
|
+
gem "fastimage"
|
|
132
|
+
```
|
|
133
|
+
```rb
|
|
134
|
+
class ImageUploader < Shrine
|
|
127
135
|
plugin :store_dimensions
|
|
128
136
|
plugin :validation_helpers
|
|
129
137
|
|
|
130
138
|
Attacher.validate do
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
validate_max_size 100*1024*1024
|
|
140
|
+
|
|
141
|
+
if validate_mime_type %w[image/jpeg image/png image/webp]
|
|
142
|
+
validate_max_dimensions [5000, 5000]
|
|
143
|
+
end
|
|
133
144
|
end
|
|
134
145
|
end
|
|
135
146
|
```
|
|
136
147
|
|
|
137
|
-
If you
|
|
138
|
-
|
|
148
|
+
If you want to be extra safe, you can add a failsafe before performing
|
|
149
|
+
processing:
|
|
150
|
+
|
|
151
|
+
```rb
|
|
152
|
+
class ImageUploader < Shrine
|
|
153
|
+
# ...
|
|
154
|
+
Attacher.derivatives do |original|
|
|
155
|
+
width, height = Shrine.dimensions(original)
|
|
156
|
+
|
|
157
|
+
fail ImageBombError if width > 5000 || height > 5000
|
|
158
|
+
|
|
159
|
+
# ...
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
```
|
|
139
163
|
|
|
140
164
|
## Prevent metadata tampering
|
|
141
165
|
|
|
@@ -153,7 +177,7 @@ app. To guard yourself from such attacks, you can load the
|
|
|
153
177
|
cached files on assignment and override the received metadata.
|
|
154
178
|
|
|
155
179
|
```rb
|
|
156
|
-
plugin :restore_cached_data
|
|
180
|
+
Shrine.plugin :restore_cached_data
|
|
157
181
|
```
|
|
158
182
|
|
|
159
183
|
## Limit number of files
|
|
@@ -172,6 +196,7 @@ class MyUploader < Shrine
|
|
|
172
196
|
|
|
173
197
|
Attacher.validate do
|
|
174
198
|
validate_min_size 10*1024 # 10 KB
|
|
199
|
+
# ...
|
|
175
200
|
end
|
|
176
201
|
end
|
|
177
202
|
```
|
|
@@ -183,6 +208,4 @@ end
|
|
|
183
208
|
* [AppSec: 8 Basic Rules to Implement Secure File Uploads](https://software-security.sans.org/blog/2009/12/28/8-basic-rules-to-implement-secure-file-uploads/)
|
|
184
209
|
|
|
185
210
|
[image bombs]: https://www.bamsoftware.com/hacks/deflate.html
|
|
186
|
-
[fastimage]: https://github.com/sdsykes/fastimage
|
|
187
|
-
[file]: http://linux.die.net/man/1/file
|
|
188
211
|
[rack-attack]: https://github.com/kickstarter/rack-attack
|