paperclip 4.2.2 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +3 -0
- data/.hound.yml +1055 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +17 -15
- data/Appraisals +4 -16
- data/CONTRIBUTING.md +19 -8
- data/Gemfile +5 -9
- data/LICENSE +1 -1
- data/MIGRATING-ES.md +317 -0
- data/MIGRATING.md +375 -0
- data/NEWS +184 -31
- data/README.md +371 -201
- data/RELEASING.md +17 -0
- data/Rakefile +2 -2
- data/UPGRADING +12 -9
- data/features/basic_integration.feature +10 -6
- data/features/migration.feature +0 -24
- data/features/step_definitions/attachment_steps.rb +41 -35
- data/features/step_definitions/html_steps.rb +2 -2
- data/features/step_definitions/rails_steps.rb +39 -38
- data/features/step_definitions/s3_steps.rb +2 -2
- data/features/step_definitions/web_steps.rb +1 -103
- data/features/support/env.rb +1 -0
- data/features/support/file_helpers.rb +2 -2
- data/features/support/paths.rb +1 -1
- data/features/support/rails.rb +0 -24
- data/gemfiles/4.2.gemfile +6 -8
- data/gemfiles/5.0.gemfile +17 -0
- data/lib/generators/paperclip/paperclip_generator.rb +9 -1
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip/attachment.rb +51 -26
- data/lib/paperclip/attachment_registry.rb +3 -2
- data/lib/paperclip/callbacks.rb +8 -6
- data/lib/paperclip/content_type_detector.rb +27 -11
- data/lib/paperclip/errors.rb +3 -1
- data/lib/paperclip/file_command_content_type_detector.rb +6 -8
- data/lib/paperclip/filename_cleaner.rb +0 -1
- data/lib/paperclip/geometry_detector_factory.rb +3 -3
- data/lib/paperclip/geometry_parser_factory.rb +1 -1
- data/lib/paperclip/glue.rb +1 -1
- data/lib/paperclip/has_attached_file.rb +9 -2
- data/lib/paperclip/helpers.rb +15 -11
- data/lib/paperclip/interpolations/plural_cache.rb +6 -5
- data/lib/paperclip/interpolations.rb +24 -14
- data/lib/paperclip/io_adapters/abstract_adapter.rb +32 -4
- data/lib/paperclip/io_adapters/attachment_adapter.rb +17 -6
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +8 -8
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
- data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +8 -7
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
- data/lib/paperclip/io_adapters/registry.rb +6 -2
- data/lib/paperclip/io_adapters/stringio_adapter.rb +9 -6
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
- data/lib/paperclip/io_adapters/uri_adapter.rb +43 -19
- data/lib/paperclip/logger.rb +1 -1
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +13 -9
- data/lib/paperclip/processor.rb +15 -6
- data/lib/paperclip/rails_environment.rb +25 -0
- data/lib/paperclip/schema.rb +4 -10
- data/lib/paperclip/storage/filesystem.rb +13 -2
- data/lib/paperclip/storage/fog.rb +33 -20
- data/lib/paperclip/storage/s3.rb +89 -70
- data/lib/paperclip/style.rb +0 -1
- data/lib/paperclip/thumbnail.rb +24 -12
- data/lib/paperclip/url_generator.rb +17 -13
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
- data/lib/paperclip/validators.rb +1 -1
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +27 -13
- data/lib/tasks/paperclip.rake +33 -3
- data/paperclip.gemspec +18 -15
- data/spec/paperclip/attachment_definitions_spec.rb +1 -1
- data/spec/paperclip/attachment_processing_spec.rb +2 -5
- data/spec/paperclip/attachment_registry_spec.rb +84 -13
- data/spec/paperclip/attachment_spec.rb +147 -41
- data/spec/paperclip/content_type_detector_spec.rb +9 -2
- data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -2
- data/spec/paperclip/filename_cleaner_spec.rb +0 -1
- data/spec/paperclip/geometry_spec.rb +1 -1
- data/spec/paperclip/glue_spec.rb +44 -0
- data/spec/paperclip/has_attached_file_spec.rb +24 -8
- data/spec/paperclip/integration_spec.rb +42 -5
- data/spec/paperclip/interpolations_spec.rb +21 -9
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +106 -23
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +6 -3
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +7 -1
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +6 -3
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +51 -14
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/registry_spec.rb +2 -2
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +5 -1
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +5 -5
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +126 -8
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +1 -1
- data/spec/paperclip/media_type_spoof_detector_spec.rb +75 -11
- data/spec/paperclip/paperclip_spec.rb +15 -40
- data/spec/paperclip/plural_cache_spec.rb +17 -16
- data/spec/paperclip/processor_spec.rb +4 -4
- data/spec/paperclip/rails_environment_spec.rb +33 -0
- data/spec/paperclip/schema_spec.rb +46 -46
- data/spec/paperclip/storage/fog_spec.rb +63 -3
- data/spec/paperclip/storage/s3_live_spec.rb +20 -14
- data/spec/paperclip/storage/s3_spec.rb +400 -215
- data/spec/paperclip/style_spec.rb +0 -1
- data/spec/paperclip/tempfile_factory_spec.rb +4 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +59 -38
- data/spec/paperclip/url_generator_spec.rb +55 -45
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
- data/spec/paperclip/validators_spec.rb +5 -5
- data/spec/spec_helper.rb +7 -1
- data/spec/support/assertions.rb +12 -1
- data/spec/support/fake_model.rb +4 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/matchers/have_column.rb +11 -2
- data/spec/support/mock_attachment.rb +2 -0
- data/spec/support/mock_url_generator_builder.rb +2 -2
- data/spec/support/model_reconstruction.rb +11 -3
- data/spec/support/reporting.rb +11 -0
- metadata +110 -63
- data/RUNNING_TESTS.md +0 -4
- data/cucumber/paperclip_steps.rb +0 -6
- data/gemfiles/3.2.gemfile +0 -19
- data/gemfiles/4.0.gemfile +0 -19
- data/gemfiles/4.1.gemfile +0 -19
- data/lib/paperclip/locales/de.yml +0 -18
- data/lib/paperclip/locales/es.yml +0 -18
- data/lib/paperclip/locales/ja.yml +0 -18
- data/lib/paperclip/locales/pt-BR.yml +0 -18
- data/lib/paperclip/locales/zh-CN.yml +0 -18
- data/lib/paperclip/locales/zh-HK.yml +0 -18
- data/lib/paperclip/locales/zh-TW.yml +0 -18
- data/spec/support/mock_model.rb +0 -2
- data/spec/support/rails_helpers.rb +0 -7
@@ -1,19 +1,22 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "aws-sdk-s3"
|
3
3
|
|
4
4
|
describe Paperclip::Storage::S3 do
|
5
5
|
before do
|
6
|
-
|
6
|
+
Aws.config[:stub_responses] = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def aws2_add_region
|
10
|
+
{ s3_region: 'us-east-1' }
|
7
11
|
end
|
8
12
|
|
9
13
|
context "Parsing S3 credentials" do
|
10
14
|
before do
|
11
15
|
@proxy_settings = {host: "127.0.0.1", port: 8888, user: "foo", password: "bar"}
|
12
|
-
rebuild_model storage: :s3,
|
16
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
13
17
|
bucket: "testing",
|
14
18
|
http_proxy: @proxy_settings,
|
15
19
|
s3_credentials: {not: :important}
|
16
|
-
|
17
20
|
@dummy = Dummy.new
|
18
21
|
@avatar = @dummy.avatar
|
19
22
|
end
|
@@ -55,7 +58,8 @@ describe Paperclip::Storage::S3 do
|
|
55
58
|
context ":bucket option via :s3_credentials" do
|
56
59
|
|
57
60
|
before do
|
58
|
-
rebuild_model storage: :s3,
|
61
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
62
|
+
s3_credentials: {bucket: 'testing'}
|
59
63
|
@dummy = Dummy.new
|
60
64
|
end
|
61
65
|
|
@@ -68,7 +72,8 @@ describe Paperclip::Storage::S3 do
|
|
68
72
|
context ":bucket option" do
|
69
73
|
|
70
74
|
before do
|
71
|
-
rebuild_model storage: :s3,
|
75
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
76
|
+
bucket: "testing", s3_credentials: {}
|
72
77
|
@dummy = Dummy.new
|
73
78
|
end
|
74
79
|
|
@@ -81,7 +86,7 @@ describe Paperclip::Storage::S3 do
|
|
81
86
|
context "missing :bucket option" do
|
82
87
|
|
83
88
|
before do
|
84
|
-
rebuild_model storage: :s3,
|
89
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
85
90
|
http_proxy: @proxy_settings,
|
86
91
|
s3_credentials: {not: :important}
|
87
92
|
|
@@ -98,17 +103,18 @@ describe Paperclip::Storage::S3 do
|
|
98
103
|
|
99
104
|
context "" do
|
100
105
|
before do
|
101
|
-
rebuild_model storage: :s3,
|
106
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
102
107
|
s3_credentials: {},
|
103
108
|
bucket: "bucket",
|
104
109
|
path: ":attachment/:basename:dotextension",
|
105
110
|
url: ":s3_path_url"
|
106
111
|
@dummy = Dummy.new
|
107
112
|
@dummy.avatar = stringy_file
|
113
|
+
@dummy.stubs(:new_record?).returns(false)
|
108
114
|
end
|
109
115
|
|
110
116
|
it "returns a url based on an S3 path" do
|
111
|
-
assert_match %r{
|
117
|
+
assert_match %r{^//s3.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
|
112
118
|
end
|
113
119
|
|
114
120
|
it "uses the correct bucket" do
|
@@ -124,8 +130,8 @@ describe Paperclip::Storage::S3 do
|
|
124
130
|
["http", :http, ""].each do |protocol|
|
125
131
|
context "as #{protocol.inspect}" do
|
126
132
|
before do
|
127
|
-
rebuild_model storage: :s3,
|
128
|
-
|
133
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
134
|
+
s3_protocol: protocol
|
129
135
|
@dummy = Dummy.new
|
130
136
|
end
|
131
137
|
|
@@ -138,13 +144,14 @@ describe Paperclip::Storage::S3 do
|
|
138
144
|
|
139
145
|
context "s3_protocol: 'https'" do
|
140
146
|
before do
|
141
|
-
rebuild_model storage: :s3,
|
147
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
142
148
|
s3_credentials: {},
|
143
149
|
s3_protocol: 'https',
|
144
150
|
bucket: "bucket",
|
145
151
|
path: ":attachment/:basename:dotextension"
|
146
152
|
@dummy = Dummy.new
|
147
153
|
@dummy.avatar = stringy_file
|
154
|
+
@dummy.stubs(:new_record?).returns(false)
|
148
155
|
end
|
149
156
|
|
150
157
|
it "returns a url based on an S3 path" do
|
@@ -154,13 +161,14 @@ describe Paperclip::Storage::S3 do
|
|
154
161
|
|
155
162
|
context "s3_protocol: ''" do
|
156
163
|
before do
|
157
|
-
rebuild_model storage: :s3,
|
164
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
158
165
|
s3_credentials: {},
|
159
166
|
s3_protocol: '',
|
160
167
|
bucket: "bucket",
|
161
168
|
path: ":attachment/:basename:dotextension"
|
162
169
|
@dummy = Dummy.new
|
163
170
|
@dummy.avatar = stringy_file
|
171
|
+
@dummy.stubs(:new_record?).returns(false)
|
164
172
|
end
|
165
173
|
|
166
174
|
it "returns a protocol-relative URL" do
|
@@ -170,13 +178,14 @@ describe Paperclip::Storage::S3 do
|
|
170
178
|
|
171
179
|
context "s3_protocol: :https" do
|
172
180
|
before do
|
173
|
-
rebuild_model storage: :s3,
|
181
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
174
182
|
s3_credentials: {},
|
175
183
|
s3_protocol: :https,
|
176
184
|
bucket: "bucket",
|
177
185
|
path: ":attachment/:basename:dotextension"
|
178
186
|
@dummy = Dummy.new
|
179
187
|
@dummy.avatar = stringy_file
|
188
|
+
@dummy.stubs(:new_record?).returns(false)
|
180
189
|
end
|
181
190
|
|
182
191
|
it "returns a url based on an S3 path" do
|
@@ -186,13 +195,14 @@ describe Paperclip::Storage::S3 do
|
|
186
195
|
|
187
196
|
context "s3_protocol: ''" do
|
188
197
|
before do
|
189
|
-
rebuild_model storage: :s3,
|
198
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
190
199
|
s3_credentials: {},
|
191
200
|
s3_protocol: '',
|
192
201
|
bucket: "bucket",
|
193
202
|
path: ":attachment/:basename:dotextension"
|
194
203
|
@dummy = Dummy.new
|
195
204
|
@dummy.avatar = stringy_file
|
205
|
+
@dummy.stubs(:new_record?).returns(false)
|
196
206
|
end
|
197
207
|
|
198
208
|
it "returns a url based on an S3 path" do
|
@@ -202,7 +212,7 @@ describe Paperclip::Storage::S3 do
|
|
202
212
|
|
203
213
|
context "An attachment that uses S3 for storage and has the style in the path" do
|
204
214
|
before do
|
205
|
-
rebuild_model storage: :s3,
|
215
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
206
216
|
bucket: "testing",
|
207
217
|
path: ":attachment/:style/:basename:dotextension",
|
208
218
|
styles: {
|
@@ -227,29 +237,33 @@ describe Paperclip::Storage::S3 do
|
|
227
237
|
end
|
228
238
|
end
|
229
239
|
|
240
|
+
# the s3_host_name will be defined by the s3_region
|
230
241
|
context "s3_host_name" do
|
231
242
|
before do
|
232
243
|
rebuild_model storage: :s3,
|
233
244
|
s3_credentials: {},
|
234
245
|
bucket: "bucket",
|
235
246
|
path: ":attachment/:basename:dotextension",
|
236
|
-
s3_host_name: "s3-ap-northeast-1.amazonaws.com"
|
247
|
+
s3_host_name: "s3-ap-northeast-1.amazonaws.com",
|
248
|
+
s3_region: "ap-northeast-1"
|
237
249
|
@dummy = Dummy.new
|
238
250
|
@dummy.avatar = stringy_file
|
251
|
+
@dummy.stubs(:new_record?).returns(false)
|
239
252
|
end
|
240
253
|
|
241
254
|
it "returns a url based on an :s3_host_name path" do
|
242
|
-
assert_match %r{
|
255
|
+
assert_match %r{^//s3-ap-northeast-1.amazonaws.com/bucket/avatars/data[^\.]}, @dummy.avatar.url
|
243
256
|
end
|
244
257
|
|
245
258
|
it "uses the S3 bucket with the correct host name" do
|
246
|
-
assert_equal "s3
|
259
|
+
assert_equal "s3.ap-northeast-1.amazonaws.com",
|
260
|
+
@dummy.avatar.s3_bucket.client.config.endpoint.host
|
247
261
|
end
|
248
262
|
end
|
249
263
|
|
250
264
|
context "dynamic s3_host_name" do
|
251
265
|
before do
|
252
|
-
rebuild_model storage: :s3,
|
266
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
253
267
|
s3_credentials: {},
|
254
268
|
bucket: "bucket",
|
255
269
|
path: ":attachment/:basename:dotextension",
|
@@ -259,18 +273,72 @@ describe Paperclip::Storage::S3 do
|
|
259
273
|
attr_accessor :value
|
260
274
|
end
|
261
275
|
@dummy.avatar = stringy_file
|
276
|
+
@dummy.stubs(:new_record?).returns(false)
|
262
277
|
end
|
263
278
|
|
264
279
|
it "uses s3_host_name as a proc if available" do
|
265
280
|
@dummy.value = "s3.something.com"
|
266
|
-
assert_equal "
|
281
|
+
assert_equal "//s3.something.com/bucket/avatars/data", @dummy.avatar.url(:original, timestamp: false)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context "use_accelerate_endpoint" do
|
286
|
+
context "defaults to false" do
|
287
|
+
before do
|
288
|
+
rebuild_model(
|
289
|
+
storage: :s3,
|
290
|
+
s3_credentials: {},
|
291
|
+
bucket: "bucket",
|
292
|
+
path: ":attachment/:basename:dotextension",
|
293
|
+
s3_host_name: "s3-ap-northeast-1.amazonaws.com",
|
294
|
+
s3_region: "ap-northeast-1",
|
295
|
+
)
|
296
|
+
@dummy = Dummy.new
|
297
|
+
@dummy.avatar = stringy_file
|
298
|
+
@dummy.stubs(:new_record?).returns(false)
|
299
|
+
end
|
300
|
+
|
301
|
+
it "returns a url based on an :s3_host_name path" do
|
302
|
+
assert_match %r{^//s3-ap-northeast-1.amazonaws.com/bucket/avatars/data[^\.]},
|
303
|
+
@dummy.avatar.url
|
304
|
+
end
|
305
|
+
|
306
|
+
it "uses the S3 client with the use_accelerate_endpoint config is false" do
|
307
|
+
expect(@dummy.avatar.s3_bucket.client.config.use_accelerate_endpoint).to be(false)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context "set to true" do
|
312
|
+
before do
|
313
|
+
rebuild_model(
|
314
|
+
storage: :s3,
|
315
|
+
s3_credentials: {},
|
316
|
+
bucket: "bucket",
|
317
|
+
path: ":attachment/:basename:dotextension",
|
318
|
+
s3_host_name: "s3-accelerate.amazonaws.com",
|
319
|
+
s3_region: "ap-northeast-1",
|
320
|
+
use_accelerate_endpoint: true,
|
321
|
+
)
|
322
|
+
@dummy = Dummy.new
|
323
|
+
@dummy.avatar = stringy_file
|
324
|
+
@dummy.stubs(:new_record?).returns(false)
|
325
|
+
end
|
326
|
+
|
327
|
+
it "returns a url based on an :s3_host_name path" do
|
328
|
+
assert_match %r{^//s3-accelerate.amazonaws.com/bucket/avatars/data[^\.]},
|
329
|
+
@dummy.avatar.url
|
330
|
+
end
|
331
|
+
|
332
|
+
it "uses the S3 client with the use_accelerate_endpoint config is true" do
|
333
|
+
expect(@dummy.avatar.s3_bucket.client.config.use_accelerate_endpoint).to be(true)
|
334
|
+
end
|
267
335
|
end
|
268
336
|
end
|
269
337
|
|
270
338
|
context "An attachment that uses S3 for storage and has styles that return different file types" do
|
271
339
|
before do
|
272
|
-
rebuild_model
|
273
|
-
|
340
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
341
|
+
styles: { large: ['500x500#', :jpg] },
|
274
342
|
bucket: "bucket",
|
275
343
|
path: ":attachment/:basename:dotextension",
|
276
344
|
s3_credentials: {
|
@@ -281,6 +349,7 @@ describe Paperclip::Storage::S3 do
|
|
281
349
|
File.open(fixture_file('5k.png'), 'rb') do |file|
|
282
350
|
@dummy = Dummy.new
|
283
351
|
@dummy.avatar = file
|
352
|
+
@dummy.stubs(:new_record?).returns(false)
|
284
353
|
end
|
285
354
|
end
|
286
355
|
|
@@ -303,8 +372,10 @@ describe Paperclip::Storage::S3 do
|
|
303
372
|
|
304
373
|
context "An attachment that uses S3 for storage and has a proc for styles" do
|
305
374
|
before do
|
306
|
-
rebuild_model
|
307
|
-
|
375
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
376
|
+
styles: lambda { |attachment| attachment.instance.counter
|
377
|
+
{thumbnail: { geometry: "50x50#",
|
378
|
+
s3_headers: {'Cache-Control' => 'max-age=31557600'}} }},
|
308
379
|
bucket: "bucket",
|
309
380
|
path: ":attachment/:style/:basename:dotextension",
|
310
381
|
s3_credentials: {
|
@@ -328,8 +399,14 @@ describe Paperclip::Storage::S3 do
|
|
328
399
|
object = stub
|
329
400
|
@dummy.avatar.stubs(:s3_object).with(:original).returns(object)
|
330
401
|
@dummy.avatar.stubs(:s3_object).with(:thumbnail).returns(object)
|
331
|
-
|
332
|
-
object.expects(:
|
402
|
+
|
403
|
+
object.expects(:upload_file)
|
404
|
+
.with(anything, content_type: 'image/png',
|
405
|
+
acl: :"public-read")
|
406
|
+
object.expects(:upload_file)
|
407
|
+
.with(anything, content_type: 'image/png',
|
408
|
+
acl: :"public-read",
|
409
|
+
cache_control: 'max-age=31557600')
|
333
410
|
@dummy.save
|
334
411
|
end
|
335
412
|
|
@@ -340,20 +417,73 @@ describe Paperclip::Storage::S3 do
|
|
340
417
|
end
|
341
418
|
end
|
342
419
|
|
420
|
+
context "An attachment that uses S3 for storage and has styles" do
|
421
|
+
before do
|
422
|
+
rebuild_model(
|
423
|
+
(aws2_add_region).merge(
|
424
|
+
storage: :s3,
|
425
|
+
styles: { thumb: ["90x90#", :jpg] },
|
426
|
+
bucket: "bucket",
|
427
|
+
s3_credentials: {
|
428
|
+
"access_key_id" => "12345",
|
429
|
+
"secret_access_key" => "54321" }
|
430
|
+
)
|
431
|
+
)
|
432
|
+
|
433
|
+
@file = File.new(fixture_file("5k.png"), "rb")
|
434
|
+
@dummy = Dummy.new
|
435
|
+
@dummy.avatar = @file
|
436
|
+
@dummy.save
|
437
|
+
end
|
438
|
+
|
439
|
+
context "reprocess" do
|
440
|
+
before do
|
441
|
+
@object = stub
|
442
|
+
@dummy.avatar.stubs(:s3_object).with(:original).returns(@object)
|
443
|
+
@dummy.avatar.stubs(:s3_object).with(:thumb).returns(@object)
|
444
|
+
@object.stubs(:get).yields(@file.read)
|
445
|
+
@object.stubs(:exists?).returns(true)
|
446
|
+
end
|
447
|
+
|
448
|
+
it "uploads original" do
|
449
|
+
@object.expects(:upload_file).with(
|
450
|
+
anything,
|
451
|
+
content_type: "image/png",
|
452
|
+
acl: :"public-read").returns(true)
|
453
|
+
@object.expects(:upload_file).with(
|
454
|
+
anything,
|
455
|
+
content_type: "image/jpeg",
|
456
|
+
acl: :"public-read").returns(true)
|
457
|
+
@dummy.avatar.reprocess!
|
458
|
+
end
|
459
|
+
|
460
|
+
it "doesn't upload original" do
|
461
|
+
@object.expects(:upload_file).with(
|
462
|
+
anything,
|
463
|
+
content_type: "image/jpeg",
|
464
|
+
acl: :"public-read").returns(true)
|
465
|
+
@dummy.avatar.reprocess!(:thumb)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
after { @file.close }
|
470
|
+
end
|
471
|
+
|
343
472
|
context "An attachment that uses S3 for storage and has spaces in file name" do
|
344
473
|
before do
|
345
|
-
rebuild_model
|
346
|
-
storage: :s3,
|
474
|
+
rebuild_model(
|
475
|
+
(aws2_add_region).merge storage: :s3,
|
476
|
+
styles: { large: ["500x500#", :jpg] },
|
347
477
|
bucket: "bucket",
|
348
|
-
s3_credentials: {
|
349
|
-
|
350
|
-
|
351
|
-
}
|
478
|
+
s3_credentials: { "access_key_id" => "12345",
|
479
|
+
"secret_access_key" => "54321" }
|
480
|
+
)
|
352
481
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
482
|
+
File.open(fixture_file("spaced file.png"), "rb") do |file|
|
483
|
+
@dummy = Dummy.new
|
484
|
+
@dummy.avatar = file
|
485
|
+
@dummy.stubs(:new_record?).returns(false)
|
486
|
+
end
|
357
487
|
end
|
358
488
|
|
359
489
|
it "returns a replaced version for path" do
|
@@ -367,24 +497,25 @@ describe Paperclip::Storage::S3 do
|
|
367
497
|
|
368
498
|
context "An attachment that uses S3 for storage and has a question mark in file name" do
|
369
499
|
before do
|
370
|
-
rebuild_model
|
371
|
-
|
500
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
501
|
+
styles: { large: ['500x500#', :jpg] },
|
372
502
|
bucket: "bucket",
|
373
503
|
s3_credentials: {
|
374
504
|
'access_key_id' => "12345",
|
375
505
|
'secret_access_key' => "54321"
|
376
506
|
}
|
377
507
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
end
|
508
|
+
stringio = stringy_file
|
509
|
+
class << stringio
|
510
|
+
def original_filename
|
511
|
+
"question?mark.png"
|
383
512
|
end
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
513
|
+
end
|
514
|
+
file = Paperclip.io_adapters.for(stringio, hash_digest: Digest::MD5)
|
515
|
+
@dummy = Dummy.new
|
516
|
+
@dummy.avatar = file
|
517
|
+
@dummy.save
|
518
|
+
@dummy.stubs(:new_record?).returns(false)
|
388
519
|
end
|
389
520
|
|
390
521
|
it "returns a replaced version for path" do
|
@@ -398,42 +529,74 @@ describe Paperclip::Storage::S3 do
|
|
398
529
|
|
399
530
|
context "" do
|
400
531
|
before do
|
401
|
-
rebuild_model storage: :s3,
|
532
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
402
533
|
s3_credentials: {},
|
403
534
|
bucket: "bucket",
|
404
535
|
path: ":attachment/:basename:dotextension",
|
405
536
|
url: ":s3_domain_url"
|
406
537
|
@dummy = Dummy.new
|
407
538
|
@dummy.avatar = stringy_file
|
539
|
+
@dummy.stubs(:new_record?).returns(false)
|
408
540
|
end
|
409
541
|
|
410
542
|
it "returns a url based on an S3 subdomain" do
|
411
|
-
assert_match %r{
|
543
|
+
assert_match %r{^//bucket.s3.amazonaws.com/avatars/data[^\.]}, @dummy.avatar.url
|
412
544
|
end
|
413
545
|
end
|
414
546
|
|
415
547
|
context "" do
|
416
548
|
before do
|
417
|
-
rebuild_model
|
549
|
+
rebuild_model(
|
550
|
+
(aws2_add_region).merge storage: :s3,
|
418
551
|
s3_credentials: {
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
552
|
+
production: { bucket: "prod_bucket" },
|
553
|
+
development: { bucket: "dev_bucket" }
|
554
|
+
},
|
555
|
+
bucket: "bucket",
|
556
|
+
s3_host_alias: "something.something.com",
|
557
|
+
path: ":attachment/:basename:dotextension",
|
558
|
+
url: ":s3_alias_url"
|
559
|
+
)
|
425
560
|
@dummy = Dummy.new
|
426
561
|
@dummy.avatar = stringy_file
|
562
|
+
@dummy.stubs(:new_record?).returns(false)
|
427
563
|
end
|
428
564
|
|
429
565
|
it "returns a url based on the host_alias" do
|
430
|
-
assert_match %r{
|
566
|
+
assert_match %r{^//something.something.com/avatars/data[^\.]}, @dummy.avatar.url
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
context "generating a url with a prefixed host alias" do
|
571
|
+
before do
|
572
|
+
rebuild_model(
|
573
|
+
aws2_add_region.merge(
|
574
|
+
storage: :s3,
|
575
|
+
s3_credentials: {
|
576
|
+
production: { bucket: "prod_bucket" },
|
577
|
+
development: { bucket: "dev_bucket" },
|
578
|
+
},
|
579
|
+
bucket: "bucket",
|
580
|
+
s3_host_alias: "something.something.com",
|
581
|
+
s3_prefixes_in_alias: 2,
|
582
|
+
path: "prefix1/prefix2/:attachment/:basename:dotextension",
|
583
|
+
url: ":s3_alias_url",
|
584
|
+
)
|
585
|
+
)
|
586
|
+
@dummy = Dummy.new
|
587
|
+
@dummy.avatar = stringy_file
|
588
|
+
@dummy.stubs(:new_record?).returns(false)
|
589
|
+
end
|
590
|
+
|
591
|
+
it "returns a url with the prefixes removed" do
|
592
|
+
assert_match %r{^//something.something.com/avatars/data[^\.]},
|
593
|
+
@dummy.avatar.url
|
431
594
|
end
|
432
595
|
end
|
433
596
|
|
434
597
|
context "generating a url with a proc as the host alias" do
|
435
598
|
before do
|
436
|
-
rebuild_model storage: :s3,
|
599
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
437
600
|
s3_credentials: { bucket: "prod_bucket" },
|
438
601
|
s3_host_alias: Proc.new{|atch| "cdn#{atch.instance.counter % 4}.example.com"},
|
439
602
|
path: ":attachment/:basename:dotextension",
|
@@ -447,11 +610,12 @@ describe Paperclip::Storage::S3 do
|
|
447
610
|
end
|
448
611
|
@dummy = Dummy.new
|
449
612
|
@dummy.avatar = stringy_file
|
613
|
+
@dummy.stubs(:new_record?).returns(false)
|
450
614
|
end
|
451
615
|
|
452
616
|
it "returns a url based on the host_alias" do
|
453
|
-
assert_match %r{
|
454
|
-
assert_match %r{
|
617
|
+
assert_match %r{^//cdn1.example.com/avatars/data[^\.]}, @dummy.avatar.url
|
618
|
+
assert_match %r{^//cdn2.example.com/avatars/data[^\.]}, @dummy.avatar.url
|
455
619
|
end
|
456
620
|
|
457
621
|
it "still returns the bucket name" do
|
@@ -462,13 +626,14 @@ describe Paperclip::Storage::S3 do
|
|
462
626
|
|
463
627
|
context "" do
|
464
628
|
before do
|
465
|
-
rebuild_model storage: :s3,
|
629
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
466
630
|
s3_credentials: {},
|
467
631
|
bucket: "bucket",
|
468
632
|
path: ":attachment/:basename:dotextension",
|
469
633
|
url: ":asset_host"
|
470
634
|
@dummy = Dummy.new
|
471
635
|
@dummy.avatar = stringy_file
|
636
|
+
@dummy.stubs(:new_record?).returns(false)
|
472
637
|
end
|
473
638
|
|
474
639
|
it "returns a relative URL for Rails to calculate assets host" do
|
@@ -492,7 +657,7 @@ describe Paperclip::Storage::S3 do
|
|
492
657
|
url: ":s3_alias_url"
|
493
658
|
}
|
494
659
|
|
495
|
-
rebuild_model base_options.merge(options)
|
660
|
+
rebuild_model (aws2_add_region).merge base_options.merge(options)
|
496
661
|
}
|
497
662
|
end
|
498
663
|
|
@@ -505,8 +670,8 @@ describe Paperclip::Storage::S3 do
|
|
505
670
|
|
506
671
|
object = stub
|
507
672
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
508
|
-
object.expects(:url_for).with(:read, expires: 3600, secure: true)
|
509
673
|
|
674
|
+
object.expects(:presigned_url).with(:get, expires_in: 3600)
|
510
675
|
@dummy.avatar.expiring_url
|
511
676
|
end
|
512
677
|
end
|
@@ -520,8 +685,9 @@ describe Paperclip::Storage::S3 do
|
|
520
685
|
|
521
686
|
object = stub
|
522
687
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
523
|
-
object.expects(:
|
524
|
-
|
688
|
+
object.expects(:presigned_url)
|
689
|
+
.with(:get, expires_in: 3600,
|
690
|
+
response_content_disposition: "inline")
|
525
691
|
@dummy.avatar.expiring_url
|
526
692
|
end
|
527
693
|
end
|
@@ -542,8 +708,8 @@ describe Paperclip::Storage::S3 do
|
|
542
708
|
|
543
709
|
object = stub
|
544
710
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
545
|
-
object.expects(:
|
546
|
-
|
711
|
+
object.expects(:presigned_url)
|
712
|
+
.with(:get, expires_in: 3600, response_content_type: "image/png")
|
547
713
|
@dummy.avatar.expiring_url
|
548
714
|
end
|
549
715
|
end
|
@@ -571,15 +737,15 @@ describe Paperclip::Storage::S3 do
|
|
571
737
|
|
572
738
|
context "Generating a url with an expiration for each style" do
|
573
739
|
before do
|
574
|
-
rebuild_model storage: :s3,
|
740
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
575
741
|
s3_credentials: {
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
742
|
+
production: { bucket: "prod_bucket" },
|
743
|
+
development: { bucket: "dev_bucket" }
|
744
|
+
},
|
745
|
+
s3_permissions: :private,
|
746
|
+
s3_host_alias: "something.something.com",
|
747
|
+
path: ":attachment/:style/:basename:dotextension",
|
748
|
+
url: ":s3_alias_url"
|
583
749
|
|
584
750
|
rails_env("production") do
|
585
751
|
@dummy = Dummy.new
|
@@ -590,26 +756,26 @@ describe Paperclip::Storage::S3 do
|
|
590
756
|
it "generates a url for the thumb" do
|
591
757
|
object = stub
|
592
758
|
@dummy.avatar.stubs(:s3_object).with(:thumb).returns(object)
|
593
|
-
object.expects(:
|
759
|
+
object.expects(:presigned_url).with(:get, expires_in: 1800)
|
594
760
|
@dummy.avatar.expiring_url(1800, :thumb)
|
595
761
|
end
|
596
762
|
|
597
763
|
it "generates a url for the default style" do
|
598
764
|
object = stub
|
599
765
|
@dummy.avatar.stubs(:s3_object).with(:original).returns(object)
|
600
|
-
object.expects(:
|
766
|
+
object.expects(:presigned_url).with(:get, expires_in: 1800)
|
601
767
|
@dummy.avatar.expiring_url(1800)
|
602
768
|
end
|
603
769
|
end
|
604
770
|
|
605
771
|
context "Parsing S3 credentials with a bucket in them" do
|
606
772
|
before do
|
607
|
-
rebuild_model storage: :s3,
|
773
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
608
774
|
s3_credentials: {
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
775
|
+
production: { bucket: "prod_bucket" },
|
776
|
+
development: { bucket: "dev_bucket" }
|
777
|
+
}
|
778
|
+
@dummy = Dummy.new
|
613
779
|
end
|
614
780
|
|
615
781
|
it "gets the right bucket in production" do
|
@@ -627,47 +793,59 @@ describe Paperclip::Storage::S3 do
|
|
627
793
|
end
|
628
794
|
end
|
629
795
|
|
796
|
+
# the bucket.name is determined by the :s3_region
|
630
797
|
context "Parsing S3 credentials with a s3_host_name in them" do
|
631
798
|
before do
|
632
799
|
rebuild_model storage: :s3,
|
633
800
|
bucket: 'testing',
|
634
801
|
s3_credentials: {
|
635
|
-
|
636
|
-
|
802
|
+
production: {
|
803
|
+
s3_region: "world-end",
|
804
|
+
s3_host_name: "s3-world-end.amazonaws.com" },
|
805
|
+
development: {
|
806
|
+
s3_region: "ap-northeast-1",
|
807
|
+
s3_host_name: "s3-ap-northeast-1.amazonaws.com" },
|
808
|
+
test: {
|
809
|
+
s3_region: "" }
|
637
810
|
}
|
638
|
-
|
811
|
+
@dummy = Dummy.new
|
639
812
|
end
|
640
813
|
|
641
814
|
it "gets the right s3_host_name in production" do
|
642
815
|
rails_env("production") do
|
643
816
|
assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_host_name
|
644
|
-
assert_match %r{^s3
|
817
|
+
assert_match %r{^s3.world-end.amazonaws.com},
|
818
|
+
@dummy.avatar.s3_bucket.client.config.endpoint.host
|
645
819
|
end
|
646
820
|
end
|
647
821
|
|
648
822
|
it "gets the right s3_host_name in development" do
|
649
823
|
rails_env("development") do
|
650
|
-
assert_match %r{^s3
|
651
|
-
|
824
|
+
assert_match %r{^s3.ap-northeast-1.amazonaws.com},
|
825
|
+
@dummy.avatar.s3_host_name
|
826
|
+
assert_match %r{^s3.ap-northeast-1.amazonaws.com},
|
827
|
+
@dummy.avatar.s3_bucket.client.config.endpoint.host
|
652
828
|
end
|
653
829
|
end
|
654
830
|
|
655
831
|
it "gets the right s3_host_name if the key does not exist" do
|
656
832
|
rails_env("test") do
|
657
833
|
assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_host_name
|
658
|
-
|
834
|
+
assert_raises(Aws::Errors::MissingRegionError) do
|
835
|
+
@dummy.avatar.s3_bucket.client.config.endpoint.host
|
836
|
+
end
|
659
837
|
end
|
660
838
|
end
|
661
839
|
end
|
662
840
|
|
663
841
|
context "An attachment with S3 storage" do
|
664
842
|
before do
|
665
|
-
rebuild_model storage: :s3,
|
843
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
666
844
|
bucket: "testing",
|
667
845
|
path: ":attachment/:style/:basename:dotextension",
|
668
846
|
s3_credentials: {
|
669
|
-
|
670
|
-
|
847
|
+
access_key_id: "12345",
|
848
|
+
secret_access_key: "54321"
|
671
849
|
}
|
672
850
|
end
|
673
851
|
|
@@ -684,6 +862,7 @@ describe Paperclip::Storage::S3 do
|
|
684
862
|
@file = File.new(fixture_file('5k.png'), 'rb')
|
685
863
|
@dummy = Dummy.new
|
686
864
|
@dummy.avatar = @file
|
865
|
+
@dummy.stubs(:new_record?).returns(false)
|
687
866
|
end
|
688
867
|
|
689
868
|
after { @file.close }
|
@@ -691,20 +870,19 @@ describe Paperclip::Storage::S3 do
|
|
691
870
|
it "does not get a bucket to get a URL" do
|
692
871
|
@dummy.avatar.expects(:s3).never
|
693
872
|
@dummy.avatar.expects(:s3_bucket).never
|
694
|
-
assert_match %r{
|
873
|
+
assert_match %r{^//s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
|
695
874
|
end
|
696
875
|
|
697
876
|
it "is rewound after flush_writes" do
|
698
877
|
@dummy.avatar.instance_eval "def after_flush_writes; end"
|
699
|
-
@dummy.avatar.stubs(:s3_object).returns(stub(
|
700
|
-
|
878
|
+
@dummy.avatar.stubs(:s3_object).returns(stub(upload_file: true))
|
701
879
|
files = @dummy.avatar.queued_for_write.values.each(&:read)
|
702
880
|
@dummy.save
|
703
881
|
assert files.none?(&:eof?), "Expect all the files to be rewound."
|
704
882
|
end
|
705
883
|
|
706
884
|
it "is removed after after_flush_writes" do
|
707
|
-
@dummy.avatar.stubs(:s3_object).returns(stub(
|
885
|
+
@dummy.avatar.stubs(:s3_object).returns(stub(upload_file: true))
|
708
886
|
paths = @dummy.avatar.queued_for_write.values.map(&:path)
|
709
887
|
@dummy.save
|
710
888
|
assert paths.none?{ |path| File.exist?(path) },
|
@@ -713,10 +891,10 @@ describe Paperclip::Storage::S3 do
|
|
713
891
|
|
714
892
|
it "will retry to save again but back off on SlowDown" do
|
715
893
|
@dummy.avatar.stubs(:sleep)
|
716
|
-
|
717
|
-
raises(
|
718
|
-
|
719
|
-
expect {@dummy.save}.to raise_error(
|
894
|
+
Aws::S3::Object.any_instance.stubs(:upload_file).
|
895
|
+
raises(Aws::S3::Errors::SlowDown.new(stub,
|
896
|
+
stub(status: 503, body: "")))
|
897
|
+
expect {@dummy.save}.to raise_error(Aws::S3::Errors::SlowDown)
|
720
898
|
expect(@dummy.avatar).to have_received(:sleep).with(1)
|
721
899
|
expect(@dummy.avatar).to have_received(:sleep).with(2)
|
722
900
|
expect(@dummy.avatar).to have_received(:sleep).with(4)
|
@@ -728,9 +906,8 @@ describe Paperclip::Storage::S3 do
|
|
728
906
|
before do
|
729
907
|
object = stub
|
730
908
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
731
|
-
object.expects(:
|
732
|
-
|
733
|
-
acl: :public_read)
|
909
|
+
object.expects(:upload_file)
|
910
|
+
.with(anything, content_type: 'image/png', acl: :"public-read")
|
734
911
|
@dummy.save
|
735
912
|
end
|
736
913
|
|
@@ -741,12 +918,11 @@ describe Paperclip::Storage::S3 do
|
|
741
918
|
|
742
919
|
context "and saved without a bucket" do
|
743
920
|
before do
|
744
|
-
|
745
|
-
|
746
|
-
raises(
|
747
|
-
|
748
|
-
|
749
|
-
then.returns(nil)
|
921
|
+
Aws::S3::Bucket.any_instance.expects(:create)
|
922
|
+
Aws::S3::Object.any_instance.stubs(:upload_file).
|
923
|
+
raises(Aws::S3::Errors::NoSuchBucket
|
924
|
+
.new(stub,
|
925
|
+
stub(status: 404, body: "<foo/>"))).then.returns(nil)
|
750
926
|
@dummy.save
|
751
927
|
end
|
752
928
|
|
@@ -757,8 +933,8 @@ describe Paperclip::Storage::S3 do
|
|
757
933
|
|
758
934
|
context "and remove" do
|
759
935
|
before do
|
760
|
-
|
761
|
-
|
936
|
+
Aws::S3::Object.any_instance.stubs(:exists?).returns(true)
|
937
|
+
Aws::S3::Object.any_instance.stubs(:delete)
|
762
938
|
@dummy.destroy
|
763
939
|
end
|
764
940
|
|
@@ -769,7 +945,9 @@ describe Paperclip::Storage::S3 do
|
|
769
945
|
|
770
946
|
context 'that the file were missing' do
|
771
947
|
before do
|
772
|
-
|
948
|
+
Aws::S3::Object.any_instance.stubs(:exists?)
|
949
|
+
.raises(Aws::S3::Errors::ServiceError.new("rspec stub raises",
|
950
|
+
"object exists?"))
|
773
951
|
end
|
774
952
|
|
775
953
|
it 'returns false on exists?' do
|
@@ -781,7 +959,7 @@ describe Paperclip::Storage::S3 do
|
|
781
959
|
|
782
960
|
context "An attachment with S3 storage and bucket defined as a Proc" do
|
783
961
|
before do
|
784
|
-
rebuild_model storage: :s3,
|
962
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
785
963
|
bucket: lambda { |attachment| "bucket_#{attachment.instance.other}" },
|
786
964
|
s3_credentials: {not: :important}
|
787
965
|
end
|
@@ -796,7 +974,7 @@ describe Paperclip::Storage::S3 do
|
|
796
974
|
|
797
975
|
context "An attachment with S3 storage and S3 credentials defined as a Proc" do
|
798
976
|
before do
|
799
|
-
rebuild_model storage: :s3,
|
977
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
800
978
|
bucket: {not: :important},
|
801
979
|
s3_credentials: lambda { |attachment|
|
802
980
|
Hash['access_key_id' => "access#{attachment.instance.other}", 'secret_access_key' => "secret#{attachment.instance.other}"]
|
@@ -813,22 +991,23 @@ describe Paperclip::Storage::S3 do
|
|
813
991
|
before do
|
814
992
|
class DummyCredentialProvider; end
|
815
993
|
|
816
|
-
rebuild_model storage: :s3,
|
994
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
817
995
|
bucket: "testing",
|
818
996
|
s3_credentials: {
|
819
|
-
|
997
|
+
credentials: DummyCredentialProvider.new
|
820
998
|
}
|
821
|
-
|
999
|
+
@dummy = Dummy.new
|
822
1000
|
end
|
823
1001
|
|
824
1002
|
it "sets the credential-provider" do
|
825
|
-
expect(@dummy.avatar.s3_bucket.config.
|
1003
|
+
expect(@dummy.avatar.s3_bucket.client.config.credentials).to be_a DummyCredentialProvider
|
826
1004
|
end
|
827
1005
|
end
|
828
1006
|
|
829
1007
|
context "An attachment with S3 storage and S3 credentials in an unsupported manor" do
|
830
1008
|
before do
|
831
|
-
rebuild_model storage: :s3,
|
1009
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1010
|
+
bucket: "testing", s3_credentials: ["unsupported"]
|
832
1011
|
@dummy = Dummy.new
|
833
1012
|
end
|
834
1013
|
|
@@ -841,7 +1020,7 @@ describe Paperclip::Storage::S3 do
|
|
841
1020
|
|
842
1021
|
context "An attachment with S3 storage and S3 credentials not supplied" do
|
843
1022
|
before do
|
844
|
-
rebuild_model storage: :s3, bucket: "testing"
|
1023
|
+
rebuild_model (aws2_add_region).merge storage: :s3, bucket: "testing"
|
845
1024
|
@dummy = Dummy.new
|
846
1025
|
end
|
847
1026
|
|
@@ -852,7 +1031,7 @@ describe Paperclip::Storage::S3 do
|
|
852
1031
|
|
853
1032
|
context "An attachment with S3 storage and specific s3 headers set" do
|
854
1033
|
before do
|
855
|
-
rebuild_model storage: :s3,
|
1034
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
856
1035
|
bucket: "testing",
|
857
1036
|
path: ":attachment/:style/:basename:dotextension",
|
858
1037
|
s3_credentials: {
|
@@ -875,10 +1054,12 @@ describe Paperclip::Storage::S3 do
|
|
875
1054
|
before do
|
876
1055
|
object = stub
|
877
1056
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
1057
|
+
|
1058
|
+
object.expects(:upload_file)
|
1059
|
+
.with(anything,
|
1060
|
+
content_type: 'image/png',
|
1061
|
+
acl: :"public-read",
|
1062
|
+
cache_control: 'max-age=31557600')
|
882
1063
|
@dummy.save
|
883
1064
|
end
|
884
1065
|
|
@@ -891,7 +1072,7 @@ describe Paperclip::Storage::S3 do
|
|
891
1072
|
|
892
1073
|
context "An attachment with S3 storage and metadata set using header names" do
|
893
1074
|
before do
|
894
|
-
rebuild_model storage: :s3,
|
1075
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
895
1076
|
bucket: "testing",
|
896
1077
|
path: ":attachment/:style/:basename:dotextension",
|
897
1078
|
s3_credentials: {
|
@@ -914,10 +1095,12 @@ describe Paperclip::Storage::S3 do
|
|
914
1095
|
before do
|
915
1096
|
object = stub
|
916
1097
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
1098
|
+
|
1099
|
+
object.expects(:upload_file)
|
1100
|
+
.with(anything,
|
1101
|
+
content_type: 'image/png',
|
1102
|
+
acl: :"public-read",
|
1103
|
+
metadata: { "color" => "red" })
|
921
1104
|
@dummy.save
|
922
1105
|
end
|
923
1106
|
|
@@ -930,7 +1113,7 @@ describe Paperclip::Storage::S3 do
|
|
930
1113
|
|
931
1114
|
context "An attachment with S3 storage and metadata set using the :s3_metadata option" do
|
932
1115
|
before do
|
933
|
-
rebuild_model storage: :s3,
|
1116
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
934
1117
|
bucket: "testing",
|
935
1118
|
path: ":attachment/:style/:basename:dotextension",
|
936
1119
|
s3_credentials: {
|
@@ -953,10 +1136,12 @@ describe Paperclip::Storage::S3 do
|
|
953
1136
|
before do
|
954
1137
|
object = stub
|
955
1138
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
1139
|
+
|
1140
|
+
object.expects(:upload_file)
|
1141
|
+
.with(anything,
|
1142
|
+
content_type: 'image/png',
|
1143
|
+
acl: :"public-read",
|
1144
|
+
metadata: { "color" => "red" })
|
960
1145
|
@dummy.save
|
961
1146
|
end
|
962
1147
|
|
@@ -970,7 +1155,7 @@ describe Paperclip::Storage::S3 do
|
|
970
1155
|
context "An attachment with S3 storage and storage class set" do
|
971
1156
|
context "using the header name" do
|
972
1157
|
before do
|
973
|
-
rebuild_model storage: :s3,
|
1158
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
974
1159
|
bucket: "testing",
|
975
1160
|
path: ":attachment/:style/:basename:dotextension",
|
976
1161
|
s3_credentials: {
|
@@ -993,10 +1178,12 @@ describe Paperclip::Storage::S3 do
|
|
993
1178
|
before do
|
994
1179
|
object = stub
|
995
1180
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1181
|
+
|
1182
|
+
object.expects(:upload_file)
|
1183
|
+
.with(anything,
|
1184
|
+
content_type: 'image/png',
|
1185
|
+
acl: :"public-read",
|
1186
|
+
storage_class: "reduced_redundancy")
|
1000
1187
|
@dummy.save
|
1001
1188
|
end
|
1002
1189
|
|
@@ -1009,7 +1196,7 @@ describe Paperclip::Storage::S3 do
|
|
1009
1196
|
|
1010
1197
|
context "using per style hash" do
|
1011
1198
|
before do
|
1012
|
-
rebuild_model :storage => :s3,
|
1199
|
+
rebuild_model (aws2_add_region).merge :storage => :s3,
|
1013
1200
|
:bucket => "testing",
|
1014
1201
|
:path => ":attachment/:style/:basename.:extension",
|
1015
1202
|
:styles => {
|
@@ -1038,9 +1225,15 @@ describe Paperclip::Storage::S3 do
|
|
1038
1225
|
object = stub
|
1039
1226
|
[:thumb, :original].each do |style|
|
1040
1227
|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
|
1041
|
-
|
1228
|
+
|
1229
|
+
expected_options = {
|
1230
|
+
:content_type => "image/png",
|
1231
|
+
acl: :"public-read"
|
1232
|
+
}
|
1042
1233
|
expected_options.merge!(:storage_class => :reduced_redundancy) if style == :thumb
|
1043
|
-
|
1234
|
+
|
1235
|
+
object.expects(:upload_file)
|
1236
|
+
.with(anything, expected_options)
|
1044
1237
|
end
|
1045
1238
|
@dummy.save
|
1046
1239
|
end
|
@@ -1054,7 +1247,7 @@ describe Paperclip::Storage::S3 do
|
|
1054
1247
|
|
1055
1248
|
context "using global hash option" do
|
1056
1249
|
before do
|
1057
|
-
rebuild_model :storage => :s3,
|
1250
|
+
rebuild_model (aws2_add_region).merge :storage => :s3,
|
1058
1251
|
:bucket => "testing",
|
1059
1252
|
:path => ":attachment/:style/:basename.:extension",
|
1060
1253
|
:styles => {
|
@@ -1081,9 +1274,11 @@ describe Paperclip::Storage::S3 do
|
|
1081
1274
|
object = stub
|
1082
1275
|
[:thumb, :original].each do |style|
|
1083
1276
|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1277
|
+
|
1278
|
+
object.expects(:upload_file)
|
1279
|
+
.with(anything, :content_type => "image/png",
|
1280
|
+
acl: :"public-read",
|
1281
|
+
:storage_class => :reduced_redundancy)
|
1087
1282
|
end
|
1088
1283
|
@dummy.save
|
1089
1284
|
end
|
@@ -1100,7 +1295,7 @@ describe Paperclip::Storage::S3 do
|
|
1100
1295
|
[nil, false, ''].each do |tech|
|
1101
1296
|
before do
|
1102
1297
|
rebuild_model(
|
1103
|
-
storage: :s3,
|
1298
|
+
(aws2_add_region).merge storage: :s3,
|
1104
1299
|
bucket: "testing",
|
1105
1300
|
path: ":attachment/:style/:basename:dotextension",
|
1106
1301
|
s3_credentials: {
|
@@ -1122,9 +1317,9 @@ describe Paperclip::Storage::S3 do
|
|
1122
1317
|
before do
|
1123
1318
|
object = stub
|
1124
1319
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1320
|
+
|
1321
|
+
object.expects(:upload_file)
|
1322
|
+
.with(anything, :content_type => "image/png", acl: :"public-read")
|
1128
1323
|
@dummy.save
|
1129
1324
|
end
|
1130
1325
|
|
@@ -1138,14 +1333,14 @@ describe Paperclip::Storage::S3 do
|
|
1138
1333
|
|
1139
1334
|
context "An attachment with S3 storage and using AES256 encryption" do
|
1140
1335
|
before do
|
1141
|
-
rebuild_model storage: :s3,
|
1336
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1142
1337
|
bucket: "testing",
|
1143
1338
|
path: ":attachment/:style/:basename:dotextension",
|
1144
1339
|
s3_credentials: {
|
1145
1340
|
'access_key_id' => "12345",
|
1146
1341
|
'secret_access_key' => "54321"
|
1147
1342
|
},
|
1148
|
-
s3_server_side_encryption:
|
1343
|
+
s3_server_side_encryption: "AES256"
|
1149
1344
|
end
|
1150
1345
|
|
1151
1346
|
context "when assigned" do
|
@@ -1161,10 +1356,11 @@ describe Paperclip::Storage::S3 do
|
|
1161
1356
|
before do
|
1162
1357
|
object = stub
|
1163
1358
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1359
|
+
|
1360
|
+
object.expects(:upload_file)
|
1361
|
+
.with(anything, content_type: "image/png",
|
1362
|
+
acl: :"public-read",
|
1363
|
+
server_side_encryption: "AES256")
|
1168
1364
|
@dummy.save
|
1169
1365
|
end
|
1170
1366
|
|
@@ -1177,7 +1373,7 @@ describe Paperclip::Storage::S3 do
|
|
1177
1373
|
|
1178
1374
|
context "An attachment with S3 storage and storage class set using the :storage_class option" do
|
1179
1375
|
before do
|
1180
|
-
rebuild_model storage: :s3,
|
1376
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1181
1377
|
bucket: "testing",
|
1182
1378
|
path: ":attachment/:style/:basename:dotextension",
|
1183
1379
|
s3_credentials: {
|
@@ -1200,10 +1396,12 @@ describe Paperclip::Storage::S3 do
|
|
1200
1396
|
before do
|
1201
1397
|
object = stub
|
1202
1398
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1399
|
+
|
1400
|
+
object.expects(:upload_file)
|
1401
|
+
.with(anything,
|
1402
|
+
content_type: "image/png",
|
1403
|
+
acl: :"public-read",
|
1404
|
+
storage_class: :reduced_redundancy)
|
1207
1405
|
@dummy.save
|
1208
1406
|
end
|
1209
1407
|
|
@@ -1221,7 +1419,7 @@ describe Paperclip::Storage::S3 do
|
|
1221
1419
|
ENV['S3_SECRET'] = 'pathname_secret'
|
1222
1420
|
|
1223
1421
|
rails_env('test') do
|
1224
|
-
rebuild_model storage: :s3,
|
1422
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1225
1423
|
s3_credentials: Pathname.new(fixture_file('s3.yml'))
|
1226
1424
|
|
1227
1425
|
Dummy.delete_all
|
@@ -1231,8 +1429,12 @@ describe Paperclip::Storage::S3 do
|
|
1231
1429
|
|
1232
1430
|
it "parses the credentials" do
|
1233
1431
|
assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
|
1234
|
-
|
1235
|
-
assert_equal '
|
1432
|
+
|
1433
|
+
assert_equal 'pathname_key',
|
1434
|
+
@dummy.avatar.s3_bucket.client.config.access_key_id
|
1435
|
+
|
1436
|
+
assert_equal 'pathname_secret',
|
1437
|
+
@dummy.avatar.s3_bucket.client.config.secret_access_key
|
1236
1438
|
end
|
1237
1439
|
end
|
1238
1440
|
|
@@ -1243,7 +1445,7 @@ describe Paperclip::Storage::S3 do
|
|
1243
1445
|
ENV['S3_SECRET'] = 'env_secret'
|
1244
1446
|
|
1245
1447
|
rails_env('test') do
|
1246
|
-
rebuild_model storage: :s3,
|
1448
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1247
1449
|
s3_credentials: File.new(fixture_file('s3.yml'))
|
1248
1450
|
|
1249
1451
|
Dummy.delete_all
|
@@ -1254,15 +1456,19 @@ describe Paperclip::Storage::S3 do
|
|
1254
1456
|
|
1255
1457
|
it "runs the file through ERB" do
|
1256
1458
|
assert_equal 'env_bucket', @dummy.avatar.bucket_name
|
1257
|
-
|
1258
|
-
assert_equal '
|
1459
|
+
|
1460
|
+
assert_equal 'env_key',
|
1461
|
+
@dummy.avatar.s3_bucket.client.config.access_key_id
|
1462
|
+
|
1463
|
+
assert_equal 'env_secret',
|
1464
|
+
@dummy.avatar.s3_bucket.client.config.secret_access_key
|
1259
1465
|
end
|
1260
1466
|
end
|
1261
1467
|
|
1262
1468
|
context "S3 Permissions" do
|
1263
1469
|
context "defaults to :public_read" do
|
1264
1470
|
before do
|
1265
|
-
rebuild_model storage: :s3,
|
1471
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1266
1472
|
bucket: "testing",
|
1267
1473
|
path: ":attachment/:style/:basename:dotextension",
|
1268
1474
|
s3_credentials: {
|
@@ -1284,9 +1490,9 @@ describe Paperclip::Storage::S3 do
|
|
1284
1490
|
before do
|
1285
1491
|
object = stub
|
1286
1492
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1493
|
+
|
1494
|
+
object.expects(:upload_file)
|
1495
|
+
.with(anything, content_type: "image/png", acl: :"public-read")
|
1290
1496
|
@dummy.save
|
1291
1497
|
end
|
1292
1498
|
|
@@ -1299,7 +1505,7 @@ describe Paperclip::Storage::S3 do
|
|
1299
1505
|
|
1300
1506
|
context "string permissions set" do
|
1301
1507
|
before do
|
1302
|
-
rebuild_model storage: :s3,
|
1508
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1303
1509
|
bucket: "testing",
|
1304
1510
|
path: ":attachment/:style/:basename:dotextension",
|
1305
1511
|
s3_credentials: {
|
@@ -1322,9 +1528,9 @@ describe Paperclip::Storage::S3 do
|
|
1322
1528
|
before do
|
1323
1529
|
object = stub
|
1324
1530
|
@dummy.avatar.stubs(:s3_object).returns(object)
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1531
|
+
|
1532
|
+
object.expects(:upload_file)
|
1533
|
+
.with(anything, content_type: "image/png", acl: :private)
|
1328
1534
|
@dummy.save
|
1329
1535
|
end
|
1330
1536
|
|
@@ -1337,7 +1543,7 @@ describe Paperclip::Storage::S3 do
|
|
1337
1543
|
|
1338
1544
|
context "hash permissions set" do
|
1339
1545
|
before do
|
1340
|
-
rebuild_model storage: :s3,
|
1546
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1341
1547
|
bucket: "testing",
|
1342
1548
|
path: ":attachment/:style/:basename:dotextension",
|
1343
1549
|
styles: {
|
@@ -1367,9 +1573,11 @@ describe Paperclip::Storage::S3 do
|
|
1367
1573
|
[:thumb, :original].each do |style|
|
1368
1574
|
object = stub
|
1369
1575
|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1576
|
+
|
1577
|
+
object.expects(:upload_file)
|
1578
|
+
.with(anything,
|
1579
|
+
content_type: "image/png",
|
1580
|
+
acl: style == :thumb ? :public_read : :private)
|
1373
1581
|
end
|
1374
1582
|
@dummy.save
|
1375
1583
|
end
|
@@ -1384,7 +1592,7 @@ describe Paperclip::Storage::S3 do
|
|
1384
1592
|
context "proc permission set" do
|
1385
1593
|
before do
|
1386
1594
|
rebuild_model(
|
1387
|
-
storage: :s3,
|
1595
|
+
(aws2_add_region).merge storage: :s3,
|
1388
1596
|
bucket: "testing",
|
1389
1597
|
path: ":attachment/:style/:basename:dotextension",
|
1390
1598
|
styles: {
|
@@ -1395,40 +1603,17 @@ describe Paperclip::Storage::S3 do
|
|
1395
1603
|
'secret_access_key' => "54321"
|
1396
1604
|
},
|
1397
1605
|
s3_permissions: lambda {|attachment, style|
|
1398
|
-
attachment.instance.private_attachment? && style.to_sym != :thumb ? :private : :
|
1606
|
+
attachment.instance.private_attachment? && style.to_sym != :thumb ? :private : :"public-read"
|
1399
1607
|
}
|
1400
1608
|
)
|
1401
1609
|
end
|
1402
|
-
|
1403
|
-
context "when assigned" do
|
1404
|
-
before do
|
1405
|
-
@file = File.new(fixture_file('5k.png'), 'rb')
|
1406
|
-
@dummy = Dummy.new
|
1407
|
-
@dummy.stubs(:private_attachment? => true)
|
1408
|
-
@dummy.avatar = @file
|
1409
|
-
end
|
1410
|
-
|
1411
|
-
after { @file.close }
|
1412
|
-
|
1413
|
-
context "and saved" do
|
1414
|
-
before do
|
1415
|
-
@dummy.save
|
1416
|
-
end
|
1417
|
-
|
1418
|
-
it "succeeds" do
|
1419
|
-
assert @dummy.avatar.url().include? "https://"
|
1420
|
-
assert @dummy.avatar.url(:thumb).include? "http://"
|
1421
|
-
end
|
1422
|
-
end
|
1423
|
-
end
|
1424
|
-
|
1425
1610
|
end
|
1426
1611
|
end
|
1427
1612
|
|
1428
1613
|
context "An attachment with S3 storage and metadata set using a proc as headers" do
|
1429
1614
|
before do
|
1430
1615
|
rebuild_model(
|
1431
|
-
storage: :s3,
|
1616
|
+
(aws2_add_region).merge storage: :s3,
|
1432
1617
|
bucket: "testing",
|
1433
1618
|
path: ":attachment/:style/:basename:dotextension",
|
1434
1619
|
styles: {
|
@@ -1459,10 +1644,12 @@ describe Paperclip::Storage::S3 do
|
|
1459
1644
|
[:thumb, :original].each do |style|
|
1460
1645
|
object = stub
|
1461
1646
|
@dummy.avatar.stubs(:s3_object).with(style).returns(object)
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1647
|
+
|
1648
|
+
object.expects(:upload_file)
|
1649
|
+
.with(anything,
|
1650
|
+
content_type: "image/png",
|
1651
|
+
acl: :"public-read",
|
1652
|
+
content_disposition: 'attachment; filename="Custom Avatar Name.png"')
|
1466
1653
|
end
|
1467
1654
|
@dummy.save
|
1468
1655
|
end
|
@@ -1476,7 +1663,7 @@ describe Paperclip::Storage::S3 do
|
|
1476
1663
|
|
1477
1664
|
context "path is a proc" do
|
1478
1665
|
before do
|
1479
|
-
rebuild_model storage: :s3,
|
1666
|
+
rebuild_model (aws2_add_region).merge storage: :s3,
|
1480
1667
|
path: ->(attachment) { attachment.instance.attachment_path }
|
1481
1668
|
|
1482
1669
|
@dummy = Dummy.new
|
@@ -1493,7 +1680,6 @@ describe Paperclip::Storage::S3 do
|
|
1493
1680
|
end
|
1494
1681
|
end
|
1495
1682
|
|
1496
|
-
|
1497
1683
|
private
|
1498
1684
|
|
1499
1685
|
def rails_env(env)
|
@@ -1504,5 +1690,4 @@ describe Paperclip::Storage::S3 do
|
|
1504
1690
|
Rails.env = stored_env
|
1505
1691
|
end
|
1506
1692
|
end
|
1507
|
-
|
1508
1693
|
end
|