paperclip 4.2.2 → 5.2.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/.codeclimate.yml +17 -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/NEWS +148 -31
- data/README.md +327 -191
- 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 +33 -27
- 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/paperclip/attachment.rb +32 -20
- 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/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 +14 -10
- data/lib/paperclip/interpolations/plural_cache.rb +6 -5
- data/lib/paperclip/interpolations.rb +19 -14
- data/lib/paperclip/io_adapters/abstract_adapter.rb +26 -3
- data/lib/paperclip/io_adapters/attachment_adapter.rb +10 -5
- 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 +7 -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 +41 -19
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +2 -2
- data/lib/paperclip/processor.rb +5 -4
- data/lib/paperclip/rails_environment.rb +25 -0
- data/lib/paperclip/schema.rb +3 -9
- data/lib/paperclip/storage/filesystem.rb +13 -2
- data/lib/paperclip/storage/fog.rb +30 -18
- data/lib/paperclip/storage/s3.rb +92 -65
- data/lib/paperclip/thumbnail.rb +16 -7
- data/lib/paperclip/url_generator.rb +16 -13
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/validators.rb +1 -1
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +25 -12
- 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 -4
- data/spec/paperclip/attachment_registry_spec.rb +84 -13
- data/spec/paperclip/attachment_spec.rb +130 -39
- data/spec/paperclip/content_type_detector_spec.rb +8 -1
- data/spec/paperclip/file_command_content_type_detector_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 +4 -3
- data/spec/paperclip/interpolations_spec.rb +16 -13
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +47 -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 +26 -6
- 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 +77 -7
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +34 -11
- data/spec/paperclip/paperclip_spec.rb +4 -29
- data/spec/paperclip/plural_cache_spec.rb +17 -16
- data/spec/paperclip/rails_environment_spec.rb +33 -0
- data/spec/paperclip/storage/fog_spec.rb +58 -3
- data/spec/paperclip/storage/s3_live_spec.rb +20 -14
- data/spec/paperclip/storage/s3_spec.rb +398 -213
- data/spec/paperclip/tempfile_factory_spec.rb +4 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +51 -32
- data/spec/paperclip/url_generator_spec.rb +55 -44
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
- data/spec/paperclip/validators_spec.rb +5 -5
- data/spec/spec_helper.rb +8 -1
- data/spec/support/assertions.rb +12 -1
- data/spec/support/conditional_filter_helper.rb +5 -0
- 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 +9 -1
- data/spec/support/reporting.rb +11 -0
- metadata +109 -162
- 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
|
@@ -17,22 +17,26 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
17
17
|
|
|
18
18
|
it "rejects a class with no validation" do
|
|
19
19
|
expect(matcher).to_not accept(Dummy)
|
|
20
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
it 'rejects a class when the validation fails' do
|
|
23
24
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
|
|
24
25
|
expect(matcher).to_not accept(Dummy)
|
|
26
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
it "accepts a class with a matching validation" do
|
|
28
30
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
|
|
29
31
|
expect(matcher).to accept(Dummy)
|
|
32
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
it "accepts a class with other validations but matching types" do
|
|
33
36
|
Dummy.validates_presence_of :title
|
|
34
37
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
|
|
35
38
|
expect(matcher).to accept(Dummy)
|
|
39
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
it "accepts a class that matches and a matcher that only specifies 'allowing'" do
|
|
@@ -40,6 +44,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
40
44
|
matcher = plain_matcher.allowing(%w(image/png image/jpeg))
|
|
41
45
|
|
|
42
46
|
expect(matcher).to accept(Dummy)
|
|
47
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
43
48
|
end
|
|
44
49
|
|
|
45
50
|
it "rejects a class that does not match and a matcher that only specifies 'allowing'" do
|
|
@@ -47,6 +52,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
47
52
|
matcher = plain_matcher.allowing(%w(image/png image/jpeg))
|
|
48
53
|
|
|
49
54
|
expect(matcher).to_not accept(Dummy)
|
|
55
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
50
56
|
end
|
|
51
57
|
|
|
52
58
|
it "accepts a class that matches and a matcher that only specifies 'rejecting'" do
|
|
@@ -54,6 +60,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
54
60
|
matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
|
|
55
61
|
|
|
56
62
|
expect(matcher).to accept(Dummy)
|
|
63
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
57
64
|
end
|
|
58
65
|
|
|
59
66
|
it "rejects a class that does not match and a matcher that only specifies 'rejecting'" do
|
|
@@ -61,6 +68,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
61
68
|
matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
|
|
62
69
|
|
|
63
70
|
expect(matcher).to_not accept(Dummy)
|
|
71
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
64
72
|
end
|
|
65
73
|
|
|
66
74
|
context "using an :if to control the validation" do
|
|
@@ -75,12 +83,14 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
|
75
83
|
dummy = Dummy.new
|
|
76
84
|
dummy.go = true
|
|
77
85
|
expect(matcher).to accept(dummy)
|
|
86
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
78
87
|
end
|
|
79
88
|
|
|
80
89
|
it "does not run the validation if the control is false" do
|
|
81
90
|
dummy = Dummy.new
|
|
82
91
|
dummy.go = false
|
|
83
92
|
expect(matcher).to_not accept(dummy)
|
|
93
|
+
expect { matcher.failure_message }.to_not raise_error
|
|
84
94
|
end
|
|
85
95
|
end
|
|
86
96
|
|
|
@@ -3,32 +3,32 @@ require 'spec_helper'
|
|
|
3
3
|
describe Paperclip::MediaTypeSpoofDetector do
|
|
4
4
|
it 'rejects a file that is named .html and identifies as PNG' do
|
|
5
5
|
file = File.open(fixture_file("5k.png"))
|
|
6
|
-
assert Paperclip::MediaTypeSpoofDetector.using(file, "5k.html").spoofed?
|
|
6
|
+
assert Paperclip::MediaTypeSpoofDetector.using(file, "5k.html", "image/png").spoofed?
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
it 'does not reject a file that is named .jpg and identifies as PNG' do
|
|
10
10
|
file = File.open(fixture_file("5k.png"))
|
|
11
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "5k.jpg").spoofed?
|
|
11
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "5k.jpg", "image/png").spoofed?
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'does not reject a file that is named .html and identifies as HTML' do
|
|
15
15
|
file = File.open(fixture_file("empty.html"))
|
|
16
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html").spoofed?
|
|
16
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "text/html").spoofed?
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it 'does not reject a file that does not have a name' do
|
|
20
20
|
file = File.open(fixture_file("empty.html"))
|
|
21
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "").spoofed?
|
|
21
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "", "text/html").spoofed?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
it 'does not reject a file that does have an extension' do
|
|
25
25
|
file = File.open(fixture_file("empty.html"))
|
|
26
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "data").spoofed?
|
|
26
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "data", "text/html").spoofed?
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
it 'does not reject when the supplied file is an IOAdapter' do
|
|
30
30
|
adapter = Paperclip.io_adapters.for(File.new(fixture_file("5k.png")))
|
|
31
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
|
|
31
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
it 'does not reject when the extension => content_type is in :content_type_mappings' do
|
|
@@ -38,19 +38,42 @@ describe Paperclip::MediaTypeSpoofDetector do
|
|
|
38
38
|
file.puts "Certificate!"
|
|
39
39
|
file.close
|
|
40
40
|
adapter = Paperclip.io_adapters.for(File.new(file.path));
|
|
41
|
-
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename).spoofed?
|
|
41
|
+
assert ! Paperclip::MediaTypeSpoofDetector.using(adapter, adapter.original_filename, adapter.content_type).spoofed?
|
|
42
42
|
ensure
|
|
43
43
|
Paperclip.options[:content_type_mappings] = {}
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
file
|
|
49
|
-
|
|
47
|
+
context "file named .html and is as HTML, but we're told JPG" do
|
|
48
|
+
let(:file) { File.open(fixture_file("empty.html")) }
|
|
49
|
+
let(:spoofed?) { Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "image/jpg").spoofed? }
|
|
50
|
+
|
|
51
|
+
it "rejects the file" do
|
|
52
|
+
assert spoofed?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "logs info about the detected spoof" do
|
|
56
|
+
Paperclip.expects(:log).with('Content Type Spoof: Filename empty.html (image/jpg from Headers, ["text/html"] from Extension), content type discovered from file command: text/html. See documentation to allow this combination.')
|
|
57
|
+
spoofed?
|
|
58
|
+
end
|
|
50
59
|
end
|
|
51
60
|
|
|
52
|
-
it "does not reject
|
|
61
|
+
it "does not reject if content_type is empty but otherwise checks out" do
|
|
53
62
|
file = File.open(fixture_file("empty.html"))
|
|
54
63
|
assert ! Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "").spoofed?
|
|
55
64
|
end
|
|
65
|
+
|
|
66
|
+
it 'does allow array as :content_type_mappings' do
|
|
67
|
+
begin
|
|
68
|
+
Paperclip.options[:content_type_mappings] = {
|
|
69
|
+
html: ['binary', 'text/html']
|
|
70
|
+
}
|
|
71
|
+
file = File.open(fixture_file('empty.html'))
|
|
72
|
+
spoofed = Paperclip::MediaTypeSpoofDetector
|
|
73
|
+
.using(file, "empty.html", "text/html").spoofed?
|
|
74
|
+
assert !spoofed
|
|
75
|
+
ensure
|
|
76
|
+
Paperclip.options[:content_type_mappings] = {}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
56
79
|
end
|
|
@@ -20,7 +20,7 @@ describe Paperclip do
|
|
|
20
20
|
it "saves Cocaine::CommandLine.path that set before" do
|
|
21
21
|
Cocaine::CommandLine.path = "/opt/my_app/bin"
|
|
22
22
|
Paperclip.run("convert", "stuff")
|
|
23
|
-
|
|
23
|
+
expect(Cocaine::CommandLine.path).to match("/opt/my_app/bin")
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "does not duplicate Cocaine::CommandLine.path on multiple runs" do
|
|
@@ -29,7 +29,9 @@ describe Paperclip do
|
|
|
29
29
|
Paperclip.options[:command_path] = "/opt/my_app/bin"
|
|
30
30
|
Paperclip.run("convert", "stuff")
|
|
31
31
|
Paperclip.run("convert", "more_stuff")
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
cmd_path = Paperclip.options[:command_path]
|
|
34
|
+
assert_equal 1, Cocaine::CommandLine.path.scan(cmd_path).count
|
|
33
35
|
end
|
|
34
36
|
end
|
|
35
37
|
|
|
@@ -123,33 +125,6 @@ describe Paperclip do
|
|
|
123
125
|
end
|
|
124
126
|
end
|
|
125
127
|
|
|
126
|
-
if using_protected_attributes?
|
|
127
|
-
context "that is attr_protected" do
|
|
128
|
-
before do
|
|
129
|
-
Dummy.class_eval do
|
|
130
|
-
attr_protected :avatar
|
|
131
|
-
end
|
|
132
|
-
@dummy = Dummy.new
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
it "does not assign the avatar on mass-set" do
|
|
136
|
-
@dummy.attributes = { other: "I'm set!",
|
|
137
|
-
avatar: @file }
|
|
138
|
-
|
|
139
|
-
assert_equal "I'm set!", @dummy.other
|
|
140
|
-
assert ! @dummy.avatar?
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "allows assigment on normal set" do
|
|
144
|
-
@dummy.other = "I'm set!"
|
|
145
|
-
@dummy.avatar = @file
|
|
146
|
-
|
|
147
|
-
assert_equal "I'm set!", @dummy.other
|
|
148
|
-
assert @dummy.avatar?
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
128
|
context "with a subclass" do
|
|
154
129
|
before do
|
|
155
130
|
class ::SubDummy < Dummy; end
|
|
@@ -3,34 +3,35 @@ require 'spec_helper'
|
|
|
3
3
|
describe 'Plural cache' do
|
|
4
4
|
it 'caches pluralizations' do
|
|
5
5
|
cache = Paperclip::Interpolations::PluralCache.new
|
|
6
|
-
|
|
6
|
+
symbol = :box
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
cache.pluralize(word)
|
|
8
|
+
first = cache.pluralize_symbol(symbol)
|
|
9
|
+
second = cache.pluralize_symbol(symbol)
|
|
10
|
+
expect(first).to equal(second)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
it 'caches pluralizations and underscores' do
|
|
14
|
+
class BigBox ; end
|
|
15
15
|
cache = Paperclip::Interpolations::PluralCache.new
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
word.expects(:pluralize).returns(word).once
|
|
19
|
-
word.expects(:underscore).returns(word).once
|
|
16
|
+
klass = BigBox
|
|
20
17
|
|
|
21
|
-
cache.
|
|
22
|
-
cache.
|
|
18
|
+
first = cache.underscore_and_pluralize_class(klass)
|
|
19
|
+
second = cache.underscore_and_pluralize_class(klass)
|
|
20
|
+
expect(first).to equal(second)
|
|
23
21
|
end
|
|
24
22
|
|
|
25
23
|
it 'pluralizes words' do
|
|
26
24
|
cache = Paperclip::Interpolations::PluralCache.new
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
symbol = :box
|
|
26
|
+
|
|
27
|
+
expect(cache.pluralize_symbol(symbol)).to eq("boxes")
|
|
29
28
|
end
|
|
30
29
|
|
|
31
|
-
it 'pluralizes and underscore
|
|
30
|
+
it 'pluralizes and underscore class names' do
|
|
31
|
+
class BigBox ; end
|
|
32
32
|
cache = Paperclip::Interpolations::PluralCache.new
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
klass = BigBox
|
|
34
|
+
|
|
35
|
+
expect(cache.underscore_and_pluralize_class(klass)).to eq("big_boxes")
|
|
35
36
|
end
|
|
36
37
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Paperclip::RailsEnvironment do
|
|
4
|
+
|
|
5
|
+
it "returns nil when Rails isn't defined" do
|
|
6
|
+
resetting_rails_to(nil) do
|
|
7
|
+
expect(Paperclip::RailsEnvironment.get).to be_nil
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "returns nil when Rails.env isn't defined" do
|
|
12
|
+
resetting_rails_to({}) do
|
|
13
|
+
expect(Paperclip::RailsEnvironment.get).to be_nil
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns the value of Rails.env if it is set" do
|
|
18
|
+
resetting_rails_to(OpenStruct.new(env: "foo")) do
|
|
19
|
+
expect(Paperclip::RailsEnvironment.get).to eq "foo"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def resetting_rails_to(new_value)
|
|
24
|
+
begin
|
|
25
|
+
previous_rails = Object.send(:remove_const, "Rails")
|
|
26
|
+
Object.const_set("Rails", new_value) unless new_value.nil?
|
|
27
|
+
yield
|
|
28
|
+
ensure
|
|
29
|
+
Object.send(:remove_const, "Rails") if Object.const_defined?("Rails")
|
|
30
|
+
Object.const_set("Rails", previous_rails)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'fog'
|
|
2
|
+
require 'fog/aws'
|
|
3
|
+
require 'fog/local'
|
|
3
4
|
require 'timecop'
|
|
4
5
|
|
|
5
6
|
describe Paperclip::Storage::Fog do
|
|
@@ -182,6 +183,13 @@ describe Paperclip::Storage::Fog do
|
|
|
182
183
|
tempfile.close
|
|
183
184
|
end
|
|
184
185
|
|
|
186
|
+
it 'is able to be handled when missing while copying to a local file' do
|
|
187
|
+
tempfile = Tempfile.new("known_location")
|
|
188
|
+
tempfile.binmode
|
|
189
|
+
assert_equal false, @dummy.avatar.copy_to_local_file(:original, tempfile.path)
|
|
190
|
+
tempfile.close
|
|
191
|
+
end
|
|
192
|
+
|
|
185
193
|
it "passes the content type to the Fog::Storage::AWS::Files instance" do
|
|
186
194
|
Fog::Storage::AWS::Files.any_instance.expects(:create).with do |hash|
|
|
187
195
|
hash[:content_type]
|
|
@@ -265,6 +273,22 @@ describe Paperclip::Storage::Fog do
|
|
|
265
273
|
end
|
|
266
274
|
end
|
|
267
275
|
|
|
276
|
+
context "with fog_public as a proc" do
|
|
277
|
+
let(:proc) { ->(attachment) { !attachment } }
|
|
278
|
+
|
|
279
|
+
before do
|
|
280
|
+
rebuild_model(@options.merge(fog_public: proc))
|
|
281
|
+
@dummy = Dummy.new
|
|
282
|
+
@dummy.avatar = StringIO.new(".")
|
|
283
|
+
@dummy.save
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it "sets the @fog_public instance variable to false" do
|
|
287
|
+
assert_equal proc, @dummy.avatar.instance_variable_get("@options")[:fog_public]
|
|
288
|
+
assert_equal false, @dummy.avatar.fog_public
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
268
292
|
context "with styles set and fog_public set to false" do
|
|
269
293
|
before do
|
|
270
294
|
rebuild_model(@options.merge(fog_public: false, styles: { medium: "300x300>", thumb: "100x100>" }))
|
|
@@ -320,6 +344,9 @@ describe Paperclip::Storage::Fog do
|
|
|
320
344
|
it "honors the scheme in public url" do
|
|
321
345
|
assert_match(/^http:\/\//, @dummy.avatar.url)
|
|
322
346
|
end
|
|
347
|
+
it "honors the scheme in expiring url" do
|
|
348
|
+
assert_match(/^http:\/\//, @dummy.avatar.expiring_url)
|
|
349
|
+
end
|
|
323
350
|
end
|
|
324
351
|
|
|
325
352
|
context "with scheme not set" do
|
|
@@ -334,15 +361,20 @@ describe Paperclip::Storage::Fog do
|
|
|
334
361
|
it "provides HTTPS public url" do
|
|
335
362
|
assert_match(/^https:\/\//, @dummy.avatar.url)
|
|
336
363
|
end
|
|
364
|
+
it "provides HTTPS expiring url" do
|
|
365
|
+
assert_match(/^https:\/\//, @dummy.avatar.expiring_url)
|
|
366
|
+
end
|
|
337
367
|
end
|
|
338
368
|
|
|
339
369
|
context "with a valid bucket name for a subdomain" do
|
|
370
|
+
before { @dummy.stubs(:new_record?).returns(false) }
|
|
371
|
+
|
|
340
372
|
it "provides an url in subdomain style" do
|
|
341
373
|
assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png/, @dummy.avatar.url)
|
|
342
374
|
end
|
|
343
375
|
|
|
344
376
|
it "provides an url that expires in subdomain style" do
|
|
345
|
-
assert_match(/^
|
|
377
|
+
assert_match(/^https:\/\/papercliptests.s3.amazonaws.com\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
|
|
346
378
|
end
|
|
347
379
|
end
|
|
348
380
|
|
|
@@ -390,7 +422,7 @@ describe Paperclip::Storage::Fog do
|
|
|
390
422
|
end
|
|
391
423
|
|
|
392
424
|
it "provides a url that expires in folder style" do
|
|
393
|
-
assert_match(/^
|
|
425
|
+
assert_match(/^https:\/\/s3.amazonaws.com\/this_is_invalid\/avatars\/5k.png.+Expires=.+$/, @dummy.avatar.expiring_url)
|
|
394
426
|
end
|
|
395
427
|
|
|
396
428
|
end
|
|
@@ -409,6 +441,9 @@ describe Paperclip::Storage::Fog do
|
|
|
409
441
|
assert @connection.directories.get(@dynamic_fog_directory).inspect
|
|
410
442
|
end
|
|
411
443
|
|
|
444
|
+
it "provides an url using dynamic bucket name" do
|
|
445
|
+
assert_match(/^https:\/\/dynamicpaperclip.s3.amazonaws.com\/avatars\/5k.png\?\d*$/, @dummy.avatar.url)
|
|
446
|
+
end
|
|
412
447
|
end
|
|
413
448
|
|
|
414
449
|
context "with a proc for the fog_host evaluating a model method" do
|
|
@@ -475,6 +510,25 @@ describe Paperclip::Storage::Fog do
|
|
|
475
510
|
assert_equal @dummy.avatar.fog_credentials, @dynamic_fog_credentials
|
|
476
511
|
end
|
|
477
512
|
end
|
|
513
|
+
|
|
514
|
+
context "with custom fog_options" do
|
|
515
|
+
before do
|
|
516
|
+
rebuild_model(
|
|
517
|
+
@options.merge(fog_options: { multipart_chunk_size: 104857600 }),
|
|
518
|
+
)
|
|
519
|
+
@dummy = Dummy.new
|
|
520
|
+
@dummy.avatar = @file
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
it "applies the options to the fog #create call" do
|
|
524
|
+
files = stub
|
|
525
|
+
@dummy.avatar.stubs(:directory).returns stub(files: files)
|
|
526
|
+
files.expects(:create).with(
|
|
527
|
+
has_entries(multipart_chunk_size: 104857600),
|
|
528
|
+
)
|
|
529
|
+
@dummy.save
|
|
530
|
+
end
|
|
531
|
+
end
|
|
478
532
|
end
|
|
479
533
|
|
|
480
534
|
end
|
|
@@ -492,6 +546,7 @@ describe Paperclip::Storage::Fog do
|
|
|
492
546
|
@file = File.new(fixture_file('5k.png'), 'rb')
|
|
493
547
|
@dummy = Dummy.new
|
|
494
548
|
@dummy.avatar = @file
|
|
549
|
+
@dummy.stubs(:new_record?).returns(false)
|
|
495
550
|
end
|
|
496
551
|
|
|
497
552
|
after do
|
|
@@ -8,9 +8,10 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
8
8
|
storage: :s3,
|
|
9
9
|
bucket: ENV["S3_BUCKET"],
|
|
10
10
|
path: ":class/:attachment/:id/:style.:extension",
|
|
11
|
+
s3_region: ENV["S3_REGION"],
|
|
11
12
|
s3_credentials: {
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
14
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
@file = File.new(fixture_file("5k.png"))
|
|
@@ -45,9 +46,10 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
45
46
|
storage: :s3,
|
|
46
47
|
bucket: ENV["S3_BUCKET"],
|
|
47
48
|
path: ":class/:attachment/:id/:style.:extension",
|
|
49
|
+
s3_region: ENV["S3_REGION"],
|
|
48
50
|
s3_credentials: {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
52
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
@dummy = Dummy.new
|
|
@@ -64,9 +66,10 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
64
66
|
storage: :s3,
|
|
65
67
|
bucket: ENV["S3_BUCKET"],
|
|
66
68
|
path: ":class/:attachment/:id/:style.:extension",
|
|
69
|
+
s3_region: ENV["S3_REGION"],
|
|
67
70
|
s3_credentials: {
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
72
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
Dummy.delete_all
|
|
@@ -105,9 +108,12 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
105
108
|
rebuild_model styles: { thumb: "100x100", square: "32x32#" },
|
|
106
109
|
storage: :s3,
|
|
107
110
|
bucket: ENV["S3_BUCKET"],
|
|
111
|
+
s3_region: ENV["S3_REGION"],
|
|
112
|
+
url: ":s3_domain_url",
|
|
113
|
+
path: "/:class/:attachment/:id_partition/:style/:filename",
|
|
108
114
|
s3_credentials: {
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
116
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
111
117
|
}
|
|
112
118
|
|
|
113
119
|
Dummy.delete_all
|
|
@@ -136,7 +142,7 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
136
142
|
it "is destroyable" do
|
|
137
143
|
url = @dummy.avatar.url
|
|
138
144
|
@dummy.destroy
|
|
139
|
-
|
|
145
|
+
assert_forbidden_response url
|
|
140
146
|
end
|
|
141
147
|
end
|
|
142
148
|
|
|
@@ -146,12 +152,12 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
146
152
|
storage: :s3,
|
|
147
153
|
bucket: ENV["S3_BUCKET"],
|
|
148
154
|
path: ":class/:attachment/:id/:style.:extension",
|
|
155
|
+
s3_region: ENV["S3_REGION"],
|
|
149
156
|
s3_credentials: {
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
|
158
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
152
159
|
},
|
|
153
|
-
s3_server_side_encryption:
|
|
154
|
-
|
|
160
|
+
s3_server_side_encryption: "AES256"
|
|
155
161
|
Dummy.delete_all
|
|
156
162
|
@dummy = Dummy.new
|
|
157
163
|
end
|
|
@@ -173,7 +179,7 @@ unless ENV["S3_BUCKET"].blank?
|
|
|
173
179
|
end
|
|
174
180
|
|
|
175
181
|
it "is encrypted on S3" do
|
|
176
|
-
assert @dummy.avatar.s3_object.server_side_encryption ==
|
|
182
|
+
assert @dummy.avatar.s3_object.server_side_encryption == "AES256"
|
|
177
183
|
end
|
|
178
184
|
end
|
|
179
185
|
end
|