cancan/README.rdoc

153 lines
7.0 KiB
Plaintext
Raw Normal View History

2009-11-17 01:03:54 +00:00
= CanCan
Wiki[http://wiki.github.com/ryanb/cancan] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan]
2010-08-06 22:54:25 +00:00
CanCan is an authorization solution for Ruby on Rails for restricting what a given user is allowed to access throughout the application. It does not care how your user roles are defined, it simply focusses on keeping permission logic in a single location (the +Ability+ class) so it is not duplicated across controllers, views, and database queries.
2010-08-06 22:54:25 +00:00
By default, the +current_user+ method is required, so if you have not already, set up some authentication (such as Authlogic[http://github.com/binarylogic/authlogic] or Devise[http://github.com/plataformatec/devise]). See {Changing Defaults}[http://wiki.github.com/ryanb/cancan/changing-defaults] if you need different behavior.
2009-11-17 05:23:06 +00:00
== Installation
2010-08-06 22:54:25 +00:00
To install CanCan, include the gem in the environment.rb in Rails 2.3.
config.gem "cancan"
Or the Gemfile in Rails 3.
gem "cancan"
2010-04-17 18:45:41 +00:00
Alternatively it can be installed as a plugin.
2009-11-17 06:15:10 +00:00
script/plugin install git://github.com/ryanb/cancan.git
2009-11-17 05:23:06 +00:00
== Getting Started
2009-11-17 05:23:06 +00:00
2010-08-06 22:54:25 +00:00
First, define a class called +Ability+ in "models/ability.rb" or anywhere else in the load path. It should look something like this.
2009-11-17 05:23:06 +00:00
class Ability
include CanCan::Ability
def initialize(user)
2009-11-17 05:23:06 +00:00
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
2009-11-17 19:22:09 +00:00
This is where all permissions will go. See the "Defining Abilities" section below for more information.
2009-11-17 05:23:06 +00:00
2010-04-17 18:45:41 +00:00
The current user's permissions can be accessed using the "can?" and "cannot?" methods in the view and controller.
2009-11-17 05:23:06 +00:00
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
2010-04-17 18:45:41 +00:00
See {Checking Abilities}[http://wiki.github.com/ryanb/cancan/checking-abilities] for more information
The "authorize!" method in the controller will raise an exception if the user is not able to perform the given action.
2009-11-17 05:23:06 +00:00
def show
@article = Article.find(params[:id])
authorize! :read, @article
2009-11-17 05:23:06 +00:00
end
2010-04-17 19:37:32 +00:00
Setting this for every action can be tedious, therefore the +load_and_authorize_resource+ method is provided to automatically authorize all actions in a RESTful style resource controller. It will use a before filter to load the resource into an instance variable and authorize it for each action.
2009-11-17 05:23:06 +00:00
class ArticlesController < ApplicationController
load_and_authorize_resource
2009-11-17 05:23:06 +00:00
def show
2010-04-17 18:45:41 +00:00
# @article is already loaded and authorized
2009-11-17 05:23:06 +00:00
end
end
2010-04-17 18:45:41 +00:00
See {Authorizing Controller Actions}[http://wiki.github.com/ryanb/cancan/authorizing-controller-actions] for more information
2010-04-17 19:37:32 +00:00
If the user authorization fails, a CanCan::AccessDenied exception will be raised. You can catch this and modify its behavior in the +ApplicationController+.
2009-11-17 05:23:06 +00:00
class ApplicationController < ActionController::Base
2009-12-14 16:37:30 +00:00
rescue_from CanCan::AccessDenied do |exception|
flash[:error] = exception.message
2009-11-17 05:23:06 +00:00
redirect_to root_url
end
end
2010-04-17 18:45:41 +00:00
See {Exception Handling}[http://wiki.github.com/ryanb/cancan/exception-handling] for more information.
2009-11-17 05:23:06 +00:00
== Defining Abilities
2010-04-17 18:45:41 +00:00
As shown above, the +Ability+ class is where all user permissions are defined. The user model is passed into the initialize method so the permissions can be modified based on any user attributes. CanCan makes no assumptions about how roles are handled in your application. See {Role Based Authorization}[http://wiki.github.com/ryanb/cancan/role-based-authorization] for an example.
2009-11-17 05:23:06 +00:00
2010-04-17 18:45:41 +00:00
The +can+ method is used to define permissions and requires two arguments. The first one is the action you're setting the permission for, the second one is the class of object you're setting it on.
2009-11-17 05:23:06 +00:00
can :update, Article
2010-04-17 18:45:41 +00:00
You can pass an array for either of these parameters to match any one. In this case the user will have the ability to update or destroy both articles and comments.
2009-11-17 05:23:06 +00:00
can [:update, :destroy], [Article, Comment]
2010-04-17 18:45:41 +00:00
Use :+manage+ to represent any action and :+all+ to represent any class. Here are some examples.
2009-11-17 05:23:06 +00:00
2010-04-17 18:45:41 +00:00
can :manage, Article # has permissions to do anything to articles
can :read, :all # has permission to read any model
can :manage, :all # has permission to do anything to any model
You can pass a hash of conditions as the third argument to further restrict what the user is able to access. Here the user will only have permission to read active projects which he owns.
2009-11-17 05:23:06 +00:00
can :read, Project, :active => true, :user_id => user.id
2010-04-17 18:45:41 +00:00
See {Defining Abilities with Hashes}[http://wiki.github.com/ryanb/cancan/defining-abilities-with-hashes] for more information.
2010-04-17 18:45:41 +00:00
Blocks can also be used if you need more control.
can :update, Project do |project|
project && project.groups.include?(user.group)
2009-11-17 05:23:06 +00:00
end
2010-04-17 18:45:41 +00:00
If the block returns true then the user has that :+update+ ability for that project, otherwise he will be denied access. See {Defining Abilities with Blocks}[http://wiki.github.com/ryanb/cancan/defining-abilities-with-blocks] for more information.
2009-11-17 05:23:06 +00:00
== Aliasing Actions
2010-04-17 19:37:32 +00:00
You will usually be working with four actions when defining and checking permissions: :+read+, :+create+, :+update+, :+destroy+. These aren't the same as the 7 RESTful actions in Rails. CanCan automatically adds some default aliases for mapping those actions.
alias_action :index, :show, :to => :read
alias_action :new, :to => :create
alias_action :edit, :to => :update
2010-04-17 18:45:41 +00:00
Notice the +edit+ action is aliased to +update+. If the user is able to update a record he also has permission to edit it. You can define your own aliases in the +Ability+ class
2010-04-17 18:45:41 +00:00
alias_action :update, :destroy, :to => :modify
can :modify, Comment
can? :update, Comment # => true
The +alias_action+ method is an instance method and usually called in +initialize+. See {Custom Actions}[http://wiki.github.com/ryanb/cancan/custom-actions] for information on adding other actions.
== Fetching Records
2010-04-17 18:45:41 +00:00
In the controller +index+ action you may want to fetch only the records which the user has permission to read. You can do this with the +accessible_by+ scope.
@articles = Article.accessible_by(current_ability)
This will only work when abilities are defined using hash conditions, not blocks. See {Fetching Records}[http://wiki.github.com/ryanb/cancan/fetching-records] for more information.
2010-04-17 18:45:41 +00:00
== Additional Docs
2010-08-06 22:54:25 +00:00
* {Upgrading to 1.3}[http://wiki.github.com/ryanb/cancan/upgrading-to-13]
* {Nested Resources}[http://wiki.github.com/ryanb/cancan/nested-resources]
2010-04-17 18:45:41 +00:00
* {Testing Abilities}[http://wiki.github.com/ryanb/cancan/testing-abilities]
* {Accessing Request Data}[http://wiki.github.com/ryanb/cancan/accessing-request-data]
* {Admin Namespace}[http://wiki.github.com/ryanb/cancan/admin-namespace]
2010-04-17 18:45:41 +00:00
* {See more}[http://wiki.github.com/ryanb/cancan/]
2009-11-17 06:31:27 +00:00
== Special Thanks
CanCan was inspired by declarative_authorization[http://github.com/stffn/declarative_authorization/] and aegis[http://github.com/makandra/aegis]. Also many thanks to the CanCan contributors[http://github.com/ryanb/cancan/contributors]. See the CHANGELOG[http://github.com/ryanb/cancan/blob/master/CHANGELOG.rdoc] for the full list.