paperclip 4.1.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -6
  3. data/.travis.yml +4 -13
  4. data/Appraisals +0 -10
  5. data/CONTRIBUTING.md +10 -5
  6. data/Gemfile +8 -4
  7. data/NEWS +1 -1
  8. data/README.md +51 -10
  9. data/Rakefile +6 -8
  10. data/features/basic_integration.feature +5 -5
  11. data/features/step_definitions/attachment_steps.rb +4 -4
  12. data/features/step_definitions/rails_steps.rb +4 -4
  13. data/features/step_definitions/web_steps.rb +2 -2
  14. data/features/support/env.rb +2 -2
  15. data/features/support/fixtures/gemfile.txt +1 -1
  16. data/features/support/rails.rb +2 -1
  17. data/gemfiles/3.2.gemfile +5 -3
  18. data/gemfiles/4.0.gemfile +5 -3
  19. data/gemfiles/4.1.gemfile +5 -3
  20. data/lib/generators/paperclip/paperclip_generator.rb +0 -2
  21. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
  22. data/lib/paperclip.rb +4 -1
  23. data/lib/paperclip/attachment.rb +90 -29
  24. data/lib/paperclip/content_type_detector.rb +1 -1
  25. data/lib/paperclip/geometry_detector_factory.rb +3 -1
  26. data/lib/paperclip/has_attached_file.rb +2 -1
  27. data/lib/paperclip/interpolations.rb +8 -0
  28. data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -1
  29. data/lib/paperclip/io_adapters/data_uri_adapter.rb +1 -1
  30. data/lib/paperclip/io_adapters/stringio_adapter.rb +5 -11
  31. data/lib/paperclip/locales/de.yml +18 -0
  32. data/lib/paperclip/locales/es.yml +18 -0
  33. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  34. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  35. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  36. data/lib/paperclip/media_type_spoof_detector.rb +10 -2
  37. data/lib/paperclip/storage/filesystem.rb +1 -1
  38. data/lib/paperclip/storage/s3.rb +26 -4
  39. data/lib/paperclip/style.rb +1 -1
  40. data/lib/paperclip/thumbnail.rb +6 -6
  41. data/lib/paperclip/validators.rb +5 -3
  42. data/lib/paperclip/validators/attachment_size_validator.rb +7 -3
  43. data/lib/paperclip/version.rb +1 -1
  44. data/lib/tasks/paperclip.rake +1 -2
  45. data/paperclip.gemspec +5 -3
  46. data/shoulda_macros/paperclip.rb +0 -1
  47. data/{test → spec}/database.yml +0 -0
  48. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  49. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +20 -21
  50. data/{test/attachment_registry_test.rb → spec/paperclip/attachment_registry_spec.rb} +10 -11
  51. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +367 -360
  52. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +8 -8
  53. data/{test/file_command_content_type_detector_test.rb → spec/paperclip/file_command_content_type_detector_spec.rb} +5 -5
  54. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  55. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  56. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  57. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +49 -51
  58. data/{test/has_attached_file_test.rb → spec/paperclip/has_attached_file_spec.rb} +18 -27
  59. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +134 -126
  60. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +54 -40
  61. data/{test/io_adapters/abstract_adapter_test.rb → spec/paperclip/io_adapters/abstract_adapter_spec.rb} +21 -10
  62. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +27 -29
  63. data/{test/io_adapters/data_uri_adapter_test.rb → spec/paperclip/io_adapters/data_uri_adapter_spec.rb} +22 -18
  64. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  65. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +32 -28
  66. data/{test/io_adapters/http_url_proxy_adapter_test.rb → spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb} +22 -22
  67. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  68. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  69. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +10 -7
  70. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +16 -17
  71. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +41 -41
  72. data/{test/io_adapters/uri_adapter_test.rb → spec/paperclip/io_adapters/uri_adapter_spec.rb} +22 -22
  73. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  74. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
  75. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  76. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  77. data/{test/media_type_spoof_detector_test.rb → spec/paperclip/media_type_spoof_detector_spec.rb} +13 -8
  78. data/spec/paperclip/meta_class_spec.rb +30 -0
  79. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  80. data/{test/paperclip_test.rb → spec/paperclip/paperclip_spec.rb} +47 -47
  81. data/{test/plural_cache_test.rb → spec/paperclip/plural_cache_spec.rb} +6 -6
  82. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +5 -5
  83. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  84. data/spec/paperclip/schema_spec.rb +206 -0
  85. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  86. data/{test/storage/fog_test.rb → spec/paperclip/storage/fog_spec.rb} +145 -140
  87. data/spec/paperclip/storage/s3_live_spec.rb +182 -0
  88. data/spec/paperclip/storage/s3_spec.rb +1475 -0
  89. data/spec/paperclip/style_spec.rb +255 -0
  90. data/spec/paperclip/tempfile_factory_spec.rb +29 -0
  91. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +107 -107
  92. data/{test/url_generator_test.rb → spec/paperclip/url_generator_spec.rb} +55 -56
  93. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  94. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  95. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +19 -19
  96. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +65 -58
  97. data/{test/validators/media_type_spoof_detection_validator_test.rb → spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb} +8 -8
  98. data/spec/paperclip/validators_spec.rb +164 -0
  99. data/spec/spec_helper.rb +40 -0
  100. data/spec/support/assertions.rb +71 -0
  101. data/spec/support/fake_model.rb +21 -0
  102. data/spec/support/fake_rails.rb +12 -0
  103. data/{test → spec/support}/fixtures/12k.png +0 -0
  104. data/{test → spec/support}/fixtures/50x50.png +0 -0
  105. data/{test → spec/support}/fixtures/5k.png +0 -0
  106. data/{test → spec/support}/fixtures/animated +0 -0
  107. data/{test → spec/support}/fixtures/animated.gif +0 -0
  108. data/{test → spec/support}/fixtures/animated.unknown +0 -0
  109. data/{test → spec/support}/fixtures/bad.png +0 -0
  110. data/{test → spec/support}/fixtures/empty.html +0 -0
  111. data/{test → spec/support}/fixtures/fog.yml +0 -0
  112. data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  113. data/{test → spec/support}/fixtures/s3.yml +0 -0
  114. data/spec/support/fixtures/spaced file.jpg +0 -0
  115. data/test/fixtures/spaced file.png b/data/spec/support/fixtures/spaced → file.png +0 -0
  116. data/{test → spec/support}/fixtures/text.txt +0 -0
  117. data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  118. data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  119. data/spec/support/matchers/accept.rb +5 -0
  120. data/spec/support/matchers/exist.rb +5 -0
  121. data/{test → spec}/support/mock_attachment.rb +0 -0
  122. data/{test → spec}/support/mock_interpolator.rb +0 -0
  123. data/{test → spec}/support/mock_model.rb +0 -0
  124. data/{test → spec}/support/mock_url_generator_builder.rb +0 -0
  125. data/spec/support/model_reconstruction.rb +60 -0
  126. data/spec/support/rails_helpers.rb +7 -0
  127. data/spec/support/test_data.rb +13 -0
  128. data/spec/support/version_helper.rb +9 -0
  129. metadata +256 -210
  130. data/gemfiles/3.0.gemfile +0 -11
  131. data/gemfiles/3.1.gemfile +0 -11
  132. data/test/attachment_definitions_test.rb +0 -13
  133. data/test/filename_cleaner_test.rb +0 -14
  134. data/test/generator_test.rb +0 -84
  135. data/test/geometry_detector_test.rb +0 -24
  136. data/test/helper.rb +0 -239
  137. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  138. data/test/io_adapters/identity_adapter_test.rb +0 -8
  139. data/test/matchers/have_attached_file_matcher_test.rb +0 -25
  140. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -111
  141. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -70
  142. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -87
  143. data/test/meta_class_test.rb +0 -32
  144. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  145. data/test/schema_test.rb +0 -206
  146. data/test/storage/s3_live_test.rb +0 -179
  147. data/test/storage/s3_test.rb +0 -1357
  148. data/test/style_test.rb +0 -251
  149. data/test/tempfile_factory_test.rb +0 -29
  150. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  151. data/test/validators/attachment_file_name_validator_test.rb +0 -162
  152. data/test/validators_test.rb +0 -101
@@ -1,179 +0,0 @@
1
- require './test/helper'
2
- require 'aws'
3
-
4
- unless ENV["S3_BUCKET"].blank?
5
- class S3LiveTest < Test::Unit::TestCase
6
- context "when assigning an S3 attachment directly to another model" do
7
- setup do
8
- @s3_credentials = File.new(fixture_file("s3.yml"))
9
- rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
10
- :storage => :s3,
11
- :bucket => ENV["S3_BUCKET"],
12
- :path => ":class/:attachment/:id/:style.:extension",
13
- :s3_credentials => @s3_credentials
14
-
15
- @file = File.new(fixture_file("5k.png"))
16
- end
17
-
18
- should "not raise any error" do
19
- @attachment = Dummy.new.avatar
20
- @attachment.assign(@file)
21
- @attachment.save
22
-
23
- @attachment2 = Dummy.new.avatar
24
- @attachment2.assign(@file)
25
- @attachment2.save
26
- end
27
-
28
- should "allow assignment from another S3 object" do
29
- @attachment = Dummy.new.avatar
30
- @attachment.assign(@file)
31
- @attachment.save
32
-
33
- @attachment2 = Dummy.new.avatar
34
- @attachment2.assign(@attachment)
35
- @attachment2.save
36
- end
37
-
38
- teardown { [@s3_credentials, @file].each(&:close) }
39
- end
40
-
41
- context "Generating an expiring url on a nonexistant attachment" do
42
- setup do
43
- @s3_credentials = File.new(fixture_file("s3.yml"))
44
- rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
45
- :storage => :s3,
46
- :bucket => ENV["S3_BUCKET"],
47
- :path => ":class/:attachment/:id/:style.:extension",
48
- :s3_credentials => @s3_credentials
49
-
50
- @dummy = Dummy.new
51
- end
52
-
53
- should "return nil" do
54
- assert_nil @dummy.avatar.expiring_url
55
- end
56
- end
57
-
58
- context "Using S3 for real, an attachment with S3 storage" do
59
- setup do
60
- @s3_credentials = File.new(fixture_file("s3.yml"))
61
- rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
62
- :storage => :s3,
63
- :bucket => ENV["S3_BUCKET"],
64
- :path => ":class/:attachment/:id/:style.:extension",
65
- :s3_credentials => @s3_credentials
66
-
67
- Dummy.delete_all
68
- @dummy = Dummy.new
69
- end
70
-
71
- teardown { @s3_credentials.close }
72
-
73
- should "be extended by the S3 module" do
74
- assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
75
- end
76
-
77
- context "when assigned" do
78
- setup do
79
- @file = File.new(fixture_file('5k.png'), 'rb')
80
- @dummy.avatar = @file
81
- end
82
-
83
- teardown do
84
- @file.close
85
- @dummy.destroy
86
- end
87
-
88
- context "and saved" do
89
- setup do
90
- @dummy.save
91
- end
92
-
93
- should "be on S3" do
94
- assert true
95
- end
96
- end
97
- end
98
- end
99
-
100
- context "An attachment that uses S3 for storage and has spaces in file name" do
101
- setup do
102
- @s3_credentials = File.new(fixture_file("s3.yml"))
103
- rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
104
- :storage => :s3,
105
- :bucket => ENV["S3_BUCKET"],
106
- :s3_credentials => @s3_credentials
107
-
108
- Dummy.delete_all
109
- @file = File.new(fixture_file('spaced file.png'), 'rb')
110
- @dummy = Dummy.new
111
- @dummy.avatar = @file
112
- @dummy.save
113
- end
114
-
115
- teardown { @s3_credentials.close }
116
-
117
- should "return a replaced version for path" do
118
- assert_match /.+\/spaced_file\.png/, @dummy.avatar.path
119
- end
120
-
121
- should "return a replaced version for url" do
122
- assert_match /.+\/spaced_file\.png/, @dummy.avatar.url
123
- end
124
-
125
- should "be accessible" do
126
- assert_success_response @dummy.avatar.url
127
- end
128
-
129
- should "be reprocessable" do
130
- assert @dummy.avatar.reprocess!
131
- end
132
-
133
- should "be destroyable" do
134
- url = @dummy.avatar.url
135
- @dummy.destroy
136
- assert_not_found_response url
137
- end
138
- end
139
-
140
- context "An attachment that uses S3 for storage and uses AES256 encryption" do
141
- setup do
142
- @s3_credentials = File.new(fixture_file("s3.yml"))
143
- rebuild_model :styles => { :thumb => "100x100", :square => "32x32#" },
144
- :storage => :s3,
145
- :bucket => ENV["S3_BUCKET"],
146
- :path => ":class/:attachment/:id/:style.:extension",
147
- :s3_credentials => @s3_credentials,
148
- :s3_server_side_encryption => :aes256
149
-
150
- Dummy.delete_all
151
- @dummy = Dummy.new
152
- end
153
-
154
- teardown { @s3_credentials.close }
155
-
156
- context "when assigned" do
157
- setup do
158
- @file = File.new(fixture_file('5k.png'), 'rb')
159
- @dummy.avatar = @file
160
- end
161
-
162
- teardown do
163
- @file.close
164
- @dummy.destroy
165
- end
166
-
167
- context "and saved" do
168
- setup do
169
- @dummy.save
170
- end
171
-
172
- should "be encrypted on S3" do
173
- assert @dummy.avatar.s3_object.server_side_encryption == :aes256
174
- end
175
- end
176
- end
177
- end
178
- end
179
- end
@@ -1,1357 +0,0 @@
1
- require './test/helper'
2
- require 'aws'
3
-
4
- class S3Test < Test::Unit::TestCase
5
- def rails_env(env)
6
- silence_warnings do
7
- Object.const_set(:Rails, stub('Rails', :env => env))
8
- end
9
- end
10
-
11
- def setup
12
- AWS.config(:access_key_id => "TESTKEY", :secret_access_key => "TESTSECRET", :stub_requests => true)
13
- end
14
-
15
- def teardown
16
- AWS.config(:access_key_id => nil, :secret_access_key => nil, :stub_requests => nil)
17
- end
18
-
19
- context "Parsing S3 credentials" do
20
- setup do
21
- @proxy_settings = {:host => "127.0.0.1", :port => 8888, :user => "foo", :password => "bar"}
22
- rebuild_model :storage => :s3,
23
- :bucket => "testing",
24
- :http_proxy => @proxy_settings,
25
- :s3_credentials => {:not => :important}
26
-
27
- @dummy = Dummy.new
28
- @avatar = @dummy.avatar
29
- end
30
-
31
- should "get the correct credentials when RAILS_ENV is production" do
32
- rails_env("production")
33
- assert_equal({:key => "12345"},
34
- @avatar.parse_credentials('production' => {:key => '12345'},
35
- :development => {:key => "54321"}))
36
- end
37
-
38
- should "get the correct credentials when RAILS_ENV is development" do
39
- rails_env("development")
40
- assert_equal({:key => "54321"},
41
- @avatar.parse_credentials('production' => {:key => '12345'},
42
- :development => {:key => "54321"}))
43
- end
44
-
45
- should "return the argument if the key does not exist" do
46
- rails_env("not really an env")
47
- assert_equal({:test => "12345"}, @avatar.parse_credentials(:test => "12345"))
48
- end
49
-
50
- should "support HTTP proxy settings" do
51
- rails_env("development")
52
- assert_equal(true, @avatar.using_http_proxy?)
53
- assert_equal(@proxy_settings[:host], @avatar.http_proxy_host)
54
- assert_equal(@proxy_settings[:port], @avatar.http_proxy_port)
55
- assert_equal(@proxy_settings[:user], @avatar.http_proxy_user)
56
- assert_equal(@proxy_settings[:password], @avatar.http_proxy_password)
57
- end
58
-
59
- end
60
-
61
- context ":bucket option via :s3_credentials" do
62
-
63
- setup do
64
- rebuild_model :storage => :s3, :s3_credentials => {:bucket => 'testing'}
65
- @dummy = Dummy.new
66
- end
67
-
68
- should "populate #bucket_name" do
69
- assert_equal @dummy.avatar.bucket_name, 'testing'
70
- end
71
-
72
- end
73
-
74
- context ":bucket option" do
75
-
76
- setup do
77
- rebuild_model :storage => :s3, :bucket => "testing", :s3_credentials => {}
78
- @dummy = Dummy.new
79
- end
80
-
81
- should "populate #bucket_name" do
82
- assert_equal @dummy.avatar.bucket_name, 'testing'
83
- end
84
-
85
- end
86
-
87
- context "missing :bucket option" do
88
-
89
- setup do
90
- rebuild_model :storage => :s3,
91
- :http_proxy => @proxy_settings,
92
- :s3_credentials => {:not => :important}
93
-
94
- @dummy = Dummy.new
95
- @dummy.avatar = stringy_file
96
-
97
- end
98
-
99
- should "raise an argument error" do
100
- exception = assert_raise(ArgumentError) { @dummy.save }
101
- assert_match /missing required :bucket option/, exception.message
102
- end
103
-
104
- end
105
-
106
- context "" do
107
- setup do
108
- rebuild_model :storage => :s3,
109
- :s3_credentials => {},
110
- :bucket => "bucket",
111
- :path => ":attachment/:basename.:extension",
112
- :url => ":s3_path_url"
113
- @dummy = Dummy.new
114
- @dummy.avatar = stringy_file
115
- end
116
-
117
- should "return a url based on an S3 path" do
118
- assert_match %r{^http://s3.amazonaws.com/bucket/avatars/data.txt}, @dummy.avatar.url
119
- end
120
-
121
- should "use the correct bucket" do
122
- assert_equal "bucket", @dummy.avatar.s3_bucket.name
123
- end
124
-
125
- should "use the correct key" do
126
- assert_equal "avatars/data.txt", @dummy.avatar.s3_object.key
127
- end
128
- end
129
-
130
- context "s3_protocol" do
131
- ["http", :http, ""].each do |protocol|
132
- context "as #{protocol.inspect}" do
133
- setup do
134
- rebuild_model :storage => :s3, :s3_protocol => protocol
135
-
136
- @dummy = Dummy.new
137
- end
138
-
139
- should "return the s3_protocol in string" do
140
- assert_equal protocol.to_s, @dummy.avatar.s3_protocol
141
- end
142
- end
143
- end
144
- end
145
-
146
- context ":s3_protocol => 'https'" do
147
- setup do
148
- rebuild_model :storage => :s3,
149
- :s3_credentials => {},
150
- :s3_protocol => 'https',
151
- :bucket => "bucket",
152
- :path => ":attachment/:basename.:extension"
153
- @dummy = Dummy.new
154
- @dummy.avatar = stringy_file
155
- end
156
-
157
- should "return a url based on an S3 path" do
158
- assert_match %r{^https://s3.amazonaws.com/bucket/avatars/data.txt}, @dummy.avatar.url
159
- end
160
- end
161
-
162
- context ":s3_protocol => :https" do
163
- setup do
164
- rebuild_model :storage => :s3,
165
- :s3_credentials => {},
166
- :s3_protocol => :https,
167
- :bucket => "bucket",
168
- :path => ":attachment/:basename.:extension"
169
- @dummy = Dummy.new
170
- @dummy.avatar = stringy_file
171
- end
172
-
173
- should "return a url based on an S3 path" do
174
- assert_match %r{^https://s3.amazonaws.com/bucket/avatars/data.txt}, @dummy.avatar.url
175
- end
176
- end
177
-
178
- context ":s3_protocol => ''" do
179
- setup do
180
- rebuild_model :storage => :s3,
181
- :s3_credentials => {},
182
- :s3_protocol => '',
183
- :bucket => "bucket",
184
- :path => ":attachment/:basename.:extension"
185
- @dummy = Dummy.new
186
- @dummy.avatar = stringy_file
187
- end
188
-
189
- should "return a url based on an S3 path" do
190
- assert_match %r{^//s3.amazonaws.com/bucket/avatars/data.txt}, @dummy.avatar.url
191
- end
192
- end
193
-
194
- context "An attachment that uses S3 for storage and has the style in the path" do
195
- setup do
196
- rebuild_model :storage => :s3,
197
- :bucket => "testing",
198
- :path => ":attachment/:style/:basename.:extension",
199
- :styles => {
200
- :thumb => "80x80>"
201
- },
202
- :s3_credentials => {
203
- 'access_key_id' => "12345",
204
- 'secret_access_key' => "54321"
205
- }
206
-
207
- @dummy = Dummy.new
208
- @dummy.avatar = stringy_file
209
- @avatar = @dummy.avatar
210
- end
211
-
212
- should "use an S3 object based on the correct path for the default style" do
213
- assert_equal("avatars/original/data.txt", @dummy.avatar.s3_object.key)
214
- end
215
-
216
- should "use an S3 object based on the correct path for the custom style" do
217
- assert_equal("avatars/thumb/data.txt", @dummy.avatar.s3_object(:thumb).key)
218
- end
219
- end
220
-
221
- context "s3_host_name" do
222
- setup do
223
- rebuild_model :storage => :s3,
224
- :s3_credentials => {},
225
- :bucket => "bucket",
226
- :path => ":attachment/:basename.:extension",
227
- :s3_host_name => "s3-ap-northeast-1.amazonaws.com"
228
- @dummy = Dummy.new
229
- @dummy.avatar = stringy_file
230
- end
231
-
232
- should "return a url based on an :s3_host_name path" do
233
- assert_match %r{^http://s3-ap-northeast-1.amazonaws.com/bucket/avatars/data.txt}, @dummy.avatar.url
234
- end
235
-
236
- should "use the S3 bucket with the correct host name" do
237
- assert_equal "s3-ap-northeast-1.amazonaws.com", @dummy.avatar.s3_bucket.config.s3_endpoint
238
- end
239
- end
240
-
241
- context "dynamic s3_host_name" do
242
- setup do
243
- rebuild_model :storage => :s3,
244
- :s3_credentials => {},
245
- :bucket => "bucket",
246
- :path => ":attachment/:basename.:extension",
247
- :s3_host_name => lambda {|a| a.instance.value }
248
- @dummy = Dummy.new
249
- class << @dummy
250
- attr_accessor :value
251
- end
252
- @dummy.avatar = stringy_file
253
- end
254
-
255
- should "use s3_host_name as a proc if available" do
256
- @dummy.value = "s3.something.com"
257
- assert_equal "http://s3.something.com/bucket/avatars/data.txt", @dummy.avatar.url(:original, :timestamp => false)
258
- end
259
- end
260
-
261
- context "An attachment that uses S3 for storage and has styles that return different file types" do
262
- setup do
263
- rebuild_model :styles => { :large => ['500x500#', :jpg] },
264
- :storage => :s3,
265
- :bucket => "bucket",
266
- :path => ":attachment/:basename.:extension",
267
- :s3_credentials => {
268
- 'access_key_id' => "12345",
269
- 'secret_access_key' => "54321"
270
- }
271
-
272
- File.open(fixture_file('5k.png'), 'rb') do |file|
273
- @dummy = Dummy.new
274
- @dummy.avatar = file
275
- end
276
- end
277
-
278
- should "return a url containing the correct original file mime type" do
279
- assert_match /.+\/5k.png/, @dummy.avatar.url
280
- end
281
-
282
- should 'use the correct key for the original file mime type' do
283
- assert_match /.+\/5k.png/, @dummy.avatar.s3_object.key
284
- end
285
-
286
- should "return a url containing the correct processed file mime type" do
287
- assert_match /.+\/5k.jpg/, @dummy.avatar.url(:large)
288
- end
289
-
290
- should "use the correct key for the processed file mime type" do
291
- assert_match /.+\/5k.jpg/, @dummy.avatar.s3_object(:large).key
292
- end
293
- end
294
-
295
- context "An attachment that uses S3 for storage and has a proc for styles" do
296
- setup do
297
- rebuild_model :styles => lambda { |attachment| attachment.instance.counter; {:thumbnail => { :geometry => "50x50#", :s3_headers => {'Cache-Control' => 'max-age=31557600'}} }},
298
- :storage => :s3,
299
- :bucket => "bucket",
300
- :path => ":attachment/:style/:basename.:extension",
301
- :s3_credentials => {
302
- 'access_key_id' => "12345",
303
- 'secret_access_key' => "54321"
304
- }
305
-
306
- @file = File.new(fixture_file('5k.png'), 'rb')
307
-
308
- Dummy.class_eval do
309
- def counter
310
- @counter ||= 0
311
- @counter += 1
312
- @counter
313
- end
314
- end
315
-
316
- @dummy = Dummy.new
317
- @dummy.avatar = @file
318
-
319
- object = stub
320
- @dummy.avatar.stubs(:s3_object).with(:original).returns(object)
321
- @dummy.avatar.stubs(:s3_object).with(:thumbnail).returns(object)
322
- object.expects(:write).with(anything, :content_type => 'image/png', :acl => :public_read)
323
- object.expects(:write).with(anything, :content_type => 'image/png', :acl => :public_read, :cache_control => 'max-age=31557600')
324
- @dummy.save
325
- end
326
-
327
- teardown { @file.close }
328
-
329
- should "succeed" do
330
- assert_equal @dummy.counter, 7
331
- end
332
- end
333
-
334
- context "An attachment that uses S3 for storage and has spaces in file name" do
335
- setup do
336
- rebuild_model :styles => { :large => ['500x500#', :jpg] },
337
- :storage => :s3,
338
- :bucket => "bucket",
339
- :s3_credentials => {
340
- 'access_key_id' => "12345",
341
- 'secret_access_key' => "54321"
342
- }
343
-
344
- File.open(fixture_file('spaced file.png'), 'rb') do |file|
345
- @dummy = Dummy.new
346
- @dummy.avatar = file
347
- end
348
- end
349
-
350
- should "return a replaced version for path" do
351
- assert_match /.+\/spaced_file\.png/, @dummy.avatar.path
352
- end
353
-
354
- should "return a replaced version for url" do
355
- assert_match /.+\/spaced_file\.png/, @dummy.avatar.url
356
- end
357
- end
358
-
359
- context "An attachment that uses S3 for storage and has a question mark in file name" do
360
- setup do
361
- rebuild_model :styles => { :large => ['500x500#', :jpg] },
362
- :storage => :s3,
363
- :bucket => "bucket",
364
- :s3_credentials => {
365
- 'access_key_id' => "12345",
366
- 'secret_access_key' => "54321"
367
- }
368
-
369
- stringio = stringy_file
370
- class << stringio
371
- def original_filename
372
- "question?mark.png"
373
- end
374
- end
375
- file = Paperclip.io_adapters.for(stringio)
376
- @dummy = Dummy.new
377
- @dummy.avatar = file
378
- @dummy.save
379
- end
380
-
381
- should "return a replaced version for path" do
382
- assert_match /.+\/question_mark\.png/, @dummy.avatar.path
383
- end
384
-
385
- should "return a replaced version for url" do
386
- assert_match /.+\/question_mark\.png/, @dummy.avatar.url
387
- end
388
- end
389
-
390
- context "" do
391
- setup do
392
- rebuild_model :storage => :s3,
393
- :s3_credentials => {},
394
- :bucket => "bucket",
395
- :path => ":attachment/:basename.:extension",
396
- :url => ":s3_domain_url"
397
- @dummy = Dummy.new
398
- @dummy.avatar = stringy_file
399
- end
400
-
401
- should "return a url based on an S3 subdomain" do
402
- assert_match %r{^http://bucket.s3.amazonaws.com/avatars/data.txt}, @dummy.avatar.url
403
- end
404
- end
405
-
406
- context "" do
407
- setup do
408
- rebuild_model :storage => :s3,
409
- :s3_credentials => {
410
- :production => { :bucket => "prod_bucket" },
411
- :development => { :bucket => "dev_bucket" }
412
- },
413
- :s3_host_alias => "something.something.com",
414
- :path => ":attachment/:basename.:extension",
415
- :url => ":s3_alias_url"
416
- @dummy = Dummy.new
417
- @dummy.avatar = stringy_file
418
- end
419
-
420
- should "return a url based on the host_alias" do
421
- assert_match %r{^http://something.something.com/avatars/data.txt}, @dummy.avatar.url
422
- end
423
- end
424
-
425
- context "generating a url with a proc as the host alias" do
426
- setup do
427
- rebuild_model :storage => :s3,
428
- :s3_credentials => { :bucket => "prod_bucket" },
429
- :s3_host_alias => Proc.new{|atch| "cdn#{atch.instance.counter % 4}.example.com"},
430
- :path => ":attachment/:basename.:extension",
431
- :url => ":s3_alias_url"
432
- Dummy.class_eval do
433
- def counter
434
- @counter ||= 0
435
- @counter += 1
436
- @counter
437
- end
438
- end
439
- @dummy = Dummy.new
440
- @dummy.avatar = stringy_file
441
- end
442
-
443
- should "return a url based on the host_alias" do
444
- assert_match %r{^http://cdn1.example.com/avatars/data.txt}, @dummy.avatar.url
445
- assert_match %r{^http://cdn2.example.com/avatars/data.txt}, @dummy.avatar.url
446
- end
447
-
448
- should "still return the bucket name" do
449
- assert_equal "prod_bucket", @dummy.avatar.bucket_name
450
- end
451
-
452
- end
453
-
454
- context "" do
455
- setup do
456
- rebuild_model :storage => :s3,
457
- :s3_credentials => {},
458
- :bucket => "bucket",
459
- :path => ":attachment/:basename.:extension",
460
- :url => ":asset_host"
461
- @dummy = Dummy.new
462
- @dummy.avatar = stringy_file
463
- end
464
-
465
- should "return a relative URL for Rails to calculate assets host" do
466
- assert_match %r{^avatars/data\.txt}, @dummy.avatar.url
467
- end
468
-
469
- end
470
-
471
- context "Generating a secure url with an expiration" do
472
- setup do
473
- @build_model_with_options = lambda {|options|
474
- base_options = {
475
- :storage => :s3,
476
- :s3_credentials => {
477
- :production => { :bucket => "prod_bucket" },
478
- :development => { :bucket => "dev_bucket" }
479
- },
480
- :s3_host_alias => "something.something.com",
481
- :s3_permissions => "private",
482
- :path => ":attachment/:basename.:extension",
483
- :url => ":s3_alias_url"
484
- }
485
-
486
- rebuild_model base_options.merge(options)
487
- }
488
- end
489
-
490
- should "use default options" do
491
- @build_model_with_options[{}]
492
-
493
- rails_env("production")
494
-
495
- @dummy = Dummy.new
496
- @dummy.avatar = stringy_file
497
-
498
- object = stub
499
- @dummy.avatar.stubs(:s3_object).returns(object)
500
- object.expects(:url_for).with(:read, :expires => 3600, :secure => true)
501
-
502
- @dummy.avatar.expiring_url
503
- end
504
-
505
- should "allow overriding s3_url_options" do
506
- @build_model_with_options[:s3_url_options => { :response_content_disposition => "inline" }]
507
-
508
- rails_env("production")
509
-
510
- @dummy = Dummy.new
511
- @dummy.avatar = stringy_file
512
-
513
- object = stub
514
- @dummy.avatar.stubs(:s3_object).returns(object)
515
- object.expects(:url_for).with(:read, :expires => 3600, :secure => true, :response_content_disposition => "inline")
516
-
517
- @dummy.avatar.expiring_url
518
- end
519
-
520
- should "allow overriding s3_object options with a proc" do
521
- @build_model_with_options[:s3_url_options => lambda {|attachment| { :response_content_type => attachment.avatar_content_type } }]
522
-
523
- rails_env("production")
524
-
525
- @dummy = Dummy.new
526
-
527
- @file = stringy_file
528
- @file.stubs(:original_filename).returns("5k.png\n\n")
529
- Paperclip.stubs(:run).returns('image/png')
530
- @file.stubs(:content_type).returns("image/png\n\n")
531
- @file.stubs(:to_tempfile).returns(@file)
532
-
533
- @dummy.avatar = @file
534
-
535
- object = stub
536
- @dummy.avatar.stubs(:s3_object).returns(object)
537
- object.expects(:url_for).with(:read, :expires => 3600, :secure => true, :response_content_type => "image/png")
538
-
539
- @dummy.avatar.expiring_url
540
- end
541
- end
542
-
543
- context "#expiring_url" do
544
- setup { @dummy = Dummy.new }
545
-
546
- context "with no attachment" do
547
- setup { assert(!@dummy.avatar.exists?) }
548
-
549
- should "return the default URL" do
550
- assert_equal(@dummy.avatar.url, @dummy.avatar.expiring_url)
551
- end
552
-
553
- should 'generate a url for a style when a file does not exist' do
554
- assert_equal(@dummy.avatar.url(:thumb), @dummy.avatar.expiring_url(3600, :thumb))
555
- end
556
- end
557
-
558
- should "generate the same url when using Times and Integer offsets" do
559
- assert_equal @dummy.avatar.expiring_url(1234), @dummy.avatar.expiring_url(Time.now + 1234)
560
- end
561
- end
562
-
563
- context "Generating a url with an expiration for each style" do
564
- setup do
565
- rebuild_model :storage => :s3,
566
- :s3_credentials => {
567
- :production => { :bucket => "prod_bucket" },
568
- :development => { :bucket => "dev_bucket" }
569
- },
570
- :s3_permissions => :private,
571
- :s3_host_alias => "something.something.com",
572
- :path => ":attachment/:style/:basename.:extension",
573
- :url => ":s3_alias_url"
574
-
575
- rails_env("production")
576
-
577
- @dummy = Dummy.new
578
- @dummy.avatar = stringy_file
579
- end
580
-
581
- should "should generate a url for the thumb" do
582
- object = stub
583
- @dummy.avatar.stubs(:s3_object).with(:thumb).returns(object)
584
- object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
585
- @dummy.avatar.expiring_url(1800, :thumb)
586
- end
587
-
588
- should "should generate a url for the default style" do
589
- object = stub
590
- @dummy.avatar.stubs(:s3_object).with(:original).returns(object)
591
- object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
592
- @dummy.avatar.expiring_url(1800)
593
- end
594
- end
595
-
596
- context "Parsing S3 credentials with a bucket in them" do
597
- setup do
598
- rebuild_model :storage => :s3,
599
- :s3_credentials => {
600
- :production => { :bucket => "prod_bucket" },
601
- :development => { :bucket => "dev_bucket" }
602
- }
603
- @dummy = Dummy.new
604
- end
605
-
606
- should "get the right bucket in production" do
607
- rails_env("production")
608
- assert_equal "prod_bucket", @dummy.avatar.bucket_name
609
- assert_equal "prod_bucket", @dummy.avatar.s3_bucket.name
610
- end
611
-
612
- should "get the right bucket in development" do
613
- rails_env("development")
614
- assert_equal "dev_bucket", @dummy.avatar.bucket_name
615
- assert_equal "dev_bucket", @dummy.avatar.s3_bucket.name
616
- end
617
- end
618
-
619
- context "Parsing S3 credentials with a s3_host_name in them" do
620
- setup do
621
- rebuild_model :storage => :s3,
622
- :bucket => 'testing',
623
- :s3_credentials => {
624
- :production => { :s3_host_name => "s3-world-end.amazonaws.com" },
625
- :development => { :s3_host_name => "s3-ap-northeast-1.amazonaws.com" }
626
- }
627
- @dummy = Dummy.new
628
- end
629
-
630
- should "get the right s3_host_name in production" do
631
- rails_env("production")
632
- assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_host_name
633
- assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
634
- end
635
-
636
- should "get the right s3_host_name in development" do
637
- rails_env("development")
638
- assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_host_name
639
- assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
640
- end
641
-
642
- should "get the right s3_host_name if the key does not exist" do
643
- rails_env("test")
644
- assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_host_name
645
- assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
646
- end
647
- end
648
-
649
- context "An attachment with S3 storage" do
650
- setup do
651
- rebuild_model :storage => :s3,
652
- :bucket => "testing",
653
- :path => ":attachment/:style/:basename.:extension",
654
- :s3_credentials => {
655
- 'access_key_id' => "12345",
656
- 'secret_access_key' => "54321"
657
- }
658
- end
659
-
660
- should "be extended by the S3 module" do
661
- assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
662
- end
663
-
664
- should "not be extended by the Filesystem module" do
665
- assert ! Dummy.new.avatar.is_a?(Paperclip::Storage::Filesystem)
666
- end
667
-
668
- context "when assigned" do
669
- setup do
670
- @file = File.new(fixture_file('5k.png'), 'rb')
671
- @dummy = Dummy.new
672
- @dummy.avatar = @file
673
- end
674
-
675
- teardown { @file.close }
676
-
677
- should "not get a bucket to get a URL" do
678
- @dummy.avatar.expects(:s3).never
679
- @dummy.avatar.expects(:s3_bucket).never
680
- assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
681
- end
682
-
683
- should "be rewinded after flush_writes" do
684
- @dummy.avatar.instance_eval "def after_flush_writes; end"
685
-
686
- files = @dummy.avatar.queued_for_write.values.each(&:read)
687
- @dummy.save
688
- assert files.none?(&:eof?), "Expect all the files to be rewinded."
689
- end
690
-
691
- should "be removed after after_flush_writes" do
692
- paths = @dummy.avatar.queued_for_write.values.map(&:path)
693
- @dummy.save
694
- assert paths.none?{ |path| File.exists?(path) },
695
- "Expect all the files to be deleted."
696
- end
697
-
698
- context "and saved" do
699
- setup do
700
- object = stub
701
- @dummy.avatar.stubs(:s3_object).returns(object)
702
- object.expects(:write).with(anything,
703
- :content_type => "image/png",
704
- :acl => :public_read)
705
- @dummy.save
706
- end
707
-
708
- should "succeed" do
709
- assert true
710
- end
711
- end
712
-
713
- context "and saved without a bucket" do
714
- setup do
715
- AWS::S3::BucketCollection.any_instance.expects(:create).with("testing")
716
- AWS::S3::S3Object.any_instance.stubs(:write).
717
- raises(AWS::S3::Errors::NoSuchBucket.new(stub,
718
- stub(:status => 404,
719
- :body => "<foo/>"))).
720
- then.returns(nil)
721
- @dummy.save
722
- end
723
-
724
- should "succeed" do
725
- assert true
726
- end
727
- end
728
-
729
- context "and remove" do
730
- setup do
731
- AWS::S3::S3Object.any_instance.stubs(:exists?).returns(true)
732
- AWS::S3::S3Object.any_instance.stubs(:delete)
733
- @dummy.destroy
734
- end
735
-
736
- should "succeed" do
737
- assert true
738
- end
739
- end
740
-
741
- context 'that the file were missing' do
742
- setup do
743
- AWS::S3::S3Object.any_instance.stubs(:exists?).raises(AWS::Errors::Base)
744
- end
745
-
746
- should 'return false on exists?' do
747
- assert !@dummy.avatar.exists?
748
- end
749
- end
750
- end
751
- end
752
-
753
- context "An attachment with S3 storage and bucket defined as a Proc" do
754
- setup do
755
- rebuild_model :storage => :s3,
756
- :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
757
- :s3_credentials => {:not => :important}
758
- end
759
-
760
- should "get the right bucket name" do
761
- assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
762
- assert "bucket_a", Dummy.new(:other => 'a').avatar.s3_bucket.name
763
- assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
764
- assert "bucket_b", Dummy.new(:other => 'b').avatar.s3_bucket.name
765
- end
766
- end
767
-
768
- context "An attachment with S3 storage and S3 credentials defined as a Proc" do
769
- setup do
770
- rebuild_model :storage => :s3,
771
- :bucket => {:not => :important},
772
- :s3_credentials => lambda { |attachment|
773
- Hash['access_key_id' => "access#{attachment.instance.other}", 'secret_access_key' => "secret#{attachment.instance.other}"]
774
- }
775
- end
776
-
777
- should "get the right credentials" do
778
- assert "access1234", Dummy.new(:other => '1234').avatar.s3_credentials[:access_key_id]
779
- assert "secret1234", Dummy.new(:other => '1234').avatar.s3_credentials[:secret_access_key]
780
- end
781
- end
782
-
783
- context "An attachment with S3 storage and S3 credentials with a :credential_provider" do
784
- setup do
785
- class DummyCredentialProvider; end
786
-
787
- rebuild_model :storage => :s3,
788
- :bucket => "testing",
789
- :s3_credentials => {
790
- :credential_provider => DummyCredentialProvider.new
791
- }
792
- @dummy = Dummy.new
793
- end
794
-
795
- should "set the credential-provider" do
796
- assert_kind_of DummyCredentialProvider, @dummy.avatar.s3_bucket.config.credential_provider
797
- end
798
- end
799
-
800
- context "An attachment with S3 storage and S3 credentials in an unsupported manor" do
801
- setup do
802
- rebuild_model :storage => :s3, :bucket => "testing", :s3_credentials => ["unsupported"]
803
- @dummy = Dummy.new
804
- end
805
-
806
- should "not accept the credentials" do
807
- assert_raise(ArgumentError) do
808
- @dummy.avatar.s3_credentials
809
- end
810
- end
811
- end
812
-
813
- context "An attachment with S3 storage and S3 credentials not supplied" do
814
- setup do
815
- rebuild_model :storage => :s3, :bucket => "testing"
816
- @dummy = Dummy.new
817
- end
818
-
819
- should "not parse any credentials" do
820
- assert_equal({}, @dummy.avatar.s3_credentials)
821
- end
822
- end
823
-
824
- context "An attachment with S3 storage and specific s3 headers set" do
825
- setup do
826
- rebuild_model :storage => :s3,
827
- :bucket => "testing",
828
- :path => ":attachment/:style/:basename.:extension",
829
- :s3_credentials => {
830
- 'access_key_id' => "12345",
831
- 'secret_access_key' => "54321"
832
- },
833
- :s3_headers => {'Cache-Control' => 'max-age=31557600'}
834
- end
835
-
836
- context "when assigned" do
837
- setup do
838
- @file = File.new(fixture_file('5k.png'), 'rb')
839
- @dummy = Dummy.new
840
- @dummy.avatar = @file
841
- end
842
-
843
- teardown { @file.close }
844
-
845
- context "and saved" do
846
- setup do
847
- object = stub
848
- @dummy.avatar.stubs(:s3_object).returns(object)
849
- object.expects(:write).with(anything,
850
- :content_type => "image/png",
851
- :acl => :public_read,
852
- :cache_control => 'max-age=31557600')
853
- @dummy.save
854
- end
855
-
856
- should "succeed" do
857
- assert true
858
- end
859
- end
860
- end
861
- end
862
-
863
- context "An attachment with S3 storage and metadata set using header names" do
864
- setup do
865
- rebuild_model :storage => :s3,
866
- :bucket => "testing",
867
- :path => ":attachment/:style/:basename.:extension",
868
- :s3_credentials => {
869
- 'access_key_id' => "12345",
870
- 'secret_access_key' => "54321"
871
- },
872
- :s3_headers => {'x-amz-meta-color' => 'red'}
873
- end
874
-
875
- context "when assigned" do
876
- setup do
877
- @file = File.new(fixture_file('5k.png'), 'rb')
878
- @dummy = Dummy.new
879
- @dummy.avatar = @file
880
- end
881
-
882
- teardown { @file.close }
883
-
884
- context "and saved" do
885
- setup do
886
- object = stub
887
- @dummy.avatar.stubs(:s3_object).returns(object)
888
- object.expects(:write).with(anything,
889
- :content_type => "image/png",
890
- :acl => :public_read,
891
- :metadata => { "color" => "red" })
892
- @dummy.save
893
- end
894
-
895
- should "succeed" do
896
- assert true
897
- end
898
- end
899
- end
900
- end
901
-
902
- context "An attachment with S3 storage and metadata set using the :s3_metadata option" do
903
- setup do
904
- rebuild_model :storage => :s3,
905
- :bucket => "testing",
906
- :path => ":attachment/:style/:basename.:extension",
907
- :s3_credentials => {
908
- 'access_key_id' => "12345",
909
- 'secret_access_key' => "54321"
910
- },
911
- :s3_metadata => { "color" => "red" }
912
- end
913
-
914
- context "when assigned" do
915
- setup do
916
- @file = File.new(fixture_file('5k.png'), 'rb')
917
- @dummy = Dummy.new
918
- @dummy.avatar = @file
919
- end
920
-
921
- teardown { @file.close }
922
-
923
- context "and saved" do
924
- setup do
925
- object = stub
926
- @dummy.avatar.stubs(:s3_object).returns(object)
927
- object.expects(:write).with(anything,
928
- :content_type => "image/png",
929
- :acl => :public_read,
930
- :metadata => { "color" => "red" })
931
- @dummy.save
932
- end
933
-
934
- should "succeed" do
935
- assert true
936
- end
937
- end
938
- end
939
- end
940
-
941
- context "An attachment with S3 storage and storage class set using the header name" do
942
- setup do
943
- rebuild_model :storage => :s3,
944
- :bucket => "testing",
945
- :path => ":attachment/:style/:basename.:extension",
946
- :s3_credentials => {
947
- 'access_key_id' => "12345",
948
- 'secret_access_key' => "54321"
949
- },
950
- :s3_headers => { "x-amz-storage-class" => "reduced_redundancy" }
951
- end
952
-
953
- context "when assigned" do
954
- setup do
955
- @file = File.new(fixture_file('5k.png'), 'rb')
956
- @dummy = Dummy.new
957
- @dummy.avatar = @file
958
- end
959
-
960
- teardown { @file.close }
961
-
962
- context "and saved" do
963
- setup do
964
- object = stub
965
- @dummy.avatar.stubs(:s3_object).returns(object)
966
- object.expects(:write).with(anything,
967
- :content_type => "image/png",
968
- :acl => :public_read,
969
- :storage_class => "reduced_redundancy")
970
- @dummy.save
971
- end
972
-
973
- should "succeed" do
974
- assert true
975
- end
976
- end
977
- end
978
- end
979
-
980
- context "Can disable AES256 encryption multiple ways" do
981
- [nil, false, ''].each do |tech|
982
- setup do
983
- rebuild_model(
984
- :storage => :s3,
985
- :bucket => "testing",
986
- :path => ":attachment/:style/:basename.:extension",
987
- :s3_credentials => {
988
- 'access_key_id' => "12345",
989
- 'secret_access_key' => "54321"},
990
- :s3_server_side_encryption => tech)
991
- end
992
-
993
- context "when assigned" do
994
- setup do
995
- @file = File.new(fixture_file('5k.png'), 'rb')
996
- @dummy = Dummy.new
997
- @dummy.avatar = @file
998
- end
999
-
1000
- teardown { @file.close }
1001
-
1002
- context "and saved" do
1003
- setup do
1004
- object = stub
1005
- @dummy.avatar.stubs(:s3_object).returns(object)
1006
- object.expects(:write).with(anything,
1007
- :content_type => "image/png",
1008
- :acl => :public_read)
1009
- @dummy.save
1010
- end
1011
-
1012
- should "succeed" do
1013
- assert true
1014
- end
1015
- end
1016
- end
1017
- end
1018
- end
1019
-
1020
- context "An attachment with S3 storage and using AES256 encryption" do
1021
- setup do
1022
- rebuild_model :storage => :s3,
1023
- :bucket => "testing",
1024
- :path => ":attachment/:style/:basename.:extension",
1025
- :s3_credentials => {
1026
- 'access_key_id' => "12345",
1027
- 'secret_access_key' => "54321"
1028
- },
1029
- :s3_server_side_encryption => :aes256
1030
- end
1031
-
1032
- context "when assigned" do
1033
- setup do
1034
- @file = File.new(fixture_file('5k.png'), 'rb')
1035
- @dummy = Dummy.new
1036
- @dummy.avatar = @file
1037
- end
1038
-
1039
- teardown { @file.close }
1040
-
1041
- context "and saved" do
1042
- setup do
1043
- object = stub
1044
- @dummy.avatar.stubs(:s3_object).returns(object)
1045
- object.expects(:write).with(anything,
1046
- :content_type => "image/png",
1047
- :acl => :public_read,
1048
- :server_side_encryption => 'AES256')
1049
- @dummy.save
1050
- end
1051
-
1052
- should "succeed" do
1053
- assert true
1054
- end
1055
- end
1056
- end
1057
- end
1058
-
1059
- context "An attachment with S3 storage and storage class set using the :storage_class option" do
1060
- setup do
1061
- rebuild_model :storage => :s3,
1062
- :bucket => "testing",
1063
- :path => ":attachment/:style/:basename.:extension",
1064
- :s3_credentials => {
1065
- 'access_key_id' => "12345",
1066
- 'secret_access_key' => "54321"
1067
- },
1068
- :s3_storage_class => :reduced_redundancy
1069
- end
1070
-
1071
- context "when assigned" do
1072
- setup do
1073
- @file = File.new(fixture_file('5k.png'), 'rb')
1074
- @dummy = Dummy.new
1075
- @dummy.avatar = @file
1076
- end
1077
-
1078
- teardown { @file.close }
1079
-
1080
- context "and saved" do
1081
- setup do
1082
- object = stub
1083
- @dummy.avatar.stubs(:s3_object).returns(object)
1084
- object.expects(:write).with(anything,
1085
- :content_type => "image/png",
1086
- :acl => :public_read,
1087
- :storage_class => :reduced_redundancy)
1088
- @dummy.save
1089
- end
1090
-
1091
- should "succeed" do
1092
- assert true
1093
- end
1094
- end
1095
- end
1096
- end
1097
-
1098
- context "with S3 credentials supplied as Pathname" do
1099
- setup do
1100
- ENV['S3_KEY'] = 'pathname_key'
1101
- ENV['S3_BUCKET'] = 'pathname_bucket'
1102
- ENV['S3_SECRET'] = 'pathname_secret'
1103
-
1104
- rails_env('test')
1105
-
1106
- rebuild_model :storage => :s3,
1107
- :s3_credentials => Pathname.new(fixture_file('s3.yml'))
1108
-
1109
- Dummy.delete_all
1110
- @dummy = Dummy.new
1111
- end
1112
-
1113
- should "parse the credentials" do
1114
- assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
1115
- assert_equal 'pathname_key', @dummy.avatar.s3_bucket.config.access_key_id
1116
- assert_equal 'pathname_secret', @dummy.avatar.s3_bucket.config.secret_access_key
1117
- end
1118
- end
1119
-
1120
- context "with S3 credentials in a YAML file" do
1121
- setup do
1122
- ENV['S3_KEY'] = 'env_key'
1123
- ENV['S3_BUCKET'] = 'env_bucket'
1124
- ENV['S3_SECRET'] = 'env_secret'
1125
-
1126
- rails_env('test')
1127
-
1128
- rebuild_model :storage => :s3,
1129
- :s3_credentials => File.new(fixture_file('s3.yml'))
1130
-
1131
- Dummy.delete_all
1132
-
1133
- @dummy = Dummy.new
1134
- end
1135
-
1136
- should "run the file through ERB" do
1137
- assert_equal 'env_bucket', @dummy.avatar.bucket_name
1138
- assert_equal 'env_key', @dummy.avatar.s3_bucket.config.access_key_id
1139
- assert_equal 'env_secret', @dummy.avatar.s3_bucket.config.secret_access_key
1140
- end
1141
- end
1142
-
1143
- context "S3 Permissions" do
1144
- context "defaults to :public_read" do
1145
- setup do
1146
- rebuild_model :storage => :s3,
1147
- :bucket => "testing",
1148
- :path => ":attachment/:style/:basename.:extension",
1149
- :s3_credentials => {
1150
- 'access_key_id' => "12345",
1151
- 'secret_access_key' => "54321"
1152
- }
1153
- end
1154
-
1155
- context "when assigned" do
1156
- setup do
1157
- @file = File.new(fixture_file('5k.png'), 'rb')
1158
- @dummy = Dummy.new
1159
- @dummy.avatar = @file
1160
- end
1161
-
1162
- teardown { @file.close }
1163
-
1164
- context "and saved" do
1165
- setup do
1166
- object = stub
1167
- @dummy.avatar.stubs(:s3_object).returns(object)
1168
- object.expects(:write).with(anything,
1169
- :content_type => "image/png",
1170
- :acl => :public_read)
1171
- @dummy.save
1172
- end
1173
-
1174
- should "succeed" do
1175
- assert true
1176
- end
1177
- end
1178
- end
1179
- end
1180
-
1181
- context "string permissions set" do
1182
- setup do
1183
- rebuild_model :storage => :s3,
1184
- :bucket => "testing",
1185
- :path => ":attachment/:style/:basename.:extension",
1186
- :s3_credentials => {
1187
- 'access_key_id' => "12345",
1188
- 'secret_access_key' => "54321"
1189
- },
1190
- :s3_permissions => :private
1191
- end
1192
-
1193
- context "when assigned" do
1194
- setup do
1195
- @file = File.new(fixture_file('5k.png'), 'rb')
1196
- @dummy = Dummy.new
1197
- @dummy.avatar = @file
1198
- end
1199
-
1200
- teardown { @file.close }
1201
-
1202
- context "and saved" do
1203
- setup do
1204
- object = stub
1205
- @dummy.avatar.stubs(:s3_object).returns(object)
1206
- object.expects(:write).with(anything,
1207
- :content_type => "image/png",
1208
- :acl => :private)
1209
- @dummy.save
1210
- end
1211
-
1212
- should "succeed" do
1213
- assert true
1214
- end
1215
- end
1216
- end
1217
- end
1218
-
1219
- context "hash permissions set" do
1220
- setup do
1221
- rebuild_model :storage => :s3,
1222
- :bucket => "testing",
1223
- :path => ":attachment/:style/:basename.:extension",
1224
- :styles => {
1225
- :thumb => "80x80>"
1226
- },
1227
- :s3_credentials => {
1228
- 'access_key_id' => "12345",
1229
- 'secret_access_key' => "54321"
1230
- },
1231
- :s3_permissions => {
1232
- :original => :private,
1233
- :thumb => :public_read
1234
- }
1235
- end
1236
-
1237
- context "when assigned" do
1238
- setup do
1239
- @file = File.new(fixture_file('5k.png'), 'rb')
1240
- @dummy = Dummy.new
1241
- @dummy.avatar = @file
1242
- end
1243
-
1244
- teardown { @file.close }
1245
-
1246
- context "and saved" do
1247
- setup do
1248
- [:thumb, :original].each do |style|
1249
- object = stub
1250
- @dummy.avatar.stubs(:s3_object).with(style).returns(object)
1251
- object.expects(:write).with(anything,
1252
- :content_type => "image/png",
1253
- :acl => style == :thumb ? :public_read : :private)
1254
- end
1255
- @dummy.save
1256
- end
1257
-
1258
- should "succeed" do
1259
- assert true
1260
- end
1261
- end
1262
- end
1263
- end
1264
-
1265
- context "proc permission set" do
1266
- setup do
1267
- rebuild_model(
1268
- :storage => :s3,
1269
- :bucket => "testing",
1270
- :path => ":attachment/:style/:basename.:extension",
1271
- :styles => {
1272
- :thumb => "80x80>"
1273
- },
1274
- :s3_credentials => {
1275
- 'access_key_id' => "12345",
1276
- 'secret_access_key' => "54321"
1277
- },
1278
- :s3_permissions => lambda {|attachment, style|
1279
- attachment.instance.private_attachment? && style.to_sym != :thumb ? :private : :public_read
1280
- }
1281
- )
1282
- end
1283
-
1284
- context "when assigned" do
1285
- setup do
1286
- @file = File.new(fixture_file('5k.png'), 'rb')
1287
- @dummy = Dummy.new
1288
- @dummy.stubs(:private_attachment? => true)
1289
- @dummy.avatar = @file
1290
- end
1291
-
1292
- teardown { @file.close }
1293
-
1294
- context "and saved" do
1295
- setup do
1296
- @dummy.save
1297
- end
1298
-
1299
- should "succeed" do
1300
- assert @dummy.avatar.url().include? "https://"
1301
- assert @dummy.avatar.url(:thumb).include? "http://"
1302
- end
1303
- end
1304
- end
1305
-
1306
- end
1307
- end
1308
-
1309
- context "An attachment with S3 storage and metadata set using a proc as headers" do
1310
- setup do
1311
- rebuild_model(
1312
- :storage => :s3,
1313
- :bucket => "testing",
1314
- :path => ":attachment/:style/:basename.:extension",
1315
- :styles => {
1316
- :thumb => "80x80>"
1317
- },
1318
- :s3_credentials => {
1319
- 'access_key_id' => "12345",
1320
- 'secret_access_key' => "54321"
1321
- },
1322
- :s3_headers => lambda {|attachment|
1323
- {'Content-Disposition' => "attachment; filename=\"#{attachment.name}\""}
1324
- }
1325
- )
1326
- end
1327
-
1328
- context "when assigned" do
1329
- setup do
1330
- @file = File.new(fixture_file('5k.png'), 'rb')
1331
- @dummy = Dummy.new
1332
- @dummy.stubs(:name => 'Custom Avatar Name.png')
1333
- @dummy.avatar = @file
1334
- end
1335
-
1336
- teardown { @file.close }
1337
-
1338
- context "and saved" do
1339
- setup do
1340
- [:thumb, :original].each do |style|
1341
- object = stub
1342
- @dummy.avatar.stubs(:s3_object).with(style).returns(object)
1343
- object.expects(:write).with(anything,
1344
- :content_type => "image/png",
1345
- :acl => :public_read,
1346
- :content_disposition => 'attachment; filename="Custom Avatar Name.png"')
1347
- end
1348
- @dummy.save
1349
- end
1350
-
1351
- should "succeed" do
1352
- assert true
1353
- end
1354
- end
1355
- end
1356
- end
1357
- end