paperclip 3.5.4 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +17 -0
  3. data/.gitignore +0 -6
  4. data/.hound.yml +1055 -0
  5. data/.rubocop.yml +1 -0
  6. data/.travis.yml +17 -20
  7. data/Appraisals +4 -16
  8. data/CONTRIBUTING.md +29 -13
  9. data/Gemfile +11 -3
  10. data/LICENSE +1 -3
  11. data/NEWS +241 -49
  12. data/README.md +471 -166
  13. data/RELEASING.md +17 -0
  14. data/Rakefile +6 -8
  15. data/UPGRADING +12 -9
  16. data/features/basic_integration.feature +27 -8
  17. data/features/migration.feature +0 -24
  18. data/features/step_definitions/attachment_steps.rb +36 -28
  19. data/features/step_definitions/html_steps.rb +2 -2
  20. data/features/step_definitions/rails_steps.rb +68 -37
  21. data/features/step_definitions/s3_steps.rb +2 -2
  22. data/features/step_definitions/web_steps.rb +1 -103
  23. data/features/support/env.rb +3 -2
  24. data/features/support/file_helpers.rb +2 -2
  25. data/features/support/fixtures/gemfile.txt +1 -1
  26. data/features/support/paths.rb +1 -1
  27. data/features/support/rails.rb +2 -25
  28. data/gemfiles/4.2.gemfile +17 -0
  29. data/gemfiles/5.0.gemfile +17 -0
  30. data/lib/generators/paperclip/paperclip_generator.rb +9 -3
  31. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +2 -2
  32. data/lib/paperclip/attachment.rb +151 -46
  33. data/lib/paperclip/attachment_registry.rb +3 -2
  34. data/lib/paperclip/callbacks.rb +13 -1
  35. data/lib/paperclip/content_type_detector.rb +26 -22
  36. data/lib/paperclip/errors.rb +8 -1
  37. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  38. data/lib/paperclip/geometry_detector_factory.rb +5 -3
  39. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  40. data/lib/paperclip/glue.rb +1 -1
  41. data/lib/paperclip/has_attached_file.rb +17 -1
  42. data/lib/paperclip/helpers.rb +15 -11
  43. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  44. data/lib/paperclip/interpolations.rb +26 -13
  45. data/lib/paperclip/io_adapters/abstract_adapter.rb +32 -4
  46. data/lib/paperclip/io_adapters/attachment_adapter.rb +13 -8
  47. data/lib/paperclip/io_adapters/data_uri_adapter.rb +11 -16
  48. data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
  49. data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
  50. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +7 -7
  51. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  52. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  53. data/lib/paperclip/io_adapters/registry.rb +6 -2
  54. data/lib/paperclip/io_adapters/stringio_adapter.rb +15 -16
  55. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
  56. data/lib/paperclip/io_adapters/uri_adapter.rb +41 -19
  57. data/lib/paperclip/locales/en.yml +1 -0
  58. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  59. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  60. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  61. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  62. data/lib/paperclip/media_type_spoof_detector.rb +90 -0
  63. data/lib/paperclip/processor.rb +5 -41
  64. data/lib/paperclip/processor_helpers.rb +50 -0
  65. data/lib/paperclip/rails_environment.rb +25 -0
  66. data/lib/paperclip/schema.rb +9 -7
  67. data/lib/paperclip/storage/filesystem.rb +14 -3
  68. data/lib/paperclip/storage/fog.rb +37 -19
  69. data/lib/paperclip/storage/s3.rb +129 -69
  70. data/lib/paperclip/style.rb +8 -2
  71. data/lib/paperclip/tempfile_factory.rb +5 -1
  72. data/lib/paperclip/thumbnail.rb +30 -18
  73. data/lib/paperclip/url_generator.rb +26 -14
  74. data/lib/paperclip/validators/attachment_content_type_validator.rb +4 -0
  75. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  76. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  77. data/lib/paperclip/validators/attachment_presence_validator.rb +4 -0
  78. data/lib/paperclip/validators/attachment_size_validator.rb +5 -3
  79. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +27 -0
  80. data/lib/paperclip/validators.rb +11 -4
  81. data/lib/paperclip/version.rb +3 -1
  82. data/lib/paperclip.rb +30 -11
  83. data/lib/tasks/paperclip.rake +34 -5
  84. data/paperclip.gemspec +21 -16
  85. data/shoulda_macros/paperclip.rb +0 -1
  86. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  87. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +17 -20
  88. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  89. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +502 -407
  90. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +17 -20
  91. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  92. data/spec/paperclip/filename_cleaner_spec.rb +14 -0
  93. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  94. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  95. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  96. data/spec/paperclip/glue_spec.rb +44 -0
  97. data/spec/paperclip/has_attached_file_spec.rb +158 -0
  98. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +137 -128
  99. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +70 -46
  100. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +132 -0
  101. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +33 -32
  102. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +89 -0
  103. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  104. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +38 -42
  105. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +121 -0
  106. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  107. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  108. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +12 -9
  109. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +21 -18
  110. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +46 -46
  111. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +172 -0
  112. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  113. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +109 -0
  114. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  115. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  116. data/spec/paperclip/media_type_spoof_detector_spec.rb +94 -0
  117. data/spec/paperclip/meta_class_spec.rb +30 -0
  118. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  119. data/spec/paperclip/paperclip_spec.rb +192 -0
  120. data/spec/paperclip/plural_cache_spec.rb +37 -0
  121. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  122. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +7 -7
  123. data/spec/paperclip/rails_environment_spec.rb +33 -0
  124. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  125. data/spec/paperclip/schema_spec.rb +248 -0
  126. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  127. data/spec/paperclip/storage/fog_spec.rb +566 -0
  128. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  129. data/spec/paperclip/storage/s3_spec.rb +1693 -0
  130. data/spec/paperclip/style_spec.rb +255 -0
  131. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  132. data/spec/paperclip/tempfile_spec.rb +35 -0
  133. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +153 -134
  134. data/spec/paperclip/url_generator_spec.rb +222 -0
  135. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  136. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  137. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  138. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +77 -64
  139. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  140. data/spec/paperclip/validators_spec.rb +164 -0
  141. data/spec/spec_helper.rb +47 -0
  142. data/spec/support/assertions.rb +82 -0
  143. data/spec/support/conditional_filter_helper.rb +5 -0
  144. data/spec/support/fake_model.rb +25 -0
  145. data/spec/support/fake_rails.rb +12 -0
  146. data/spec/support/fixtures/empty.html +1 -0
  147. data/spec/support/fixtures/empty.xlsx +0 -0
  148. data/spec/support/fixtures/spaced file.jpg +0 -0
  149. data/spec/support/matchers/accept.rb +5 -0
  150. data/spec/support/matchers/exist.rb +5 -0
  151. data/spec/support/matchers/have_column.rb +23 -0
  152. data/{test → spec}/support/mock_attachment.rb +2 -0
  153. data/{test → spec}/support/mock_url_generator_builder.rb +2 -2
  154. data/spec/support/model_reconstruction.rb +68 -0
  155. data/spec/support/reporting.rb +11 -0
  156. data/spec/support/test_data.rb +13 -0
  157. data/spec/support/version_helper.rb +9 -0
  158. metadata +348 -225
  159. data/RUNNING_TESTS.md +0 -4
  160. data/cucumber/paperclip_steps.rb +0 -6
  161. data/gemfiles/3.0.gemfile +0 -11
  162. data/gemfiles/3.1.gemfile +0 -11
  163. data/gemfiles/3.2.gemfile +0 -11
  164. data/gemfiles/4.0.gemfile +0 -11
  165. data/test/attachment_definitions_test.rb +0 -12
  166. data/test/attachment_registry_test.rb +0 -88
  167. data/test/file_command_content_type_detector_test.rb +0 -27
  168. data/test/filename_cleaner_test.rb +0 -14
  169. data/test/generator_test.rb +0 -84
  170. data/test/geometry_detector_test.rb +0 -24
  171. data/test/has_attached_file_test.rb +0 -125
  172. data/test/helper.rb +0 -232
  173. data/test/io_adapters/abstract_adapter_test.rb +0 -58
  174. data/test/io_adapters/data_uri_adapter_test.rb +0 -74
  175. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  176. data/test/io_adapters/http_url_proxy_adapter_test.rb +0 -102
  177. data/test/io_adapters/identity_adapter_test.rb +0 -8
  178. data/test/io_adapters/uri_adapter_test.rb +0 -102
  179. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  180. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  181. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -69
  182. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  183. data/test/meta_class_test.rb +0 -32
  184. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  185. data/test/paperclip_test.rb +0 -217
  186. data/test/plural_cache_test.rb +0 -36
  187. data/test/schema_test.rb +0 -200
  188. data/test/storage/fog_test.rb +0 -473
  189. data/test/storage/s3_live_test.rb +0 -179
  190. data/test/storage/s3_test.rb +0 -1356
  191. data/test/style_test.rb +0 -213
  192. data/test/support/mock_model.rb +0 -2
  193. data/test/tempfile_factory_test.rb +0 -17
  194. data/test/url_generator_test.rb +0 -187
  195. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  196. data/test/validators_test.rb +0 -61
  197. /data/{test → spec}/database.yml +0 -0
  198. /data/{test → spec/support}/fixtures/12k.png +0 -0
  199. /data/{test → spec/support}/fixtures/50x50.png +0 -0
  200. /data/{test → spec/support}/fixtures/5k.png +0 -0
  201. /data/{test → spec/support}/fixtures/animated +0 -0
  202. /data/{test → spec/support}/fixtures/animated.gif +0 -0
  203. /data/{test → spec/support}/fixtures/animated.unknown +0 -0
  204. /data/{test → spec/support}/fixtures/bad.png +0 -0
  205. /data/{test → spec/support}/fixtures/fog.yml +0 -0
  206. /data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  207. /data/{test → spec/support}/fixtures/s3.yml +0 -0
  208. /data/{test → spec/support}/fixtures/spaced file.png +0 -0
  209. /data/{test → spec/support}/fixtures/text.txt +0 -0
  210. /data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  211. /data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  212. /data/{test → spec}/support/mock_interpolator.rb +0 -0
@@ -1,1356 +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 = StringIO.new(".")
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 = StringIO.new(".")
115
- end
116
-
117
- should "return a url based on an S3 path" do
118
- assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.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/stringio.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 = StringIO.new(".")
155
- end
156
-
157
- should "return a url based on an S3 path" do
158
- assert_match %r{^https://s3.amazonaws.com/bucket/avatars/stringio.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 = StringIO.new(".")
171
- end
172
-
173
- should "return a url based on an S3 path" do
174
- assert_match %r{^https://s3.amazonaws.com/bucket/avatars/stringio.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 = StringIO.new(".")
187
- end
188
-
189
- should "return a url based on an S3 path" do
190
- assert_match %r{^//s3.amazonaws.com/bucket/avatars/stringio.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 = StringIO.new(".")
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/stringio.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/stringio.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 = StringIO.new(".")
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/stringio.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 = StringIO.new(".")
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/stringio.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 = StringIO.new(".")
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 = StringIO.new(".")
399
- end
400
-
401
- should "return a url based on an S3 subdomain" do
402
- assert_match %r{^http://bucket.s3.amazonaws.com/avatars/stringio.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 = StringIO.new(".")
418
- end
419
-
420
- should "return a url based on the host_alias" do
421
- assert_match %r{^http://something.something.com/avatars/stringio.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 = StringIO.new(".")
441
- end
442
-
443
- should "return a url based on the host_alias" do
444
- assert_match %r{^http://cdn1.example.com/avatars/stringio.txt}, @dummy.avatar.url
445
- assert_match %r{^http://cdn2.example.com/avatars/stringio.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 = StringIO.new(".")
463
- end
464
-
465
- should "return a relative URL for Rails to calculate assets host" do
466
- assert_match %r{^avatars/stringio\.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 = StringIO.new(".")
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 = StringIO.new(".")
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 = StringIO.new(".")
528
- @file.stubs(:original_filename).returns("5k.png\n\n")
529
- @file.stubs(:content_type).returns("image/png\n\n")
530
- @file.stubs(:to_tempfile).returns(@file)
531
-
532
- @dummy.avatar = @file
533
-
534
- object = stub
535
- @dummy.avatar.stubs(:s3_object).returns(object)
536
- object.expects(:url_for).with(:read, :expires => 3600, :secure => true, :response_content_type => "image/png")
537
-
538
- @dummy.avatar.expiring_url
539
- end
540
- end
541
-
542
- context "#expiring_url" do
543
- setup { @dummy = Dummy.new }
544
-
545
- context "with no attachment" do
546
- setup { assert(!@dummy.avatar.exists?) }
547
-
548
- should "return the default URL" do
549
- assert_equal(@dummy.avatar.url, @dummy.avatar.expiring_url)
550
- end
551
-
552
- should 'generate a url for a style when a file does not exist' do
553
- assert_equal(@dummy.avatar.url(:thumb), @dummy.avatar.expiring_url(3600, :thumb))
554
- end
555
- end
556
-
557
- should "generate the same url when using Times and Integer offsets" do
558
- assert_equal @dummy.avatar.expiring_url(1234), @dummy.avatar.expiring_url(Time.now + 1234)
559
- end
560
- end
561
-
562
- context "Generating a url with an expiration for each style" do
563
- setup do
564
- rebuild_model :storage => :s3,
565
- :s3_credentials => {
566
- :production => { :bucket => "prod_bucket" },
567
- :development => { :bucket => "dev_bucket" }
568
- },
569
- :s3_permissions => :private,
570
- :s3_host_alias => "something.something.com",
571
- :path => ":attachment/:style/:basename.:extension",
572
- :url => ":s3_alias_url"
573
-
574
- rails_env("production")
575
-
576
- @dummy = Dummy.new
577
- @dummy.avatar = StringIO.new(".")
578
- end
579
-
580
- should "should generate a url for the thumb" do
581
- object = stub
582
- @dummy.avatar.stubs(:s3_object).with(:thumb).returns(object)
583
- object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
584
- @dummy.avatar.expiring_url(1800, :thumb)
585
- end
586
-
587
- should "should generate a url for the default style" do
588
- object = stub
589
- @dummy.avatar.stubs(:s3_object).with(:original).returns(object)
590
- object.expects(:url_for).with(:read, :expires => 1800, :secure => true)
591
- @dummy.avatar.expiring_url(1800)
592
- end
593
- end
594
-
595
- context "Parsing S3 credentials with a bucket in them" do
596
- setup do
597
- rebuild_model :storage => :s3,
598
- :s3_credentials => {
599
- :production => { :bucket => "prod_bucket" },
600
- :development => { :bucket => "dev_bucket" }
601
- }
602
- @dummy = Dummy.new
603
- end
604
-
605
- should "get the right bucket in production" do
606
- rails_env("production")
607
- assert_equal "prod_bucket", @dummy.avatar.bucket_name
608
- assert_equal "prod_bucket", @dummy.avatar.s3_bucket.name
609
- end
610
-
611
- should "get the right bucket in development" do
612
- rails_env("development")
613
- assert_equal "dev_bucket", @dummy.avatar.bucket_name
614
- assert_equal "dev_bucket", @dummy.avatar.s3_bucket.name
615
- end
616
- end
617
-
618
- context "Parsing S3 credentials with a s3_host_name in them" do
619
- setup do
620
- rebuild_model :storage => :s3,
621
- :bucket => 'testing',
622
- :s3_credentials => {
623
- :production => { :s3_host_name => "s3-world-end.amazonaws.com" },
624
- :development => { :s3_host_name => "s3-ap-northeast-1.amazonaws.com" }
625
- }
626
- @dummy = Dummy.new
627
- end
628
-
629
- should "get the right s3_host_name in production" do
630
- rails_env("production")
631
- assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_host_name
632
- assert_match %r{^s3-world-end.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
633
- end
634
-
635
- should "get the right s3_host_name in development" do
636
- rails_env("development")
637
- assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_host_name
638
- assert_match %r{^s3-ap-northeast-1.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
639
- end
640
-
641
- should "get the right s3_host_name if the key does not exist" do
642
- rails_env("test")
643
- assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_host_name
644
- assert_match %r{^s3.amazonaws.com}, @dummy.avatar.s3_bucket.config.s3_endpoint
645
- end
646
- end
647
-
648
- context "An attachment with S3 storage" do
649
- setup do
650
- rebuild_model :storage => :s3,
651
- :bucket => "testing",
652
- :path => ":attachment/:style/:basename.:extension",
653
- :s3_credentials => {
654
- 'access_key_id' => "12345",
655
- 'secret_access_key' => "54321"
656
- }
657
- end
658
-
659
- should "be extended by the S3 module" do
660
- assert Dummy.new.avatar.is_a?(Paperclip::Storage::S3)
661
- end
662
-
663
- should "not be extended by the Filesystem module" do
664
- assert ! Dummy.new.avatar.is_a?(Paperclip::Storage::Filesystem)
665
- end
666
-
667
- context "when assigned" do
668
- setup do
669
- @file = File.new(fixture_file('5k.png'), 'rb')
670
- @dummy = Dummy.new
671
- @dummy.avatar = @file
672
- end
673
-
674
- teardown { @file.close }
675
-
676
- should "not get a bucket to get a URL" do
677
- @dummy.avatar.expects(:s3).never
678
- @dummy.avatar.expects(:s3_bucket).never
679
- assert_match %r{^http://s3\.amazonaws\.com/testing/avatars/original/5k\.png}, @dummy.avatar.url
680
- end
681
-
682
- should "be rewinded after flush_writes" do
683
- @dummy.avatar.instance_eval "def after_flush_writes; end"
684
-
685
- files = @dummy.avatar.queued_for_write.values.each(&:read)
686
- @dummy.save
687
- assert files.none?(&:eof?), "Expect all the files to be rewinded."
688
- end
689
-
690
- should "be removed after after_flush_writes" do
691
- paths = @dummy.avatar.queued_for_write.values.map(&:path)
692
- @dummy.save
693
- assert paths.none?{ |path| File.exists?(path) },
694
- "Expect all the files to be deleted."
695
- end
696
-
697
- context "and saved" do
698
- setup do
699
- object = stub
700
- @dummy.avatar.stubs(:s3_object).returns(object)
701
- object.expects(:write).with(anything,
702
- :content_type => "image/png",
703
- :acl => :public_read)
704
- @dummy.save
705
- end
706
-
707
- should "succeed" do
708
- assert true
709
- end
710
- end
711
-
712
- context "and saved without a bucket" do
713
- setup do
714
- AWS::S3::BucketCollection.any_instance.expects(:create).with("testing")
715
- AWS::S3::S3Object.any_instance.stubs(:write).
716
- raises(AWS::S3::Errors::NoSuchBucket.new(stub,
717
- stub(:status => 404,
718
- :body => "<foo/>"))).
719
- then.returns(nil)
720
- @dummy.save
721
- end
722
-
723
- should "succeed" do
724
- assert true
725
- end
726
- end
727
-
728
- context "and remove" do
729
- setup do
730
- AWS::S3::S3Object.any_instance.stubs(:exists?).returns(true)
731
- AWS::S3::S3Object.any_instance.stubs(:delete)
732
- @dummy.destroy
733
- end
734
-
735
- should "succeed" do
736
- assert true
737
- end
738
- end
739
-
740
- context 'that the file were missing' do
741
- setup do
742
- AWS::S3::S3Object.any_instance.stubs(:exists?).raises(AWS::Errors::Base)
743
- end
744
-
745
- should 'return false on exists?' do
746
- assert !@dummy.avatar.exists?
747
- end
748
- end
749
- end
750
- end
751
-
752
- context "An attachment with S3 storage and bucket defined as a Proc" do
753
- setup do
754
- rebuild_model :storage => :s3,
755
- :bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
756
- :s3_credentials => {:not => :important}
757
- end
758
-
759
- should "get the right bucket name" do
760
- assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
761
- assert "bucket_a", Dummy.new(:other => 'a').avatar.s3_bucket.name
762
- assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
763
- assert "bucket_b", Dummy.new(:other => 'b').avatar.s3_bucket.name
764
- end
765
- end
766
-
767
- context "An attachment with S3 storage and S3 credentials defined as a Proc" do
768
- setup do
769
- rebuild_model :storage => :s3,
770
- :bucket => {:not => :important},
771
- :s3_credentials => lambda { |attachment|
772
- Hash['access_key_id' => "access#{attachment.instance.other}", 'secret_access_key' => "secret#{attachment.instance.other}"]
773
- }
774
- end
775
-
776
- should "get the right credentials" do
777
- assert "access1234", Dummy.new(:other => '1234').avatar.s3_credentials[:access_key_id]
778
- assert "secret1234", Dummy.new(:other => '1234').avatar.s3_credentials[:secret_access_key]
779
- end
780
- end
781
-
782
- context "An attachment with S3 storage and S3 credentials with a :credential_provider" do
783
- setup do
784
- class DummyCredentialProvider; end
785
-
786
- rebuild_model :storage => :s3,
787
- :bucket => "testing",
788
- :s3_credentials => {
789
- :credential_provider => DummyCredentialProvider.new
790
- }
791
- @dummy = Dummy.new
792
- end
793
-
794
- should "set the credential-provider" do
795
- assert_kind_of DummyCredentialProvider, @dummy.avatar.s3_bucket.config.credential_provider
796
- end
797
- end
798
-
799
- context "An attachment with S3 storage and S3 credentials in an unsupported manor" do
800
- setup do
801
- rebuild_model :storage => :s3, :bucket => "testing", :s3_credentials => ["unsupported"]
802
- @dummy = Dummy.new
803
- end
804
-
805
- should "not accept the credentials" do
806
- assert_raise(ArgumentError) do
807
- @dummy.avatar.s3_credentials
808
- end
809
- end
810
- end
811
-
812
- context "An attachment with S3 storage and S3 credentials not supplied" do
813
- setup do
814
- rebuild_model :storage => :s3, :bucket => "testing"
815
- @dummy = Dummy.new
816
- end
817
-
818
- should "not parse any credentials" do
819
- assert_equal({}, @dummy.avatar.s3_credentials)
820
- end
821
- end
822
-
823
- context "An attachment with S3 storage and specific s3 headers set" do
824
- setup do
825
- rebuild_model :storage => :s3,
826
- :bucket => "testing",
827
- :path => ":attachment/:style/:basename.:extension",
828
- :s3_credentials => {
829
- 'access_key_id' => "12345",
830
- 'secret_access_key' => "54321"
831
- },
832
- :s3_headers => {'Cache-Control' => 'max-age=31557600'}
833
- end
834
-
835
- context "when assigned" do
836
- setup do
837
- @file = File.new(fixture_file('5k.png'), 'rb')
838
- @dummy = Dummy.new
839
- @dummy.avatar = @file
840
- end
841
-
842
- teardown { @file.close }
843
-
844
- context "and saved" do
845
- setup do
846
- object = stub
847
- @dummy.avatar.stubs(:s3_object).returns(object)
848
- object.expects(:write).with(anything,
849
- :content_type => "image/png",
850
- :acl => :public_read,
851
- :cache_control => 'max-age=31557600')
852
- @dummy.save
853
- end
854
-
855
- should "succeed" do
856
- assert true
857
- end
858
- end
859
- end
860
- end
861
-
862
- context "An attachment with S3 storage and metadata set using header names" do
863
- setup do
864
- rebuild_model :storage => :s3,
865
- :bucket => "testing",
866
- :path => ":attachment/:style/:basename.:extension",
867
- :s3_credentials => {
868
- 'access_key_id' => "12345",
869
- 'secret_access_key' => "54321"
870
- },
871
- :s3_headers => {'x-amz-meta-color' => 'red'}
872
- end
873
-
874
- context "when assigned" do
875
- setup do
876
- @file = File.new(fixture_file('5k.png'), 'rb')
877
- @dummy = Dummy.new
878
- @dummy.avatar = @file
879
- end
880
-
881
- teardown { @file.close }
882
-
883
- context "and saved" do
884
- setup do
885
- object = stub
886
- @dummy.avatar.stubs(:s3_object).returns(object)
887
- object.expects(:write).with(anything,
888
- :content_type => "image/png",
889
- :acl => :public_read,
890
- :metadata => { "color" => "red" })
891
- @dummy.save
892
- end
893
-
894
- should "succeed" do
895
- assert true
896
- end
897
- end
898
- end
899
- end
900
-
901
- context "An attachment with S3 storage and metadata set using the :s3_metadata option" do
902
- setup do
903
- rebuild_model :storage => :s3,
904
- :bucket => "testing",
905
- :path => ":attachment/:style/:basename.:extension",
906
- :s3_credentials => {
907
- 'access_key_id' => "12345",
908
- 'secret_access_key' => "54321"
909
- },
910
- :s3_metadata => { "color" => "red" }
911
- end
912
-
913
- context "when assigned" do
914
- setup do
915
- @file = File.new(fixture_file('5k.png'), 'rb')
916
- @dummy = Dummy.new
917
- @dummy.avatar = @file
918
- end
919
-
920
- teardown { @file.close }
921
-
922
- context "and saved" do
923
- setup do
924
- object = stub
925
- @dummy.avatar.stubs(:s3_object).returns(object)
926
- object.expects(:write).with(anything,
927
- :content_type => "image/png",
928
- :acl => :public_read,
929
- :metadata => { "color" => "red" })
930
- @dummy.save
931
- end
932
-
933
- should "succeed" do
934
- assert true
935
- end
936
- end
937
- end
938
- end
939
-
940
- context "An attachment with S3 storage and storage class set using the header name" do
941
- setup do
942
- rebuild_model :storage => :s3,
943
- :bucket => "testing",
944
- :path => ":attachment/:style/:basename.:extension",
945
- :s3_credentials => {
946
- 'access_key_id' => "12345",
947
- 'secret_access_key' => "54321"
948
- },
949
- :s3_headers => { "x-amz-storage-class" => "reduced_redundancy" }
950
- end
951
-
952
- context "when assigned" do
953
- setup do
954
- @file = File.new(fixture_file('5k.png'), 'rb')
955
- @dummy = Dummy.new
956
- @dummy.avatar = @file
957
- end
958
-
959
- teardown { @file.close }
960
-
961
- context "and saved" do
962
- setup do
963
- object = stub
964
- @dummy.avatar.stubs(:s3_object).returns(object)
965
- object.expects(:write).with(anything,
966
- :content_type => "image/png",
967
- :acl => :public_read,
968
- :storage_class => "reduced_redundancy")
969
- @dummy.save
970
- end
971
-
972
- should "succeed" do
973
- assert true
974
- end
975
- end
976
- end
977
- end
978
-
979
- context "Can disable AES256 encryption multiple ways" do
980
- [nil, false, ''].each do |tech|
981
- setup do
982
- rebuild_model(
983
- :storage => :s3,
984
- :bucket => "testing",
985
- :path => ":attachment/:style/:basename.:extension",
986
- :s3_credentials => {
987
- 'access_key_id' => "12345",
988
- 'secret_access_key' => "54321"},
989
- :s3_server_side_encryption => tech)
990
- end
991
-
992
- context "when assigned" do
993
- setup do
994
- @file = File.new(fixture_file('5k.png'), 'rb')
995
- @dummy = Dummy.new
996
- @dummy.avatar = @file
997
- end
998
-
999
- teardown { @file.close }
1000
-
1001
- context "and saved" do
1002
- setup do
1003
- object = stub
1004
- @dummy.avatar.stubs(:s3_object).returns(object)
1005
- object.expects(:write).with(anything,
1006
- :content_type => "image/png",
1007
- :acl => :public_read)
1008
- @dummy.save
1009
- end
1010
-
1011
- should "succeed" do
1012
- assert true
1013
- end
1014
- end
1015
- end
1016
- end
1017
- end
1018
-
1019
- context "An attachment with S3 storage and using AES256 encryption" do
1020
- setup do
1021
- rebuild_model :storage => :s3,
1022
- :bucket => "testing",
1023
- :path => ":attachment/:style/:basename.:extension",
1024
- :s3_credentials => {
1025
- 'access_key_id' => "12345",
1026
- 'secret_access_key' => "54321"
1027
- },
1028
- :s3_server_side_encryption => :aes256
1029
- end
1030
-
1031
- context "when assigned" do
1032
- setup do
1033
- @file = File.new(fixture_file('5k.png'), 'rb')
1034
- @dummy = Dummy.new
1035
- @dummy.avatar = @file
1036
- end
1037
-
1038
- teardown { @file.close }
1039
-
1040
- context "and saved" do
1041
- setup do
1042
- object = stub
1043
- @dummy.avatar.stubs(:s3_object).returns(object)
1044
- object.expects(:write).with(anything,
1045
- :content_type => "image/png",
1046
- :acl => :public_read,
1047
- :server_side_encryption => 'AES256')
1048
- @dummy.save
1049
- end
1050
-
1051
- should "succeed" do
1052
- assert true
1053
- end
1054
- end
1055
- end
1056
- end
1057
-
1058
- context "An attachment with S3 storage and storage class set using the :storage_class option" do
1059
- setup do
1060
- rebuild_model :storage => :s3,
1061
- :bucket => "testing",
1062
- :path => ":attachment/:style/:basename.:extension",
1063
- :s3_credentials => {
1064
- 'access_key_id' => "12345",
1065
- 'secret_access_key' => "54321"
1066
- },
1067
- :s3_storage_class => :reduced_redundancy
1068
- end
1069
-
1070
- context "when assigned" do
1071
- setup do
1072
- @file = File.new(fixture_file('5k.png'), 'rb')
1073
- @dummy = Dummy.new
1074
- @dummy.avatar = @file
1075
- end
1076
-
1077
- teardown { @file.close }
1078
-
1079
- context "and saved" do
1080
- setup do
1081
- object = stub
1082
- @dummy.avatar.stubs(:s3_object).returns(object)
1083
- object.expects(:write).with(anything,
1084
- :content_type => "image/png",
1085
- :acl => :public_read,
1086
- :storage_class => :reduced_redundancy)
1087
- @dummy.save
1088
- end
1089
-
1090
- should "succeed" do
1091
- assert true
1092
- end
1093
- end
1094
- end
1095
- end
1096
-
1097
- context "with S3 credentials supplied as Pathname" do
1098
- setup do
1099
- ENV['S3_KEY'] = 'pathname_key'
1100
- ENV['S3_BUCKET'] = 'pathname_bucket'
1101
- ENV['S3_SECRET'] = 'pathname_secret'
1102
-
1103
- rails_env('test')
1104
-
1105
- rebuild_model :storage => :s3,
1106
- :s3_credentials => Pathname.new(fixture_file('s3.yml'))
1107
-
1108
- Dummy.delete_all
1109
- @dummy = Dummy.new
1110
- end
1111
-
1112
- should "parse the credentials" do
1113
- assert_equal 'pathname_bucket', @dummy.avatar.bucket_name
1114
- assert_equal 'pathname_key', @dummy.avatar.s3_bucket.config.access_key_id
1115
- assert_equal 'pathname_secret', @dummy.avatar.s3_bucket.config.secret_access_key
1116
- end
1117
- end
1118
-
1119
- context "with S3 credentials in a YAML file" do
1120
- setup do
1121
- ENV['S3_KEY'] = 'env_key'
1122
- ENV['S3_BUCKET'] = 'env_bucket'
1123
- ENV['S3_SECRET'] = 'env_secret'
1124
-
1125
- rails_env('test')
1126
-
1127
- rebuild_model :storage => :s3,
1128
- :s3_credentials => File.new(fixture_file('s3.yml'))
1129
-
1130
- Dummy.delete_all
1131
-
1132
- @dummy = Dummy.new
1133
- end
1134
-
1135
- should "run the file through ERB" do
1136
- assert_equal 'env_bucket', @dummy.avatar.bucket_name
1137
- assert_equal 'env_key', @dummy.avatar.s3_bucket.config.access_key_id
1138
- assert_equal 'env_secret', @dummy.avatar.s3_bucket.config.secret_access_key
1139
- end
1140
- end
1141
-
1142
- context "S3 Permissions" do
1143
- context "defaults to :public_read" do
1144
- setup do
1145
- rebuild_model :storage => :s3,
1146
- :bucket => "testing",
1147
- :path => ":attachment/:style/:basename.:extension",
1148
- :s3_credentials => {
1149
- 'access_key_id' => "12345",
1150
- 'secret_access_key' => "54321"
1151
- }
1152
- end
1153
-
1154
- context "when assigned" do
1155
- setup do
1156
- @file = File.new(fixture_file('5k.png'), 'rb')
1157
- @dummy = Dummy.new
1158
- @dummy.avatar = @file
1159
- end
1160
-
1161
- teardown { @file.close }
1162
-
1163
- context "and saved" do
1164
- setup do
1165
- object = stub
1166
- @dummy.avatar.stubs(:s3_object).returns(object)
1167
- object.expects(:write).with(anything,
1168
- :content_type => "image/png",
1169
- :acl => :public_read)
1170
- @dummy.save
1171
- end
1172
-
1173
- should "succeed" do
1174
- assert true
1175
- end
1176
- end
1177
- end
1178
- end
1179
-
1180
- context "string permissions set" do
1181
- setup do
1182
- rebuild_model :storage => :s3,
1183
- :bucket => "testing",
1184
- :path => ":attachment/:style/:basename.:extension",
1185
- :s3_credentials => {
1186
- 'access_key_id' => "12345",
1187
- 'secret_access_key' => "54321"
1188
- },
1189
- :s3_permissions => :private
1190
- end
1191
-
1192
- context "when assigned" do
1193
- setup do
1194
- @file = File.new(fixture_file('5k.png'), 'rb')
1195
- @dummy = Dummy.new
1196
- @dummy.avatar = @file
1197
- end
1198
-
1199
- teardown { @file.close }
1200
-
1201
- context "and saved" do
1202
- setup do
1203
- object = stub
1204
- @dummy.avatar.stubs(:s3_object).returns(object)
1205
- object.expects(:write).with(anything,
1206
- :content_type => "image/png",
1207
- :acl => :private)
1208
- @dummy.save
1209
- end
1210
-
1211
- should "succeed" do
1212
- assert true
1213
- end
1214
- end
1215
- end
1216
- end
1217
-
1218
- context "hash permissions set" do
1219
- setup do
1220
- rebuild_model :storage => :s3,
1221
- :bucket => "testing",
1222
- :path => ":attachment/:style/:basename.:extension",
1223
- :styles => {
1224
- :thumb => "80x80>"
1225
- },
1226
- :s3_credentials => {
1227
- 'access_key_id' => "12345",
1228
- 'secret_access_key' => "54321"
1229
- },
1230
- :s3_permissions => {
1231
- :original => :private,
1232
- :thumb => :public_read
1233
- }
1234
- end
1235
-
1236
- context "when assigned" do
1237
- setup do
1238
- @file = File.new(fixture_file('5k.png'), 'rb')
1239
- @dummy = Dummy.new
1240
- @dummy.avatar = @file
1241
- end
1242
-
1243
- teardown { @file.close }
1244
-
1245
- context "and saved" do
1246
- setup do
1247
- [:thumb, :original].each do |style|
1248
- object = stub
1249
- @dummy.avatar.stubs(:s3_object).with(style).returns(object)
1250
- object.expects(:write).with(anything,
1251
- :content_type => "image/png",
1252
- :acl => style == :thumb ? :public_read : :private)
1253
- end
1254
- @dummy.save
1255
- end
1256
-
1257
- should "succeed" do
1258
- assert true
1259
- end
1260
- end
1261
- end
1262
- end
1263
-
1264
- context "proc permission set" do
1265
- setup do
1266
- rebuild_model(
1267
- :storage => :s3,
1268
- :bucket => "testing",
1269
- :path => ":attachment/:style/:basename.:extension",
1270
- :styles => {
1271
- :thumb => "80x80>"
1272
- },
1273
- :s3_credentials => {
1274
- 'access_key_id' => "12345",
1275
- 'secret_access_key' => "54321"
1276
- },
1277
- :s3_permissions => lambda {|attachment, style|
1278
- attachment.instance.private_attachment? && style.to_sym != :thumb ? :private : :public_read
1279
- }
1280
- )
1281
- end
1282
-
1283
- context "when assigned" do
1284
- setup do
1285
- @file = File.new(fixture_file('5k.png'), 'rb')
1286
- @dummy = Dummy.new
1287
- @dummy.stubs(:private_attachment? => true)
1288
- @dummy.avatar = @file
1289
- end
1290
-
1291
- teardown { @file.close }
1292
-
1293
- context "and saved" do
1294
- setup do
1295
- @dummy.save
1296
- end
1297
-
1298
- should "succeed" do
1299
- assert @dummy.avatar.url().include? "https://"
1300
- assert @dummy.avatar.url(:thumb).include? "http://"
1301
- end
1302
- end
1303
- end
1304
-
1305
- end
1306
- end
1307
-
1308
- context "An attachment with S3 storage and metadata set using a proc as headers" do
1309
- setup do
1310
- rebuild_model(
1311
- :storage => :s3,
1312
- :bucket => "testing",
1313
- :path => ":attachment/:style/:basename.:extension",
1314
- :styles => {
1315
- :thumb => "80x80>"
1316
- },
1317
- :s3_credentials => {
1318
- 'access_key_id' => "12345",
1319
- 'secret_access_key' => "54321"
1320
- },
1321
- :s3_headers => lambda {|attachment|
1322
- {'Content-Disposition' => "attachment; filename=\"#{attachment.name}\""}
1323
- }
1324
- )
1325
- end
1326
-
1327
- context "when assigned" do
1328
- setup do
1329
- @file = File.new(fixture_file('5k.png'), 'rb')
1330
- @dummy = Dummy.new
1331
- @dummy.stubs(:name => 'Custom Avatar Name.png')
1332
- @dummy.avatar = @file
1333
- end
1334
-
1335
- teardown { @file.close }
1336
-
1337
- context "and saved" do
1338
- setup do
1339
- [:thumb, :original].each do |style|
1340
- object = stub
1341
- @dummy.avatar.stubs(:s3_object).with(style).returns(object)
1342
- object.expects(:write).with(anything,
1343
- :content_type => "image/png",
1344
- :acl => :public_read,
1345
- :content_disposition => 'attachment; filename="Custom Avatar Name.png"')
1346
- end
1347
- @dummy.save
1348
- end
1349
-
1350
- should "succeed" do
1351
- assert true
1352
- end
1353
- end
1354
- end
1355
- end
1356
- end