views:

81

answers:

2

Hello, 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

A: 

"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)
Ngetha
Thanks Ngetha; A unique ID to find a unique user is there and I guess the nature of my question ( or FEAR!) is that I am quite terrified by the idea that someone might guess the URL to a certain files. Is that possible in Rails? Or is it not impossible because every URL is a http://dns/[controller][,/action][,/id]?
Nik
+1  A: 

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.

hopeless
This is fantastic! Thank you for your in-depth instruction. My mind is certainly more at rest knowing that there is a limitation to who gets to download what. Now this PaperClip business, in plain words, once installed would intercept 'all' URL's is that the story? -- (If I remember right, though can't remember where, I read an article or perhaps an eBook that mentioned about Rails' apps's controller + actions are your only possibilities for URLs is that right?Thank You, again!
Nik
hmmm... not quite sure what you mean. I would suggest that you start off slowly with a simple rails app, gradually building it up.RestfulAuthentication is all about getting users to register, login, logout and ensure that certain pages are only visible to logged in users. It provides the login_required filter and current_user variable you see above.Paperclip is a plugin for managing file uploads. Essentially, it takes on the job of storing the file and managing the metadata about it (i.e., path, size, type) in your database.The main crux of the solution is that assets controller
hopeless