Skip to content
clyfe edited this page Mar 9, 2011 · 33 revisions

About

If you use CanCan for authorization, the ActiveScaffold CanCan bridge auto-loads and plugs into ActiveScaffold by chaining your Ability rules in the default ActiveScaffold behavior.

Features

  1. activates only when CanCan is installed via default bridges '@install_if = lambda { Object.const_defined?(name) }' functionality
  2. delegates to default AS security in case CanCan says "no"
  3. integrates with begining_of_chain both in "list" and "nested" via CanCan#accessible_by? (feature more known as load_and_authorize_resources)

This feature, for maximum security is best used with default_permission = false, all-tough default_permission = true should also work.

# config/initializers/active_scaffold.rb
ActiveScaffold.set_defaults do |config|
  config.security.default_permission = false
end

Usage

ActiveScaffold asks CanCan access to the following abilities, grouped in two categories:

  1. CRUD Types :create, :update, :read
  2. Actions :list, :show etc (other rails actions (controller method names)) :TODO document column granularity https://github.com/vhochstein/active_scaffold/issues#issue/122

For access to be allowed, CanCan must reply true both to :crud_type and :action simultaneously. If access is not granted it defaults to old ActiveScaffold security behavior and you can write access rules inside your models like you used to.

The CanCan bridge also, if the model is used within a controller (so this does not work, say, in the console), makes available to the model the current_ability.

Important

Note that the bridge plugs into AS#begining_of_chain. That is the main scope from which the listing is fetched and new models are created. The bridge chains this scope taking into account your ability definitions similar to how CanCan#load_and_authorize_resources works, by limiting the result according to the Ability definitions.

FAQ

Q. I get a undefined method 'something_id' for nil:NilClass
A. CanCan tries to authorize a model instance not sufficiently wired to it's scope.
For example while authorizing a document it might look for document.project.owner_id and if the document does not have a project assigned the error will be rendered.
To fix this override the piece of code (in your controller/view) that deals with the model and make sure to wire it up.
Sample here

Q. I get a undefined method 'can?' for nil:NilClass
A. The current_ability (just like current_user) is available inside models only during request/response cycle, because is inserted there by means of a controller before_filter.
If one queryes the CanCan ACL at configure time ( when the controller class body executes ) the authorization will find no current ability to query upon.
At configure time we have nothing: no current_user, no current_ability.
You can only query the authorization during request/response when a user is logged in.
One way to deal with this is: since at configure time we know nothing of who we're authorizing, we can return whatever authorized_for_without_cancan? returns (default old behavior).
In this case because of the default "paranoic" false security reply (if you use it like this):

ActiveScaffold.set_defaults do |config|
  config.security.default_permission = false
end

you'll have to override the security methods as per AS#security wiki

Q. My form only shows the submit button, all the fields are missing
A. AS also authorizes at column level, and your CanCan rule probably reply "no". Make sure the model (@record) that is used for form_for is sufficiently wired to it's related objects. For example the rule can :create, Project, :account_id => user.account_id will render an empty form for a record unless you wire it (overide do_new in controller) like @record.account_id = current_user.account_id. As a side-note, a better rule in the given example is can :create, Project and enforce @record.account_id = current_user.account_id in the update action.

A note of caution

Note that this bridge, along with all AS security layer, and probably many parts of ActiveScaffold, is not thread-safe. That means that these features will work bug-free only in a classic Rails shared-nothing deployment architecture. Trying to deploy this in thread-based mode will most probably lead to race conditions and unexpected behavior!

Clone this wiki locally