Nik So
Nik So

Reputation: 16821

What's a working concept for serving protected/individual downloads in Rails?

I was wondering how I can let a logged in user download his and only his files on the server. For example, no one else but only I can download my Google Docs' documents when I have logged in. Is there a concept page you have link to handy I can read up on? Is there a book like a recipe book that might get into more detail and specific about the implementation in Rails? And is there a gem/plugin that already does so?

Thanks

Upvotes: 0

Views: 174

Answers (2)

ideasasylum
ideasasylum

Reputation: 2130

I would suggest creating a controller which limits access to the downloads. The trick is to serve the file through a controller, not directly from Apache. I'm assuming that you're using RestfulAuthentication and Paperclip here:

This is the model (a photo which has an image attachment)

class Photo < ActiveRecord::Base
  belongs_to :user

  has_attached_file :image, #:styles => {:thumbnail => "100x100#", :large => "800x600>"},
   :path => ":rails_root/assets/:attachment/:id_partition/:style/:basename.:extension",
   :url => "/assets/:userid/:attachment/:id/:style"
end

Note the url attribute which, in combination with the route below, will force the image to be accessed via a controller and not directly from the public directory. Also note the :path attribute which specifies a private assets directory instead of the default public one.

map.assets 'assets/:userid/:attachment/:id/:style', :controller => 'assets', :action => 'get', :conditions => {:method => :get }

Now, this is the simple controller which requires the user to be logged in, checks the user id and sends the appropriate file back to the user.

class AssetsController < ApplicationController
  before_filter :login_required

  def get
    if current_user.id == params[:userid].to_i
      @photo = Photo.find params[:id]
      send_file @photo.image.path(params[:style]), :type => @photo.image_content_type, :disposition => 'inline'
    else
      render :nothing => true
    end
  end
end

You should also specify :x_sendfile => true in send_file to improve the performance by letting Apache take the strain of actually serving the file once your controller has approved it.

Upvotes: 1

Ngetha
Ngetha

Reputation: 254

"let a logged in user download his and only his files on the server"

Do you have a way of uniquely knowing who owns what file? This is the starting point, if say the files are images and you only want me to see my images, then when saving (uploading) the images, make sure you store along with the image data my user id.

So once am logged in, you only select what belongs to to me. Have a look at the table below (images example, assuming they are stored in FileSystem)

photos(id,title,desc,file_name,user_id*) * User ID is the ID of the person who is logged in

These plugins can help

  • RestFul authentication
  • ActiveACL (or any other authorization plugin)
  • PaperClip (File uploads)

Upvotes: 0

Related Questions