shrinerb / shrine

File Attachment toolkit for Ruby applications

Home Page:https://shrinerb.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change folder in AWS using Uppy direct to S3?

JetsonDavis opened this issue · comments

This works well but I need my file to go to a folder named 'avatar' in my S3 bucket and as written, it is going to the cache folder. How can I control which folder the object is stored in, pls?

UPDATE:

I solved this by doing the following. I'd love to know if this creates any issues I'm not aware of!?

  1. In the Shrine.rb initializer I added a storage called 'avatar'
Shrine.storages = {
    cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
    avatar: Shrine::Storage::S3.new(prefix: "avatar", **s3_options),
    store: Shrine::Storage::S3.new(**s3_options),
  }
  1. In routes, I put in this line:
    mount Shrine.presign_endpoint(:avatar) => "avatar/s3/params"

  2. In the JavaScript file, I changed:

uppy.use(Uppy.AwsS3, {
      companionUrl: '/', // will call Shrine's presign endpoint on `/s3/params`
    })

to

uppy.use(Uppy.AwsS3, {
      companionUrl: '/avatar', // will call Shrine's presign endpoint on `avatar/s3/params`
    })

I'm assuming that, unlike with temporary storage where the uploaded file is moved to permanent storage when attached, you want to retain this file in the avatar/ directory. If that's the case, you don't need a separate :avatar storage, you can reuse :store:

avatar_presign_endpoint = Shrine.presign_endpoint(:store, presign_location: -> (r) {
  "avatar/#{SecureRandom.hex}#{File.extname(r.params["filename"].to_s)}"
})

mount avatar_presign_endpoint => "avatar/s3/params"

Then when you attach the file to a record, you cannot use regular assignment as that only allows cached files. For example, you can do this:

user_params[:avatar] #=> '{"id":"...","storage":"store","metadata":{...}}'
user.avatar_attacher.set Shrine.uploaded_file(user_params[:avatar])
# ...
user.save

There are some considerations for this approach to keep in mind:

  • Files that are uploaded to the avatar/ directory don't need to necessarily end up being attached to a record. If users choose not to submit the form after uploading the file, they can become orphan files. So, that's theoretically an attack vector unless you find a way to clear our orphan files somehow.

  • An attacker can theoretically hijack an attached file from another resource. If they see an S3 URL of another file, they can guess it's id, which means they can construct Shrine's uploaded file JSON data for that file and submit it for their own resource. Then if they delete that resource, the uploaded file would get deleted to even though it belongs to a resource they're not authorized for.

Since this is a question and not a bug report, I'll close this issue. If you have any further questions, feel free to ask on the ruby-shrine google group.