This tutorial is about the gem Paperclip. But it is not about the basics. For introductions about this you have to google. There are a lot of blogposts about that already in the internet.
Following explanations demonstrate how you could protect documents, which are uploaded via Paperclip. Further this documents are additonal protected through an authorization process and through an extra password for each document. You can use Devise, Authlogic, or other systems you prefer for your authorization process.
Logged in admins are allowed to read the documents without password input, logged in customers must authenticate with passwords.
So let's start: First you have to add a new model. I call it "document". This model just contains standard Paperclip stuff with a few overriedes. Further it has the attribute "password".
I override the default save path. Instead of my public directory, I save the documents in a directory called "documents". This directory gets created at my applicaton's root level. So nowbody could read this data from outside.
Furhter I add an :url path. This is necessary for the download method, which will be explained later.
class Document < ActiveRecord::Base # validations validates :password, :presence => true # post_process just if document is an image before_post_process :is_image? def is_image? ['image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png', 'image/gif'].include?(self.document_content_type) end has_attached_file :document :path => ':rails_root/documents/:class/:id/:style/:basename.:extension' :url => '/documents/:id/download' end
Next you have to modify your controller:
class DocumentsController < ApplicationController before_filter :your_auth_system_admin, :only => [:show] before_filter :your_auth_system_admin_or_customer, :only => [:index, :download] def index @documents = Documents.all end def download @download = Download.find(params[:id]) password = params[:password] if @document.password == password # here you can add an encryption and decryption for your password field (md5, sha1, etc.) send_file @document.document.path, :type => @document.document_content_type, :disposition => 'inline' else flash[:error] = "Wrong password, access denied" redirect_to documents_path end end def show @document = Document.find(params[:id]) send_file @document.document.path, :type => @document.document_content_type, :disposition => 'inline' end end
Now let's have a look at the view. You just need the documents#index view:
<% @documents.each do |document| %> <%= document.document_content_name %> <%= form_tag download_url(:id => document.id) do %> <%= label_tag :password, "Password" %> <%= password_field_tag :document, document.id %> <%= submit_tag "DOWNLOAD" %> <% end %> <% end %>
And last, but not least you have to modify your routes.
resources :documents match 'documents/:id/download' => 'documents#download', :as => :download
And thats it. Now you have the possibility to upload documents, give them passwords and protect them from outside access. You can give your customers passwords for the documents and they can download them. As admin you must just be logged in and you have access to everything. The extra password protection could be to much, but if you just have one customer account and a lot of customers, you could specify the access for each customer in an extra way.