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

Advanced ARMing AdvancedArming

AutomaticToThePeople

WhereDoesItSuck

No comments yet. post a comment >