Exec summary: acts_as_rolemodel arms your ActiveRecord models with access control abilities
The owner is eno
arm your models!
The rails way of authorization
...is zip: there is none. Rails comes without any support for authorization or authentication. Consequently some plugins sprung into life, notably acts_as_authorized and acts_as_authenticated.
However, everything happens on the controller side of life – usually the controller code checks for the identity of a logged-in user, and, based on that, checks whether the user has the right to do, whatever he just initiated in the browser.
This gives you a number of options to do things wrong. Think of a newly added controller method. DRY as you are you might have refactored authorization in a method-specific before-filter: did you ever forget adding a new action to the :only list of methods there? You say you test your application: do you test authorization too? On each controller action?
ARM to the rescue!
acts_as_rolemodel tries to fill the gap. By tieing authorization to the model itself it provides you with a simpler interface to do things right. And it comes with added benefit: an improved find method.
Consider paging. While you can easily render a paginated view of, say, all images on your system you simply render a paginated view of all images the currently logged in user is actually allowed to see in an effective way.
With ARM you can: thanks to ARMing ActiveRecord::find with authorization support this is just a simple query, not different from what you usually do.
ARMs authorization model consists of these components:
accounts: an Account represents a user
group: a group of accounts
right: a right defines an action a user might take on an object, like :read or :write
ARM lets you define the rights members of a group are allowed to act upon an object.
What sounds quite complicated at first boils down to pretty simple stuff. This is how to...
define permissions on a object:
# allow anyone to read
# allow member of friends (a Rolemodel::Group object) and the current user to read and to write
object.permit :read => :all, [ :read, :write ] => [ friends, Rolemodel.whoami ]
revoke permissions on a object:
# revoke :read permission from :all group.
object.revoke :read => :all
Note that the above example doesn't revoke the :read permission from friends or from Rolemodel.whoami
setting the current user
You can simply assign the current user as
Rolemodel.current_user = <obj>
Usually, however, you will use this syntax:
Rolemodel.as(user) {
# do something
}
which allows you to run a code block
define permissions on a object:
check permissions on a object:
object.permits?(:read) {
# do something
}
permits?executes the code blocked (if present) only if the requested right is granted to the current user.
For reasons of simplicity the code block passed to permits? gets the object passed as a parameter:
object.permits?(:read) { |obj|
# object is passed in as obj
}
which allows you to write one-liner in some cases.
object.permits?(:read, &:print)
Project Peace^H^H^H^H^HPacemaker or: Getting started with acts_as_rolemodel
Roles
Now, what is a role?
acts_as_rolemodel :account
acts_as_rolemodel :group
acts_as_rolemodel :manual
Space Home