get paperclip attach url from custom find - ruby-on-rails

i have two models, User has_many Message.
User model has an avatar attachment with paperclip. I have a complex find that returns users data and i need to return the avatar url too.
I can't do something like user.avatar.url because the find does not return a User object.
Is there any way to work around this and get the attach url?
running rails 2.3.8

Related

How to find the model an ActiveStorage attachment belongs to using only the blob_path?

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?
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

How prevent deleting image from ActiveStorage by another user?

I have User which have products. User can upload image for product using ActiveStorage. For uploading images I am using separate controller ImageController with only one action delete, and also I have route in my routes:
delete "image/:id/purge", to: "images#delete", as: "purge_image"
So in my db I have ActiveStorage tables, User table and Product table. User has_many products and Product belongs_to User. As I understand, User does not have any connection to ActiveStorage table. How prevent deleting image by another User if he want to use direct route to delete image? Or how to find out which user uploaded image? I will be appreciate for your help.
Simple way is something like this in your controller
def delete
ActiveStorage::Attachment
.where(record_id: current_user&.product_ids)
.find(params[:id])
.purge
end
This way you will find attachments only in the scope of current user products
find method will raise 404 error if this user haven't such images
Or you can use some authorization gem (ActionPolicy, pundit, cancancan etc.)

How to add an ajax autosearch collection in activeadmin?

I have an active admin page called vendor that has a list of user in my model written as:
has_many :users do
def staff_users
where('staff_user' = true)
end
In my vendor active admin form I need to make an autocomplete search for users that I can add to my staff_users (I have the function already working).
I just need to get the available list of users as a collection on my front end.
I've seen this gem select2 from activeadminaddons and installed it using gem install activeadmin_addons. I was trying to use it, however I'm having a problem understanding what is the url for.
Is it correct that I need to create a method on my vendors_controller that can be mapped in my routes.rb that will return all User?
If what I understood is not what it's supposed to do, can someone please explain to me what and how to connect the url param in active admin select2 activeadminaddons.
Any other ideas too? Maybe without the use of this gem, there's a simple solution I can integrate what I need in active admin?
Thanks!
Try running rake routes and find the collection_url for your Vendor model. I guess it will be something like: admin_vendors_path. This route has been dynamically created by registering your model through ActiveAdmin.
Maybe try reading more at: https://github.com/platanus/activeadmin_addons/blob/master/docs/select2_search.md

Ruby on Rails omniauth and carrierwave

I'm using omniauth ( omniauth-facebook) in my ruby on rails application. I would like to know whether I can retrieve user's city, country and gender information. And how can I take user profile photo with carrierwave,
Thanks.
Using the (Carrierwave Documentation)[https://github.com/carrierwaveuploader/carrierwave] as my reference, you would need to modify your user model to add a new fields to support the carrierwave gem functionality.
Typically this means:
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
But it will vary if you are using MongoDB instead of an SQL/ActiveRecord.
You can test this new field exists by initializing a new object in the rails console and examining the fields available.
bundle exec rails c
u = User.new
u.(tab twice quickly to see the available options)
# You are looking for the avatar field
u.avatar
You can set it from console to test it using
File.open('somewhere') do |f|
u.avatar = f
end
Then finally you would add it to the form field in your views once you tested it. You typically have a CRUD for your user so in the Create/Update forms in the views, you modify these forms to include a file form (this is HTML not specifically rails, so you can look up more information using HTML in your search), and once it is added, you will need to modify the corresponding controllers to whitelist the value so it can be saved using these controller actions.
The process is similar to adding other fields to your user object after the initial generation of the user model.
Usually omniauth will return a standard answer that is only concerned with authentication, basically a hash with a combination of email, name/first/last, profile_picture url, username, etc. Some providers give you email, others don't, others only provide some fields if you ask specifically for them through scopes.
For facebook I'm using the following on my omniauth.rb (inside config/initializers/*)
provider :facebook, ENV['FB_ID'], ENV['FB_SECRET'], scope: 'public_profile, email, manage_pages, user_friends', info_fields: 'id, first_name, last_name, link, email', image_size: 'large'
This means that facebook will provide me an email, some basic info such as ID, first name and last name on the response hash (that omniauth takes care of arranging) after a successful oauth authorization. The token it will provide will also be scoped for managing pages although I don't ask for any field related to it initially.
So in your case you would ask for city, country and whatever in info_fields (double checking through their graph explorer that you don't need any extra scope for those fields).
After you get the response through omniauth (which is basically a piece of code written as middleware, that does the oauth2 flow for you - you could do it by yourself as well) you'll have a profile pic url.
You'll want to download that picture.
Using carrierwave you do that either on your controller or module/class by instantiating the column where you have the uploader set and then executing the method .download! passing it the url from where to download:
user.avatar = AvatarUploader.new
user.avatar.download! omniauth_hash['blabla_fields']['blabla_picture_url']
This will download a remote picture url and save it as a regular carrierwave attachment, that you can then access through your model normally.

Rails 4: Use carrierwave as download-only

I have a User model like this:
# profile_pic is of type TEXT in Database
class User < ActiveRecord::Base
mount_uploader :profile_pic, ProfilePicUploader
end
I'd like Carrierwave to work as download only. In other words, I'd like to do user.profile_pic.url and receive the url where the pic is kept, along with a signature, expiration, etc.
What I don't want is for Carrierwave to interfere when I try to save a user's profile pic. For example
user = User.first
user.update(profile_pic: 'random_string')
I want Carrierwave to stay out of it, and let me save whatever string I want in profile_pic.
However, I can't get to update profile_pic, because Carrierwave is expecting an instance of a ProfilePicUploader instead of a string.
What can I do to just use Carrierwave to download files, but never to upload files?

Resources