DarthSim/carrierwave-bombshelter

Cannot assign uploader from one model to another to copy files

kkohrt opened this issue · 2 comments

This code used to work for us (we mount our Image uploader on the media field, and images are stored on S3 using the fog gem):

copied_asset = Assets::Image.create(
  media: original_asset.media,
  internal_name: "published_#{original_asset.internal_name}"
)

Now it fails to save because of image type protection here:
https://github.com/DarthSim/carrierwave-bombshelter/blob/master/lib/carrierwave/bombshelter.rb#L41
Which generates

copied_asset.errors.full_messages
# => ["Media Image has an unsupported type"]

I may be completely on the wrong track, but when I look at the line that feeds the type checker
https://github.com/DarthSim/carrierwave-bombshelter/blob/master/lib/carrierwave/bombshelter.rb#L36

def protect_from_image_bomb!(new_file)
      image = FastImage.new(new_file.path || get_real_file(new_file.file))

and try to pass in
new_file = original_asset.media,
then since new_file.path resolves to image_assets/3bb19772-4350-4f96-9279-688740bb7628.png, I get

image = FastImage.new(new_file.path || get_real_file(new_file.file))
# => #<FastImage:0x007f9f0a75dcc0 
@uri="image_assets/3bb19772-4350-4f96-9279-688740bb7628.png", 
@options={:type_only=>false, :timeout=>2, :raise_on_failure=>false, :proxy=>nil, :http_header=>{}}, 
@property=:size,
@parsed_uri=#<Addressable::URI:0x3fcf853aebcc URI:image_assets/3bb19772-4350-4f96-9279-688740bb7628.png>
>
image.type
# => nil

If I skip the path option I get

image = FastImage.new( get_real_file(new_file.file))
ArgumentError: wrong number of arguments (1 for 0)
  from .../gems/carrierwave-0.11.1/lib/carrierwave/storage/fog.rb:225:in `read'
  from .../gems/fastimage-2.0.0/lib/fastimage.rb:327:in `block in fetch_using_read'

(which suggests I am sending in the wrong object; though new_file.file responds_to?(:read), which makes FastImage think it can call read(LocalFileChunkSize) on it--which is one too many arguments for Fog )

If I use new_file = original_asset.media.file I still get

image = FastImage.new(new_file.path || get_real_file(new_file.file))
# => #<FastImage:0x007f9f0a6d5c08 @uri="image_assets/3bb19772-4350-4f96-9279-688740bb7628.png",
@options={:type_only=>false, :timeout=>2, :raise_on_failure=>false, :proxy=>nil, :http_header=>{}},
@property=:size, 
@parsed_uri=#<Addressable::URI:0x3fcf8536ac10 URI:image_assets/3bb19772-4350-4f96-9279-688740bb7628.png>
>
image.type
# => nil

So backing all the way out, if I try at the top level to use

asset = Assets::Image.create( 
  media: original_asset.url, 
  internal_name: "published_#{original_asset.internal_name}" 
)

It does actually save, but with no image:

asset.url
# => nil
asset.media
=> #<ImageUploader:0x007f9f0a67f178 
@model=#<Assets::Image id: 37848, created_at: "2016-05-13 15:45:10", media: nil, type: "Assets::Image", updated_at: "2016-05-13 15:45:10", internal_name: "published_3bb19772-4350-4f96-9279-688740bb7628_378...">,
@mounted_as=:media, 
@storage=#<CarrierWave::Storage::Fog:0x007f9f0a674cf0 
@uploader=#<ImageUploader:0x007f9f0a67f178 ...>>
>

Is this a use case that was not considered before?
Or, at the very least, is there a way to do what we are doing and pass protect_from_image_bomb! ?

Thanks for discovery! Fixed in 0.2.1.

👍 Thanks! Bundling the new version now