I upload some images on a Rails app through Paperclip gem which I want only the admins on the backend to be able to view. As a result, I have set them as private.
Then I searched around for a solution on how just admin's with specific links can be viewing the files. This is what I found.
I went on to try this but I am struggling on creating the needed signature. The formula is given on the above link and is:
Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) ) );
StringToSign = HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
I had no clue which library/module/gem I need to get this to work on Ruby on Rails. By searching around I found about the aws-s3 gem. I read their wiki and saw this "Accessing private objects from a browser".
So I installed them gem, went on and open my rails console and tried to test them out. I was able to make a connection with AWS S3 but then I cannot do anything as I get errors like "uninitialized constant" and "NameError".
Any tip/guidance to the right direction is appreciated.
Last note, what I try to do is generate links that the admins will be able to use for viewing the images on their browser and not downloading them. From what I read this is what it does. But is it for sure or just downloads them to the admin's computer?
Since you are using Paperclip, you can just use its expiring_url
feature. So you could have a #show
or #download
controller action that just redirects to the temporary URL. There is no need to implement it all yourself.
I will add that although the docs above recommend 10 minutes for the expiration time, I've found that if your server's clock skews one way and S3 skews another, the URL can expire before it exists. So maybe 20 or 30 minutes is safer.
Obviously if you add a controller action like that you should make sure only admins are allowed to use it.
Firstly there is no difference between being able to view an image in the browser or being able to download an image. Either way the user's browser gets the bytes that make up the image and can do whatever it wants with them.
Amazon provide the aws-sdk gem as the officially supported way to access their services, including s3. To generate an s3 presigned url you would do something like
s3 = Aws::S3::Resource.new(region: "us-east-1")
s3.bucket("bucket-name").object("key/for/object").presigned_url("get", expires_in: 3600)
Which returns a link valid for 1 hour (this assumes you have instance provided credentials or have environment variables AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
with your credentials. If not you need to specify then when creating the resource object. )
Defines a downloadable? method that can be used to implement user access rights to the track. For simplicity it just allows all logged in users to access the track, however you can replace this with whatever logic your app requires.
def downloadable?(user)
user != :guest
end
and modify your attachemnet model like this
has_attached_file :mp3,
:url => ':s3_domain_url',
:path => 'assets/:class/:id/:style.:extension',
:storage => :s3,
:s3_credentials => File.join(Rails.root, 'config', 's3.yml'),
:s3_permissions => 'authenticated-read',
:s3_protocol => 'http'
have a look at this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With