Allan & Steve are the chubby founders of LessEverything. This is their blog, hear them rant, praise, give advice and talk about Just Stuff, Less Accounting, Lovd by Less, More Honey, Less Memories, Code, Business, Design, Marketing
April 10th, 2008

Rails Tip: Always Scope Your Finders

written by Steven Bristol

It is easy to open a security hole in your Rails application. Fortunately, by scoping your finders, it is also easy to write your code without opening it.

Here is an example. Let’s say you have a expense tracking application and the url is /expenses/151. Obviously this calls the expenses controller with a params[:id] = 151.


#bad:
def show
  @expense = Expenses.find(params[:id])
end

#good:
#@user is the logged on user.
def show
  @expense = @user.expenses.find(params[:id])
end

The scoped finders actually add the proper where clause to the sql. It happens automatically. Without scoping the expense finder, anyone can see anyone else’s data. Generally you will want to set this up as a before filter.

This also works for nested routes. Let’s say the url is /invoices/25/line_items/87:

class LineItemsController < ApplicationController
  before_filter :setup
#snip many lines

  protected
  def setup
    @invoice = @user.invoices.find(params[:invoice_id]) unless params[:invoice_id].blank?
    @line_item = @invoice.blank? ? @user.line_items.find(params[:id]) : @invoices.line_items.find(params[:id])
  end
end

You don’t have to use the @user variable. In Less Accounting we use sub-domains for each business. Since each business may have several users, all the controllers are scoped around the @business variable, which is determined by the sub-domain of the url. The @business variable itself is scoped by the @user variable.

2 Responses to “Rails Tip: Always Scope Your Finders”

  1. Lourens Naude April 11th, 2008

    Perhaps a bit verbose, but I like the result, especially if it can be reused for a couple of controllers …

    http://pastie.caboo.se/179238

  2. Steven Bristol April 11th, 2008

    @Lourens

    As always, very good. I will have to mull this over for a few days to decide if it’s to far from KISS, but I love the passion behind it. You always give me something to think about. You are a rock star.

    steve

Leave a Reply