shrine 3.6.0 → 3.7.1
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 +24 -0
- data/doc/changing_derivatives.md +2 -1
- data/doc/changing_location.md +17 -5
- data/doc/getting_started.md +4 -2
- data/doc/plugins/derivation_endpoint.md +15 -1
- data/doc/plugins/derivatives.md +2 -1
- data/doc/plugins/download_endpoint.md +16 -4
- data/doc/plugins/rack_response.md +9 -0
- data/doc/plugins/refresh_metadata.md +20 -0
- data/doc/plugins/signature.md +8 -6
- data/doc/processing.md +5 -3
- data/doc/release_notes/3.7.0.md +75 -0
- data/doc/release_notes/3.7.1.md +13 -0
- data/lib/shrine/attacher.rb +21 -21
- data/lib/shrine/attachment.rb +2 -2
- data/lib/shrine/plugins/_persistence.rb +1 -1
- data/lib/shrine/plugins/_urlsafe_serialization.rb +4 -4
- data/lib/shrine/plugins/add_metadata.rb +2 -4
- data/lib/shrine/plugins/atomic_helpers.rb +7 -7
- data/lib/shrine/plugins/backgrounding.rb +9 -9
- data/lib/shrine/plugins/column.rb +6 -4
- data/lib/shrine/plugins/data_uri.rb +1 -1
- data/lib/shrine/plugins/default_url.rb +4 -4
- data/lib/shrine/plugins/delete_raw.rb +2 -2
- data/lib/shrine/plugins/derivation_endpoint.rb +29 -27
- data/lib/shrine/plugins/derivatives.rb +5 -1
- data/lib/shrine/plugins/download_endpoint.rb +62 -10
- data/lib/shrine/plugins/entity.rb +7 -7
- data/lib/shrine/plugins/infer_extension.rb +1 -1
- data/lib/shrine/plugins/instrumentation.rb +8 -8
- data/lib/shrine/plugins/metadata_attributes.rb +1 -1
- data/lib/shrine/plugins/mirroring.rb +10 -10
- data/lib/shrine/plugins/model.rb +9 -9
- data/lib/shrine/plugins/presign_endpoint.rb +4 -4
- data/lib/shrine/plugins/pretty_location.rb +2 -2
- data/lib/shrine/plugins/processing.rb +3 -3
- data/lib/shrine/plugins/rack_file.rb +2 -2
- data/lib/shrine/plugins/rack_response.rb +6 -6
- data/lib/shrine/plugins/refresh_metadata.rb +6 -6
- data/lib/shrine/plugins/remote_url.rb +4 -4
- data/lib/shrine/plugins/restore_cached_data.rb +3 -3
- data/lib/shrine/plugins/signature.rb +2 -2
- data/lib/shrine/plugins/store_dimensions.rb +2 -2
- data/lib/shrine/plugins/upload_endpoint.rb +4 -4
- data/lib/shrine/plugins/upload_options.rb +1 -1
- data/lib/shrine/plugins/validation.rb +8 -8
- data/lib/shrine/plugins/validation_helpers.rb +1 -1
- data/lib/shrine/plugins/versions.rb +10 -10
- data/lib/shrine/plugins.rb +6 -14
- data/lib/shrine/storage/file_system.rb +4 -17
- data/lib/shrine/storage/linter.rb +8 -8
- data/lib/shrine/storage/memory.rb +1 -3
- data/lib/shrine/storage/s3.rb +45 -37
- data/lib/shrine/uploaded_file.rb +20 -18
- data/lib/shrine/version.rb +2 -2
- data/lib/shrine.rb +18 -18
- data/shrine.gemspec +6 -6
- metadata +16 -17
|
@@ -67,19 +67,19 @@ class Shrine
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
# Does a background promote if promote block was registered.
|
|
70
|
-
def promote_cached(**
|
|
70
|
+
def promote_cached(**)
|
|
71
71
|
if promote? && promote_block
|
|
72
|
-
promote_background
|
|
72
|
+
promote_background(**)
|
|
73
73
|
else
|
|
74
74
|
super
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Calls the registered promote block.
|
|
79
|
-
def promote_background(**
|
|
79
|
+
def promote_background(**)
|
|
80
80
|
fail Error, "promote block is not registered" unless promote_block
|
|
81
81
|
|
|
82
|
-
background_block(promote_block, **
|
|
82
|
+
background_block(promote_block, **)
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
# Does a background destroy if destroy block was registered.
|
|
@@ -92,19 +92,19 @@ class Shrine
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# Calls the registered destroy block.
|
|
95
|
-
def destroy_background(**
|
|
95
|
+
def destroy_background(**)
|
|
96
96
|
fail Error, "destroy block is not registered" unless destroy_block
|
|
97
97
|
|
|
98
|
-
background_block(destroy_block, **
|
|
98
|
+
background_block(destroy_block, **)
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
private
|
|
102
102
|
|
|
103
|
-
def background_block(block, **
|
|
103
|
+
def background_block(block, **)
|
|
104
104
|
if block.arity == 1
|
|
105
|
-
block.call(self, **
|
|
105
|
+
block.call(self, **)
|
|
106
106
|
else
|
|
107
|
-
instance_exec(
|
|
107
|
+
instance_exec(**, &block)
|
|
108
108
|
end
|
|
109
109
|
end
|
|
110
110
|
end
|
|
@@ -16,8 +16,8 @@ class Shrine
|
|
|
16
16
|
# from a database record column.
|
|
17
17
|
#
|
|
18
18
|
# Attacher.from_column('{"id":"...","storage":"...","metadata":{...}}')
|
|
19
|
-
def from_column(data, **
|
|
20
|
-
attacher = new(**
|
|
19
|
+
def from_column(data, **)
|
|
20
|
+
attacher = new(**)
|
|
21
21
|
attacher.load_column(data)
|
|
22
22
|
attacher
|
|
23
23
|
end
|
|
@@ -28,8 +28,8 @@ class Shrine
|
|
|
28
28
|
attr_reader :column_serializer
|
|
29
29
|
|
|
30
30
|
# Allows overriding the default column serializer.
|
|
31
|
-
def initialize(column_serializer: shrine_class.opts[:column][:serializer], **
|
|
32
|
-
super(**
|
|
31
|
+
def initialize(column_serializer: shrine_class.opts[:column][:serializer], **)
|
|
32
|
+
super(**)
|
|
33
33
|
@column_serializer = column_serializer
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -75,6 +75,8 @@ class Shrine
|
|
|
75
75
|
# Attacher.deserialize_column(nil)
|
|
76
76
|
# #=> nil
|
|
77
77
|
def deserialize_column(data)
|
|
78
|
+
return nil if data == ""
|
|
79
|
+
|
|
78
80
|
if column_serializer && data && !data.is_a?(Hash)
|
|
79
81
|
column_serializer.load(data)
|
|
80
82
|
else
|
|
@@ -16,16 +16,16 @@ class Shrine
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
module AttacherMethods
|
|
19
|
-
def url(**
|
|
20
|
-
super || default_url(**
|
|
19
|
+
def url(**)
|
|
20
|
+
super || default_url(**)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
|
-
def default_url(**
|
|
25
|
+
def default_url(**)
|
|
26
26
|
return unless default_url_block
|
|
27
27
|
|
|
28
|
-
url = instance_exec(
|
|
28
|
+
url = instance_exec(**, &default_url_block)
|
|
29
29
|
|
|
30
30
|
[*default_url_host, url].join
|
|
31
31
|
end
|
|
@@ -15,8 +15,8 @@ class Shrine
|
|
|
15
15
|
private
|
|
16
16
|
|
|
17
17
|
# Deletes the file that was uploaded, unless it's an UploadedFile.
|
|
18
|
-
def _upload(io, delete: delete_raw?, **
|
|
19
|
-
super(io, delete
|
|
18
|
+
def _upload(io, delete: delete_raw?, **)
|
|
19
|
+
super(io, delete:, **)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def delete_raw?
|
|
@@ -48,7 +48,7 @@ class Shrine
|
|
|
48
48
|
# It uses a trick where it removes the derivation path prefix from the
|
|
49
49
|
# path info before calling the Rack app, which is what web framework
|
|
50
50
|
# routers do before they're calling a mounted Rack app.
|
|
51
|
-
def derivation_response(env, **
|
|
51
|
+
def derivation_response(env, **)
|
|
52
52
|
script_name = env["SCRIPT_NAME"]
|
|
53
53
|
path_info = env["PATH_INFO"]
|
|
54
54
|
|
|
@@ -61,7 +61,7 @@ class Shrine
|
|
|
61
61
|
env["SCRIPT_NAME"] += match.to_s
|
|
62
62
|
env["PATH_INFO"] = match.post_match
|
|
63
63
|
|
|
64
|
-
derivation_endpoint(**
|
|
64
|
+
derivation_endpoint(**).call(env)
|
|
65
65
|
ensure
|
|
66
66
|
env["SCRIPT_NAME"] = script_name
|
|
67
67
|
env["PATH_INFO"] = path_info
|
|
@@ -87,15 +87,15 @@ class Shrine
|
|
|
87
87
|
# Generates a URL to a derivation with the receiver as the source file.
|
|
88
88
|
# Any arguments provided will be included in the URL and passed to the
|
|
89
89
|
# derivation block. Accepts additional URL options.
|
|
90
|
-
def derivation_url(name,
|
|
91
|
-
derivation(name, *
|
|
90
|
+
def derivation_url(name, *, **)
|
|
91
|
+
derivation(name, *).url(**)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# Calls the specified derivation with the receiver as the source file,
|
|
95
95
|
# returning a Rack response triple. The derivation endpoint ultimately
|
|
96
96
|
# calls this method.
|
|
97
|
-
def derivation_response(name,
|
|
98
|
-
derivation(name,
|
|
97
|
+
def derivation_response(name, *, env:, **)
|
|
98
|
+
derivation(name, *, **).response(env)
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
# Returns a Shrine::Derivation object created from the provided
|
|
@@ -129,14 +129,14 @@ class Shrine
|
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
# Returns an URL to the derivation.
|
|
132
|
-
def url(**
|
|
132
|
+
def url(**)
|
|
133
133
|
Derivation::Url.new(self).call(
|
|
134
134
|
host: option(:host),
|
|
135
135
|
prefix: option(:prefix),
|
|
136
136
|
expires_in: option(:expires_in),
|
|
137
137
|
version: option(:version),
|
|
138
138
|
metadata: option(:metadata),
|
|
139
|
-
|
|
139
|
+
**,
|
|
140
140
|
)
|
|
141
141
|
end
|
|
142
142
|
|
|
@@ -158,8 +158,8 @@ class Shrine
|
|
|
158
158
|
|
|
159
159
|
# Uploads the derivation result to a dedicated destination on the specified
|
|
160
160
|
# Shrine storage.
|
|
161
|
-
def upload(file = nil, **
|
|
162
|
-
Derivation::Upload.new(self).call(file, **
|
|
161
|
+
def upload(file = nil, **)
|
|
162
|
+
Derivation::Upload.new(self).call(file, **)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
# Returns a Shrine::UploadedFile object pointing to the uploaded derivative
|
|
@@ -184,7 +184,7 @@ class Shrine
|
|
|
184
184
|
end
|
|
185
185
|
|
|
186
186
|
def self.option(name, default: nil, result: nil)
|
|
187
|
-
options[name] = { default
|
|
187
|
+
options[name] = { default:, result: }
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
option :cache_control, default: -> { default_cache_control }
|
|
@@ -303,27 +303,28 @@ class Shrine
|
|
|
303
303
|
class Derivation::Url < Derivation::Command
|
|
304
304
|
delegate :name, :args, :source, :secret_key, :signer
|
|
305
305
|
|
|
306
|
-
def call(host: nil, prefix: nil, **
|
|
306
|
+
def call(host: nil, prefix: nil, metadata: [], format: nil, **)
|
|
307
307
|
base_url = [host, *prefix].join("/")
|
|
308
|
-
path = path_identifier(metadata
|
|
308
|
+
path = path_identifier(metadata:, format:)
|
|
309
309
|
|
|
310
310
|
if signer
|
|
311
311
|
url = [base_url, path].join("/")
|
|
312
|
-
signer.call(url, **
|
|
312
|
+
signer.call(url, **)
|
|
313
313
|
else
|
|
314
|
-
signed_part = signed_url("#{path}?#{query(**
|
|
314
|
+
signed_part = signed_url("#{path}?#{query(**)}")
|
|
315
315
|
[base_url, signed_part].join("/")
|
|
316
316
|
end
|
|
317
317
|
end
|
|
318
318
|
|
|
319
319
|
private
|
|
320
320
|
|
|
321
|
-
def path_identifier(metadata: [])
|
|
322
|
-
[
|
|
321
|
+
def path_identifier(metadata: [], format: nil)
|
|
322
|
+
path = [
|
|
323
323
|
name,
|
|
324
324
|
*args,
|
|
325
|
-
source.urlsafe_dump(metadata:
|
|
325
|
+
source.urlsafe_dump(metadata:)
|
|
326
326
|
].map{|component| Rack::Utils.escape_path(component.to_s)}.join('/')
|
|
327
|
+
format ? "#{path}.#{format}" : path
|
|
327
328
|
end
|
|
328
329
|
|
|
329
330
|
def query(expires_in: nil,
|
|
@@ -386,6 +387,7 @@ class Shrine
|
|
|
386
387
|
check_expiry!(request)
|
|
387
388
|
|
|
388
389
|
name, *args, serialized_file = request.path_info.split("/")[1..-1]
|
|
390
|
+
serialized_file = serialized_file.sub(/\.\w+$/, "")
|
|
389
391
|
|
|
390
392
|
name = name.to_sym
|
|
391
393
|
uploaded_file = shrine_class::UploadedFile.urlsafe_load(serialized_file)
|
|
@@ -558,7 +560,7 @@ class Shrine
|
|
|
558
560
|
filename = self.filename
|
|
559
561
|
filename += File.extname(file.path) if File.extname(filename).empty?
|
|
560
562
|
|
|
561
|
-
ContentDisposition.format(disposition
|
|
563
|
+
ContentDisposition.format(disposition:, filename:)
|
|
562
564
|
end
|
|
563
565
|
end
|
|
564
566
|
|
|
@@ -597,9 +599,9 @@ class Shrine
|
|
|
597
599
|
end
|
|
598
600
|
|
|
599
601
|
# Calls the derivation block.
|
|
600
|
-
def derive(*
|
|
602
|
+
def derive(*)
|
|
601
603
|
instrument_derivation do
|
|
602
|
-
derivation.instance_exec(
|
|
604
|
+
derivation.instance_exec(*, &derivation_block)
|
|
603
605
|
end
|
|
604
606
|
end
|
|
605
607
|
|
|
@@ -607,7 +609,7 @@ class Shrine
|
|
|
607
609
|
def instrument_derivation(&block)
|
|
608
610
|
return yield unless shrine_class.respond_to?(:instrument)
|
|
609
611
|
|
|
610
|
-
shrine_class.instrument(:derivation, { derivation:
|
|
612
|
+
shrine_class.instrument(:derivation, { derivation: }, &block)
|
|
611
613
|
end
|
|
612
614
|
|
|
613
615
|
# Massages the derivation result, ensuring it's opened in binary mode,
|
|
@@ -646,22 +648,22 @@ class Shrine
|
|
|
646
648
|
# Uploads the derivation result to the dedicated location on the storage.
|
|
647
649
|
# If a file object is given, uploads that to the storage, otherwise calls
|
|
648
650
|
# the derivation block and uploads the result.
|
|
649
|
-
def call(derivative = nil, **
|
|
651
|
+
def call(derivative = nil, **)
|
|
650
652
|
if derivative
|
|
651
|
-
upload(derivative, **
|
|
653
|
+
upload(derivative, **)
|
|
652
654
|
else
|
|
653
|
-
upload(derivation.generate, delete: true, **
|
|
655
|
+
upload(derivation.generate, delete: true, **)
|
|
654
656
|
end
|
|
655
657
|
end
|
|
656
658
|
|
|
657
659
|
private
|
|
658
660
|
|
|
659
|
-
def upload(io, **
|
|
661
|
+
def upload(io, **)
|
|
660
662
|
shrine_class.upload io, upload_storage,
|
|
661
663
|
location: upload_location,
|
|
662
664
|
upload_options: upload_options,
|
|
663
665
|
action: :derivation,
|
|
664
|
-
**
|
|
666
|
+
**
|
|
665
667
|
end
|
|
666
668
|
end
|
|
667
669
|
|
|
@@ -459,9 +459,13 @@ class Shrine
|
|
|
459
459
|
# attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
|
|
460
460
|
# attacher.change(file)
|
|
461
461
|
# attacher.derivatives #=> {}
|
|
462
|
+
#
|
|
463
|
+
# # With keep_derivatives: true
|
|
464
|
+
# attacher.change(file)
|
|
465
|
+
# attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
|
|
462
466
|
def change(*)
|
|
463
467
|
result = super
|
|
464
|
-
set_derivatives({})
|
|
468
|
+
set_derivatives({}) unless shrine_class.derivatives_options[:keep_derivatives]
|
|
465
469
|
result
|
|
466
470
|
end
|
|
467
471
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'openssl'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
3
6
|
class Shrine
|
|
4
7
|
module Plugins
|
|
5
8
|
# Documentation can be found on https://shrinerb.com/docs/plugins/download_endpoint
|
|
@@ -16,11 +19,11 @@ class Shrine
|
|
|
16
19
|
|
|
17
20
|
module ClassMethods
|
|
18
21
|
# Returns the Rack application that retrieves requested files.
|
|
19
|
-
def download_endpoint(**
|
|
22
|
+
def download_endpoint(**)
|
|
20
23
|
Shrine::DownloadEndpoint.new(
|
|
21
24
|
shrine_class: self,
|
|
22
25
|
**opts[:download_endpoint],
|
|
23
|
-
|
|
26
|
+
**,
|
|
24
27
|
)
|
|
25
28
|
end
|
|
26
29
|
|
|
@@ -30,7 +33,7 @@ class Shrine
|
|
|
30
33
|
# It uses a trick where it removes the download path prefix from the
|
|
31
34
|
# path info before calling the Rack app, which is what web framework
|
|
32
35
|
# routers do before they're calling a mounted Rack app.
|
|
33
|
-
def download_response(env, **
|
|
36
|
+
def download_response(env, **)
|
|
34
37
|
script_name = env["SCRIPT_NAME"]
|
|
35
38
|
path_info = env["PATH_INFO"]
|
|
36
39
|
|
|
@@ -43,7 +46,7 @@ class Shrine
|
|
|
43
46
|
env["SCRIPT_NAME"] += match.to_s
|
|
44
47
|
env["PATH_INFO"] = match.post_match
|
|
45
48
|
|
|
46
|
-
download_endpoint(**
|
|
49
|
+
download_endpoint(**).call(env)
|
|
47
50
|
ensure
|
|
48
51
|
env["SCRIPT_NAME"] = script_name
|
|
49
52
|
env["PATH_INFO"] = path_info
|
|
@@ -53,8 +56,8 @@ class Shrine
|
|
|
53
56
|
|
|
54
57
|
module FileMethods
|
|
55
58
|
# Returns file URL on the download endpoint.
|
|
56
|
-
def download_url(**
|
|
57
|
-
FileUrl.new(self).call(**
|
|
59
|
+
def download_url(**)
|
|
60
|
+
FileUrl.new(self).call(**)
|
|
58
61
|
end
|
|
59
62
|
end
|
|
60
63
|
|
|
@@ -65,14 +68,36 @@ class Shrine
|
|
|
65
68
|
@file = file
|
|
66
69
|
end
|
|
67
70
|
|
|
68
|
-
def call(host: self.host)
|
|
69
|
-
[
|
|
71
|
+
def call(host: self.host, expires_in: nil)
|
|
72
|
+
path = file.urlsafe_dump(metadata: %w[filename size mime_type])
|
|
73
|
+
|
|
74
|
+
query = signature_as_query(path: path, expires_in: expires_in)
|
|
75
|
+
|
|
76
|
+
path = [host, *prefix, path].join("/")
|
|
77
|
+
path += "?#{query}" if query
|
|
78
|
+
path
|
|
70
79
|
end
|
|
71
80
|
|
|
72
81
|
protected
|
|
73
82
|
|
|
74
|
-
def path
|
|
75
|
-
|
|
83
|
+
def signature_as_query(path:, expires_in:)
|
|
84
|
+
expires_in = default_expires_in if expires_in.nil?
|
|
85
|
+
raise(Error, "secret_key is required for expiring URLs") if !secret_key && expires_in
|
|
86
|
+
raise(Error, "expires_in is required for expiring URLs") if secret_key && !expires_in
|
|
87
|
+
|
|
88
|
+
return nil unless expires_in
|
|
89
|
+
|
|
90
|
+
expires_at = (Time.now + expires_in).to_i
|
|
91
|
+
signature = OpenSSL::HMAC.digest(
|
|
92
|
+
OpenSSL::Digest::SHA256.new,
|
|
93
|
+
secret_key,
|
|
94
|
+
"#{path}--#{expires_at}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
Rack::Utils.build_query(
|
|
98
|
+
signature: Base64.urlsafe_encode64(signature),
|
|
99
|
+
expires_at: expires_at
|
|
100
|
+
)
|
|
76
101
|
end
|
|
77
102
|
|
|
78
103
|
def host
|
|
@@ -83,6 +108,14 @@ class Shrine
|
|
|
83
108
|
options[:prefix]
|
|
84
109
|
end
|
|
85
110
|
|
|
111
|
+
def default_expires_in
|
|
112
|
+
options[:expires_in]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def secret_key
|
|
116
|
+
options[:secret_key]
|
|
117
|
+
end
|
|
118
|
+
|
|
86
119
|
def options
|
|
87
120
|
file.shrine_class.opts[:download_endpoint]
|
|
88
121
|
end
|
|
@@ -129,6 +162,9 @@ class Shrine
|
|
|
129
162
|
|
|
130
163
|
def handle_request(request)
|
|
131
164
|
_, serialized, * = request.path_info.split("/")
|
|
165
|
+
signature, expires_at = request.params.values_at("signature", "expires_at")
|
|
166
|
+
|
|
167
|
+
check_signature!(serialized, signature, expires_at) if @secret_key
|
|
132
168
|
|
|
133
169
|
uploaded_file = get_uploaded_file(serialized)
|
|
134
170
|
|
|
@@ -189,6 +225,22 @@ class Shrine
|
|
|
189
225
|
bad_request!("Invalid serialized file")
|
|
190
226
|
end
|
|
191
227
|
|
|
228
|
+
def check_signature!(serialized, signature, expires_at)
|
|
229
|
+
if expires_at && expires_at.to_i < Time.now.to_i
|
|
230
|
+
error!(400, "URL has expired")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
calculated_signature = OpenSSL::HMAC.digest(
|
|
234
|
+
OpenSSL::Digest::SHA256.new,
|
|
235
|
+
@secret_key,
|
|
236
|
+
"#{serialized}--#{expires_at}"
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
if !Rack::Utils.secure_compare(signature, Base64.urlsafe_encode64(calculated_signature))
|
|
240
|
+
error!(403, "Signature does not match")
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
192
244
|
def not_found!
|
|
193
245
|
error!(404, "File Not Found")
|
|
194
246
|
end
|
|
@@ -10,7 +10,7 @@ class Shrine
|
|
|
10
10
|
|
|
11
11
|
module AttachmentMethods
|
|
12
12
|
# Defines instance methods on initialization.
|
|
13
|
-
def initialize(name, **
|
|
13
|
+
def initialize(name, **)
|
|
14
14
|
super
|
|
15
15
|
|
|
16
16
|
define_entity_methods(name)
|
|
@@ -59,16 +59,16 @@ class Shrine
|
|
|
59
59
|
|
|
60
60
|
# Returns the class attacher instance with loaded entity. It's not
|
|
61
61
|
# memoized because the entity object could be frozen.
|
|
62
|
-
def attacher(record, **
|
|
63
|
-
attacher = class_attacher(**
|
|
62
|
+
def attacher(record, **)
|
|
63
|
+
attacher = class_attacher(**)
|
|
64
64
|
attacher.load_entity(record, @name)
|
|
65
65
|
attacher
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# Creates an instance of the corresponding attacher class with set
|
|
69
69
|
# name.
|
|
70
|
-
def class_attacher(**
|
|
71
|
-
attacher = shrine_class::Attacher.new(**@options, **
|
|
70
|
+
def class_attacher(**)
|
|
71
|
+
attacher = shrine_class::Attacher.new(**@options, **)
|
|
72
72
|
attacher.instance_variable_set(:@name, @name)
|
|
73
73
|
attacher
|
|
74
74
|
end
|
|
@@ -81,8 +81,8 @@ class Shrine
|
|
|
81
81
|
#
|
|
82
82
|
# attacher = Attacher.from_entity(photo, :image)
|
|
83
83
|
# attacher.file #=> #<Shrine::UploadedFile>
|
|
84
|
-
def from_entity(record, name, **
|
|
85
|
-
attacher = new(**
|
|
84
|
+
def from_entity(record, name, **)
|
|
85
|
+
attacher = new(**)
|
|
86
86
|
attacher.load_entity(record, name)
|
|
87
87
|
attacher
|
|
88
88
|
end
|
|
@@ -169,14 +169,14 @@ class Shrine
|
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
-
def library_send(method_name,
|
|
172
|
+
def library_send(method_name, ...)
|
|
173
173
|
case notifications.to_s
|
|
174
174
|
when /Dry::Monitor::Notifications/
|
|
175
|
-
send(:"dry_monitor_#{method_name}",
|
|
175
|
+
send(:"dry_monitor_#{method_name}", ...)
|
|
176
176
|
when /ActiveSupport::Notifications/
|
|
177
|
-
send(:"active_support_#{method_name}",
|
|
177
|
+
send(:"active_support_#{method_name}", ...)
|
|
178
178
|
else
|
|
179
|
-
notifications.send(method_name,
|
|
179
|
+
notifications.send(method_name, ...)
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
182
|
end
|
|
@@ -224,14 +224,14 @@ class Shrine
|
|
|
224
224
|
event.duration.to_i
|
|
225
225
|
end
|
|
226
226
|
|
|
227
|
-
def library_send(method_name,
|
|
227
|
+
def library_send(method_name, ...)
|
|
228
228
|
case event.class.name
|
|
229
229
|
when "ActiveSupport::Notifications::Event"
|
|
230
|
-
send(:"active_support_#{method_name}",
|
|
230
|
+
send(:"active_support_#{method_name}", ...)
|
|
231
231
|
when "Dry::Events::Event"
|
|
232
|
-
send(:"dry_events_#{method_name}",
|
|
232
|
+
send(:"dry_events_#{method_name}", ...)
|
|
233
233
|
else
|
|
234
|
-
event.send(method_name,
|
|
234
|
+
event.send(method_name, ...)
|
|
235
235
|
end
|
|
236
236
|
end
|
|
237
237
|
end
|
|
@@ -51,9 +51,9 @@ class Shrine
|
|
|
51
51
|
|
|
52
52
|
module InstanceMethods
|
|
53
53
|
# Mirrors upload to other mirror storages.
|
|
54
|
-
def upload(io, mirror: true, **
|
|
55
|
-
file = super(io, **
|
|
56
|
-
file.trigger_mirror_upload(**
|
|
54
|
+
def upload(io, mirror: true, **)
|
|
55
|
+
file = super(io, **)
|
|
56
|
+
file.trigger_mirror_upload(**) if mirror
|
|
57
57
|
file
|
|
58
58
|
end
|
|
59
59
|
end
|
|
@@ -61,31 +61,31 @@ class Shrine
|
|
|
61
61
|
module FileMethods
|
|
62
62
|
# Mirrors upload if mirrors are defined. Calls mirror block if
|
|
63
63
|
# registered, otherwise mirrors synchronously.
|
|
64
|
-
def trigger_mirror_upload(**
|
|
64
|
+
def trigger_mirror_upload(**)
|
|
65
65
|
return unless shrine_class.mirrors[storage_key] && shrine_class.mirror_upload?
|
|
66
66
|
|
|
67
67
|
if shrine_class.mirror_upload_block
|
|
68
|
-
mirror_upload_background(**
|
|
68
|
+
mirror_upload_background(**)
|
|
69
69
|
else
|
|
70
|
-
mirror_upload(**
|
|
70
|
+
mirror_upload(**)
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
# Calls mirror upload block.
|
|
75
|
-
def mirror_upload_background(**
|
|
75
|
+
def mirror_upload_background(**)
|
|
76
76
|
fail Error, "mirror upload block is not registered" unless shrine_class.mirror_upload_block
|
|
77
77
|
|
|
78
|
-
shrine_class.mirror_upload_block.call(self, **
|
|
78
|
+
shrine_class.mirror_upload_block.call(self, **)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
# Uploads the file to each mirror storage.
|
|
82
|
-
def mirror_upload(**
|
|
82
|
+
def mirror_upload(**)
|
|
83
83
|
previously_opened = opened?
|
|
84
84
|
|
|
85
85
|
each_mirror do |mirror|
|
|
86
86
|
rewind if opened?
|
|
87
87
|
|
|
88
|
-
shrine_class.upload(self, mirror,
|
|
88
|
+
shrine_class.upload(self, mirror, **, location: id, close: false, action: :mirror)
|
|
89
89
|
end
|
|
90
90
|
ensure
|
|
91
91
|
if opened? && !previously_opened
|
data/lib/shrine/plugins/model.rb
CHANGED
|
@@ -18,8 +18,8 @@ class Shrine
|
|
|
18
18
|
#
|
|
19
19
|
# Shrine::Attachment(:image) # model (default)
|
|
20
20
|
# Shrine::Attachment(:image, model: false) # entity
|
|
21
|
-
def initialize(name, model: true, **
|
|
22
|
-
super(name, **
|
|
21
|
+
def initialize(name, model: true, **)
|
|
22
|
+
super(name, **)
|
|
23
23
|
@model = model
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -82,16 +82,16 @@ class Shrine
|
|
|
82
82
|
#
|
|
83
83
|
# attacher = Attacher.from_model(photo, :image)
|
|
84
84
|
# attacher.file #=> #<Shrine::UploadedFile>
|
|
85
|
-
def from_model(record, name, **
|
|
86
|
-
attacher = new(**
|
|
85
|
+
def from_model(record, name, **)
|
|
86
|
+
attacher = new(**)
|
|
87
87
|
attacher.load_model(record, name)
|
|
88
88
|
attacher
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
module AttacherMethods
|
|
93
|
-
def initialize(model_cache: shrine_class.opts[:model][:cache], **
|
|
94
|
-
super(**
|
|
93
|
+
def initialize(model_cache: shrine_class.opts[:model][:cache], **)
|
|
94
|
+
super(**)
|
|
95
95
|
@model_cache = model_cache
|
|
96
96
|
@model = nil
|
|
97
97
|
end
|
|
@@ -111,11 +111,11 @@ class Shrine
|
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
# Called by the attachment attribute setter on the model.
|
|
114
|
-
def model_assign(value, **
|
|
114
|
+
def model_assign(value, **)
|
|
115
115
|
if model_cache?
|
|
116
|
-
assign(value, **
|
|
116
|
+
assign(value, **)
|
|
117
117
|
else
|
|
118
|
-
attach(value, **
|
|
118
|
+
attach(value, **)
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|