Skip to content
cainlevy edited this page Sep 14, 2010 · 21 revisions

If you want to deploy ActiveScaffold in production and expose it to possibly untrusted users, you can take advantage of its security layer to protect your data. The security layer works by paying attention to methods that you can define on your models and controllers. With these methods you may restrict access by taking into account any of the following, as appropriate: the ActiveRecord model, the database record, the current/intended action, and the current user. You may also restrict access at various levels of granularity, forbidding access to an entire action, an entire record, or just a column on the record.

Disclaimer: The security layer in ActiveScaffold is new. Please, please, please test your security setup! If your data is critical and you want complete peace of mind, you must test it yourself. Make sure you have been as specific as possible, and that you have tested to make sure your security methods are being used.

Settings

security.current_user_method global

Names a method on the controller that should return the current_user object, when available. The default is :current_user, which fits nicely with acts_as_authenticated, etc.

class ApplicationController < ActionController::Base ActiveScaffold.set_defaults do |config| config.security.current_user_method = :current_login end protected def current_login session[:user_id] ? User.find(session[:user_id]) : nil end end

security.default_permission global

A boolean value for what a security check should return in the absence of a relevant method. The default is true, which lets ActiveScaffold work out of the box. If you need to be security conscious in your application, you should consider setting this to false so that nothing works until you permit it.

class ApplicationController < ActionController::Base ActiveScaffold.set_defaults do |config| config.security.default_permission = false end end

Controller Method: Restricting an Action

You may restrict an entire action (in the ActiveScaffold plugin sense) by defining a method on your controller in the format #{action_name}_authorized?. All of the actions are set up with before_filters that check these controller methods. The default behavior of each controller method is to query the scaffold’s ActiveRecord model (see Model Methods below).

Example:
class PostController
active_scaffold :posts

protected
  1. only authenticated users are authorized to create records
    def create_authorized?
    self.logged_in?
    end
    end

Model Methods: Restricting Anything Else

On your model object you may define methods in any of three formats, depending on your need for granularity. All methods are defined on the instance level (e.g. def authorized_for_update?, not def self.authorized_for_update?). The methods accept no arguments.

The formats are:

  • #{column_name}_authorized_for_#{crud_action}?
  • #{column_name}_authorized?
  • authorized_for_#{crud_action}?

Hopefully these methods are for the most part intuitive. Crud_action is one of :create, :read, :update, and :destroy. Column_name is not necessarily the name of a database field. It’s the name of whatever column ActiveScaffold is working with, which means it may be a virtual column or it may be an association column.

You may combine methods, and ActiveScaffold will use them intelligently. That is, if you define :authorized_for_update? and :username_authorized_for_update? methods, ActiveScaffold will check both and decide which result to use. It does this by simply giving immediate priority to any false response.

Tips for Defining Model Security Methods

ActiveScaffold’s permissions system actually makes the current user available to your records via the :current_user method. This lets you actually pay attention to who’s logged in and what their roles/permissions are. You should still be prepared to handle the current_user.nil? scenario, though. The current_user may not exist for anonymous users, during cron scripts, or if the model is accessed outside of a request/response cycle.

The second tip is that even though the methods are always at the instance level, the current record isn’t always meaningful. To distinguish whether the specific record matters for the security check, use the :existing_record_check? method.

def authorized_for_destroy?
  1. anonymous users may never destroy these/this records
    return false unless current_user
  2. and logged-in users are usually authorized to destroy records
    return true unless existing_record_check?
  3. unless it’s an existing record and a ‘permanent’ flag has been thrown
    return (self.permanent == false)
    end

What Does NOT Happen

We have tried to design these security methods in a way that lets us spin them off into a new plugin at some future date. The reason they are not a separate plugin yet is because they function passively. That is, they only function when ActiveScaffold is polite enough to care! So please be aware: you can still mess up your data with these security methods in place if you bypass ActiveScaffold (with script/console, for example).

Clone this wiki locally