shrine 2.17.1 → 2.18.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -1
- data/README.md +527 -502
- data/doc/advantages.md +1 -3
- data/doc/attacher.md +22 -11
- data/doc/carrierwave.md +7 -8
- data/doc/design.md +1 -1
- data/doc/direct_s3.md +10 -15
- data/doc/metadata.md +11 -3
- data/doc/paperclip.md +1 -2
- data/doc/plugins/default_url_options.md +1 -1
- data/doc/plugins/derivation_endpoint.md +2 -1
- data/doc/plugins/download_endpoint.md +5 -13
- data/doc/plugins/parsed_json.md +12 -0
- data/doc/plugins/presign_endpoint.md +37 -8
- data/doc/plugins/upload_endpoint.md +72 -19
- data/doc/plugins/versions.md +1 -1
- data/doc/refile.md +6 -9
- data/doc/release_notes/2.17.0.md +2 -2
- data/doc/release_notes/2.18.0.md +155 -0
- data/doc/retrieving_uploads.md +45 -6
- data/doc/storage/s3.md +11 -12
- data/lib/shrine.rb +19 -5
- data/lib/shrine/attacher.rb +1 -1
- data/lib/shrine/plugins/data_uri.rb +1 -3
- data/lib/shrine/plugins/presign_endpoint.rb +21 -0
- data/lib/shrine/plugins/remote_url.rb +1 -3
- data/lib/shrine/plugins/remove_attachment.rb +1 -3
- data/lib/shrine/plugins/signature.rb +1 -2
- data/lib/shrine/plugins/upload_endpoint.rb +63 -10
- data/lib/shrine/storage/s3.rb +13 -18
- data/lib/shrine/version.rb +2 -2
- metadata +3 -2
@@ -7,11 +7,9 @@ class Shrine
|
|
7
7
|
# [doc/plugins/remove_attachment.md]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/remove_attachment.md
|
8
8
|
module RemoveAttachment
|
9
9
|
module AttachmentMethods
|
10
|
-
def initialize(
|
10
|
+
def initialize(name, **options)
|
11
11
|
super
|
12
12
|
|
13
|
-
name = attachment_name
|
14
|
-
|
15
13
|
define_method :"remove_#{name}=" do |value|
|
16
14
|
send(:"#{name}_attacher").remove = value
|
17
15
|
end
|
@@ -10,8 +10,7 @@ class Shrine
|
|
10
10
|
# Calculates `algorithm` hash of the contents of the IO object, and
|
11
11
|
# encodes it into `format`.
|
12
12
|
def calculate_signature(io, algorithm, format: :hex)
|
13
|
-
algorithm
|
14
|
-
SignatureCalculator.new(algorithm, format: format).call(io)
|
13
|
+
SignatureCalculator.new(algorithm.downcase, format: format).call(io)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
@@ -36,6 +36,27 @@ class Shrine
|
|
36
36
|
**options,
|
37
37
|
)
|
38
38
|
end
|
39
|
+
|
40
|
+
# Calls the upload endpoint passing the request information, and
|
41
|
+
# returns the Rack response triple.
|
42
|
+
#
|
43
|
+
# It performs the same mounting logic that Rack and other web
|
44
|
+
# frameworks use, and is meant for cases where statically mounting the
|
45
|
+
# endpoint in the router isn't enough.
|
46
|
+
def upload_response(storage_key, env, **options)
|
47
|
+
script_name = env["SCRIPT_NAME"]
|
48
|
+
path_info = env["PATH_INFO"]
|
49
|
+
|
50
|
+
begin
|
51
|
+
env["SCRIPT_NAME"] += path_info
|
52
|
+
env["PATH_INFO"] = ""
|
53
|
+
|
54
|
+
upload_endpoint(storage_key, **options).call(env)
|
55
|
+
ensure
|
56
|
+
env["SCRIPT_NAME"] = script_name
|
57
|
+
env["PATH_INFO"] = path_info
|
58
|
+
end
|
59
|
+
end
|
39
60
|
end
|
40
61
|
end
|
41
62
|
|
@@ -95,18 +116,30 @@ class Shrine
|
|
95
116
|
make_response(uploaded_file, request)
|
96
117
|
end
|
97
118
|
|
98
|
-
# Retrieves the
|
99
|
-
# IO-like object that can be passed to `Shrine#upload`.
|
119
|
+
# Retrieves the upload from the request and verifies it.
|
100
120
|
def get_io(request)
|
101
|
-
file = request
|
121
|
+
file = get_multipart_upload(request)
|
122
|
+
|
123
|
+
verify_size!(file, request)
|
124
|
+
verify_checksum!(file, request)
|
102
125
|
|
103
|
-
|
104
|
-
|
105
|
-
|
126
|
+
file
|
127
|
+
end
|
128
|
+
|
129
|
+
# Retrieves the file from "file" or "files[]" multipart POST param, and
|
130
|
+
# converts it into an IO-like object that can be passed to `Shrine#upload`.
|
131
|
+
def get_multipart_upload(request)
|
132
|
+
if request.params.key?("file")
|
133
|
+
value = request.params["file"]
|
134
|
+
elsif request.params["files"].is_a?(Array)
|
135
|
+
error!(400, "Too Many Files") if request.params["files"].count > 1
|
136
|
+
value = request.params["files"].first
|
137
|
+
end
|
106
138
|
|
107
|
-
|
139
|
+
error!(400, "Upload Not Found") if value.nil?
|
140
|
+
error!(400, "Upload Not Valid") unless value.is_a?(Hash) && value[:tempfile]
|
108
141
|
|
109
|
-
@shrine_class.rack_file(
|
142
|
+
@shrine_class.rack_file(value)
|
110
143
|
end
|
111
144
|
|
112
145
|
# Returns a hash of information containing `:action` and `:request`
|
@@ -137,12 +170,32 @@ class Shrine
|
|
137
170
|
if @rack_response
|
138
171
|
@rack_response.call(object, request)
|
139
172
|
else
|
140
|
-
|
173
|
+
if @url
|
174
|
+
url = case @url
|
175
|
+
when true then object.url
|
176
|
+
when Hash then object.url(**@url)
|
177
|
+
else @url.call(object, request)
|
178
|
+
end
|
179
|
+
|
180
|
+
body = { data: object, url: url }.to_json
|
181
|
+
else
|
182
|
+
body = object.to_json
|
183
|
+
end
|
184
|
+
|
185
|
+
[200, { "Content-Type" => CONTENT_TYPE_JSON }, [body]]
|
141
186
|
end
|
142
187
|
end
|
143
188
|
|
189
|
+
def verify_size!(file, request)
|
190
|
+
error!(413, "Upload Too Large") if @max_size && file.size > @max_size
|
191
|
+
end
|
192
|
+
|
144
193
|
# Verifies the provided checksum against the received file.
|
145
|
-
def verify_checksum!(file,
|
194
|
+
def verify_checksum!(file, request)
|
195
|
+
return unless request.env.key?("HTTP_CONTENT_MD5")
|
196
|
+
|
197
|
+
provided_checksum = request.env["HTTP_CONTENT_MD5"]
|
198
|
+
|
146
199
|
error!(400, "The Content-MD5 you specified was invalid") if provided_checksum.length != 24
|
147
200
|
|
148
201
|
calculated_checksum = Digest::MD5.file(file.path).base64digest
|
data/lib/shrine/storage/s3.rb
CHANGED
@@ -5,11 +5,13 @@ begin
|
|
5
5
|
require "aws-sdk-s3"
|
6
6
|
if Gem::Version.new(Aws::S3::GEM_VERSION) < Gem::Version.new("1.2.0")
|
7
7
|
raise "Shrine::Storage::S3 requires aws-sdk-s3 version 1.2.0 or above"
|
8
|
+
elsif Gem::Version.new(Aws::S3::GEM_VERSION) < Gem::Version.new("1.14.0")
|
9
|
+
Shrine.deprecation("Using aws-sdk-s3 < 1.14 is deprecated and support for it will be removed in Shrine 3. Update to aws-sdk-s3 version 1.14 or higher")
|
8
10
|
end
|
9
11
|
rescue LoadError => exception
|
10
12
|
begin
|
11
13
|
require "aws-sdk"
|
12
|
-
Shrine.deprecation("Using aws-sdk 2.x is deprecated and support for it will be removed in Shrine 3
|
14
|
+
Shrine.deprecation("Using aws-sdk 2.x is deprecated and support for it will be removed in Shrine 3. Use the new aws-sdk-s3 gem instead.")
|
13
15
|
Aws.eager_autoload!(services: ["S3"])
|
14
16
|
rescue LoadError
|
15
17
|
raise exception
|
@@ -115,8 +117,7 @@ class Shrine
|
|
115
117
|
if copyable?(io)
|
116
118
|
copy(io, id, **options)
|
117
119
|
else
|
118
|
-
|
119
|
-
shrine_metadata["size"] ||= bytes_uploaded
|
120
|
+
put(io, id, **options)
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
@@ -153,10 +154,9 @@ class Shrine
|
|
153
154
|
# typically useful for setting CDN hosts (e.g.
|
154
155
|
# `http://abc123.cloudfront.net`)
|
155
156
|
#
|
156
|
-
# :
|
157
|
-
# :
|
158
|
-
#
|
159
|
-
# download it.
|
157
|
+
# :public
|
158
|
+
# : Returns the unsigned URL to the S3 object. This requires the S3
|
159
|
+
# object to be public.
|
160
160
|
#
|
161
161
|
# All other options are forwarded to [`Aws::S3::Object#presigned_url`] or
|
162
162
|
# [`Aws::S3::Object#public_url`].
|
@@ -164,7 +164,10 @@ class Shrine
|
|
164
164
|
# [`Aws::S3::Object#presigned_url`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
|
165
165
|
# [`Aws::S3::Object#public_url`]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#public_url-instance_method
|
166
166
|
def url(id, download: nil, public: self.public, host: self.host, **options)
|
167
|
-
|
167
|
+
if download
|
168
|
+
Shrine.deprecation("The :download option in Shrine::Storage::S3#url is deprecated and will be removed in Shrine 3. Use the :response_content_disposition option directly, e.g. `response_content_disposition: \"attachment\"`.")
|
169
|
+
options[:response_content_disposition] ||= "attachment"
|
170
|
+
end
|
168
171
|
options[:response_content_disposition] = encode_content_disposition(options[:response_content_disposition]) if options[:response_content_disposition]
|
169
172
|
|
170
173
|
if public || signer
|
@@ -285,35 +288,27 @@ class Shrine
|
|
285
288
|
|
286
289
|
# Uploads the file to S3. Uses multipart upload for large files.
|
287
290
|
def put(io, id, **options)
|
288
|
-
bytes_uploaded = nil
|
289
|
-
|
290
291
|
if (path = extract_path(io))
|
291
292
|
# use `upload_file` for files because it can do multipart upload
|
292
293
|
options = { multipart_threshold: @multipart_threshold[:upload] }.merge!(options)
|
293
294
|
object(id).upload_file(path, **options)
|
294
|
-
bytes_uploaded = File.size(path)
|
295
295
|
else
|
296
296
|
io.to_io if io.is_a?(UploadedFile) # open if not already opened
|
297
297
|
|
298
298
|
if io.respond_to?(:size) && io.size && (io.size <= @multipart_threshold[:upload] || !object(id).respond_to?(:upload_stream))
|
299
299
|
object(id).put(body: io, **options)
|
300
|
-
bytes_uploaded = io.size
|
301
300
|
elsif object(id).respond_to?(:upload_stream)
|
302
301
|
# `upload_stream` uses multipart upload
|
303
302
|
object(id).upload_stream(tempfile: true, **options) do |write_stream|
|
304
|
-
|
303
|
+
IO.copy_stream(io, write_stream)
|
305
304
|
end
|
306
305
|
else
|
307
|
-
Shrine.deprecation "Uploading a file of unknown size with aws-sdk-s3 older than 1.14 is deprecated and will be removed in Shrine 3. Update to aws-sdk-s3 1.14 or higher."
|
308
|
-
|
309
306
|
Tempfile.create("shrine-s3", binmode: true) do |file|
|
310
|
-
|
307
|
+
IO.copy_stream(io, file.path)
|
311
308
|
object(id).upload_file(file.path, **options)
|
312
309
|
end
|
313
310
|
end
|
314
311
|
end
|
315
|
-
|
316
|
-
bytes_uploaded
|
317
312
|
end
|
318
313
|
|
319
314
|
# Aws::S3::Object#load doesn't support passing options to #head_object,
|
data/lib/shrine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shrine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: down
|
@@ -433,6 +433,7 @@ files:
|
|
433
433
|
- doc/release_notes/2.15.0.md
|
434
434
|
- doc/release_notes/2.16.0.md
|
435
435
|
- doc/release_notes/2.17.0.md
|
436
|
+
- doc/release_notes/2.18.0.md
|
436
437
|
- doc/release_notes/2.2.0.md
|
437
438
|
- doc/release_notes/2.3.0.md
|
438
439
|
- doc/release_notes/2.3.1.md
|