Rails configurable authorization per-role/crud action

665 Views Asked by At

I'm working with a Rails 2.3 app that is already using declarative_authorization to handle user permissions. Each user belongs to one group (no fancy roles) with permissions on certain models, mostly the regular CRUD actions, but with a few special ones. This all works fine with declarative_authorization in it's usual out of the box mode.

We now want to allow admins to set permissions on particular groups of users with regards to model types. For example, we create a new group Foo, assign some users to it, and then decide with checkboxes if users in group Foo can c/r/u/d objects of model Bar.

I've used acl9 before, and I think I see how I could make that work. I've been a fan of CanCan lately, but I don't see how do it easily with that. If declarative_authorization can do this, I'll stick with it, but I'm prepared to bite the bullet and switch.

What plugin would be the best way to accomplish this? Is there a way to get declarative_authorization to do the job? An elegant way to use CanCan? Are there any gotchas I should watch for, e.g. database performance?

I could be convinced to upgrade the app to Rails 3.1, but I'd prefer to find a 2.3-compatible solution.

I've seen some similar questions, but no satisfactory answers Rails Dynamic Role-Based Authorization plugin?

and this, for cancan https://github.com/ryanb/cancan/wiki/Role-Based-Authorization

1

There are 1 best solutions below

0
On

I'm a fan of the StoneWall gem - authorization checks are in the form of a Ruby block, so in that block you could look up records and see if the user in question has authorization.

There's not a lot of documentation, but the idea is:

a_user_object.may_read?(object)

If object is a Todo instance, then Stonewall will look int the Todo model and execute the read block

# app/models/todo.rb

stonewall do |s|

    s.action :read do |todo, user|
      todo.owner == user  # only the owner of a todo item may read the item
    end
end

This approach makes two things easy:

  1. read is just a Ruby block, so whatever you want to happen can happen
  2. actions can be given arbitrary names, so if you want to check to see if a user has permission to comment on a todo item (for example), just create a s.action :comment and access it with a_user_object.may_comment?(object)