paperclip 3.5.2 → 5.2.1

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