0

To prevent anyone with a url accessing restricted files, I need to check user role permissions to view those ActiveStorage model attachments beforehand. I've created an ActiveStorage::BaseController with a before action that does all the needed checks.

I currently find the original parent model that the attachment belongs to by using the signed_id in the params:

signed_id = params[:signed_id].presence || params[:signed_blob_id].presence
blob_id = ActiveStorage::Blob.find_signed(signed_id)
attachment = ActiveStorage::Attachment.find_by(blob_id: blob_id)
record = attachment.record

# record.some_model method_or_check etc.

This works really well and I'm able to do all the stuff I want to do, however, sometimes the signed_id is not in the params and instead I just get:

{"encoded_key"=>
"[LONG KEY HERE]",
 "filename"=>"sample",
 "format"=>"pdf"}

I have no idea why this happens unpredictably as I'm always using rails_blob_path(model.attachment, disposition: 'attachment') or rails_blob_path(model.attachment, disposition: 'preview') everywhere in the code and testing under the same conditions.

Is it possible to ensure the signed_id is always present or alternatively, is there a way to get back to the parent model using the encoded_key as rails obviously does this to display the attachment anyway?

  • `attachment.record_type.constantize.find(attachment.record_id)` is the most convoluted way of doing `attachment.record` I can imagine. ;) https://github.com/rails/rails/blob/8015c2c2cf5c8718449677570f372ceb01318a32/activestorage/app/models/active_storage/attachment.rb#L21 – max Dec 19 '22 at 14:49
  • You should also note that this will just prevent the redirect if you're using ActiveStorage in redirect mode. The URL to the asset itself won't be protected unless you use authorization on the cloud platform as well or if ActiveStorage is actually proxying. – max Dec 19 '22 at 14:54
  • Also I don't sure that `presence` is needed. I guess param value is non-empty string or nil – mechnicov Dec 19 '22 at 15:06
  • Good points @max, I somehow forgot that it belongs_ to a record while I was trying to work it all out! – Kurt Peniket Dec 19 '22 at 15:09

1 Answers1

1

I am not sure you need it

If you're worried that someone might view the file if he/she knows URL, you can make time expiration limit for that URL

# config/initializers/active_storage.rb
Rails.application.config.active_storage.service_urls_expire_in = 1.minute

It is unlikely that an attacker will be able to generate URL in such a way as to be able to view that file

mechnicov
  • 12,025
  • 4
  • 33
  • 56