Credit: This plugin expands on the original code and ideas of Chris Scharf.
This plugin provides role and permissions handling for Rails applications. It is designed for an escalating permissions
system, where each higher role contains all of the permissions of the roles below it. If you are seeking a many-to-many
type of role/permissions solution, this is not it.
Here’s all you need to know to get started:
- Make sure you have a #role column of type Integer in your “users” table
- Installation:
script/plugin install git://github.com/rpheath/authorize.git
- Open up the model that manages your users and add
include Authorize::Roles
at the top - Redefine the constants in
Authorize::Levels
(authorize/lib/authorize/levels.rb) to make sense (these
constants will be used to generate methods on the fly, so use proper naming :-)
Once you’ve done those initial steps, you can define permissions in your controllers like so:
class PostsController < ActionController::Base
permissions do
author :new, :create
editor :edit, :update
publisher :destroy
end
# ...
end
You define the lowest level of permission for a list of actions. So assuming that an editor is higher up than an author,
an editor would have access to new, create, edit, update, whereas an author can only access new and create. Make sense?
Keep in mind, the available methods used in the permissions block (i.e. author, editor, etc) map to the constants that
you have defined in Authorize::Levels
. Meaning, the above code would assume you had:
module Authorize
module Levels
AUTHOR = 0 unless const_defined?(:AUTHOR)
EDITOR = 1 unless const_defined?(:EDITOR)
PUBLISHER = 2 unless const_defined?(:PUBLISHER)
end
end
And having a PUBLIC_USER
constant would build a public_user
permissions method, as expected, so underscores are handled properly.
This plugin will generate some named_scope’s for you based on the permission levels you defined in Authorize::Levels
. Sticking with our
example from above, we’ll assume you have three: AUTHOR, EDITOR, PUBLISHER. This will allow you to do:
User.authors # => all users having the at least an author role
User.editors # => all users having at least an editor role
Now, since the permissions are setup to build upon the previous one, calling User.authors
will return not only all of the users having the
author role, but also all users having a role above that (since they also have “author” permissions). I realize this may not be the most
desireable approach in all cases, so you can pass “true” to any of the named_scope’s to return the users having exactly that role.
User.authors(true) # => all users having exactly the author role
User.editors(true) # => all users having exactly the editor role
For each level of permission defined, the authorize plugin will automatically generate a block helper for you. This let’s you do:
<% editor do %>
(editor only content)
<% end %>
In the above example, it will only yield if the current user has editor permissions or above. Useful for keeping your views clean.
If a user tries to access an action that he/she does not have access to, a protected invalid_permissions
method would get called.
By default this method will display a warning and redirect to the root_path
. However, if you want some other behavior, just redefine this
method in your application controller.
There’s built-in support for drop down menus. Assuming you included the module into a User
class, you would call:
User::Role.to_options
. Pass false
as a parameter to remove the default -- Choose Role --
option. Or you can pass
:default_text => '--'
to set your own. For good measure, you could wrap this up in a helper called role_options
or something.
It seems that most of my applications involving these types of permissions involve an “inactive” state for the user.
Essentially, this is nothing more than a role with no permission to do anything, and I feel should be treated as such.
Browse through the code to see how the inactive stuff works, but really it’s just like another role, and you have active?
and inactive?
methods available automatically.
If you look in Authorize::Levels
you can see that there’s self.default
and self.lowest
methods. These are useful for defining
what you would like your default permission to be (most cases, inactive) and your lowest level of permission. If you are not using
the inactive state, then you typically would want the default and lowest to be the same, but I’ll leave that up to you.
Here’s an example usecase for the self.default
method:
class User < ActiveRecord::Base
before_create :set_default_role
private
def set_default_role
self[:role] = Authorize::Levels.default
end
end
In a lot of cases, you want to have that user who is above all and permissions are simply irrelevant. The plugin will react to
a super_user?
method, giving them permissions to do anything and everything. If you want to use it, just add a boolean “super_user”
flag to your “users” table, and ActiveRecord
will automatically provide a super_user?
method. The plugin checks if the user
responds to the super user stuff, so if you don’t want to use it, you don’t have to anything.
Copyright © 2009 Ryan Heath and Chris Scharf, released under the MIT license