Authorization in Rails 3.1: CanCan, CanTango, declarative_authorization?

I reviewed declarative_authorization, CanCan and CanTango. They are all good at adding authorization to the application, but I was wondering how to add authorization to a specific instance of the model, i.e. a person can have access to management in one project and only limited (read less than manage: limited update, etc.) in another.

Could you suggest a better way? Sorry if my question sounds too trivial. This may be because I'm new to RoR.

Thanks, John

+7
source share
2 answers

As I know CanCan and declarative_authorization, and I have implemented role-based credentials with both, I recommend CanCan. Only my two cents.

Example (unverified, unfortunately, I can not check here, and I do not have access to my code)

So, let's say we have this structure:

class User < ActiveRecord::Base belongs_to :role end class Role < ActiveRecord::Base has_many :users # attributes: project_read, project_create, project_update end 

Then CanCan might look like this:

 class Ability include CanCan::Ability def initialize(user) @user = user @role = user.role # user can see a project if he has project_read => true in his role can :read, Project if role.project_read? # same, but with create can :create, Project if role.project_create? # can do everything with projects if he is an admin can :manage, Project if user.admin? end end 

You can find all the information you need on the CanCan wiki on github. Personal recommendations:

Basically, you just need to extend the example above to include your roles in your relationship. To keep it simple, you can also create additional helper methods in ability.rb .

The main middle caveat you can count on (at least me) is to make sure your user can do something with the model before determining what the user cannot. Otherwise, you will sit there disappointed and think, "but why? I never wrote that the user cannot." Yes. But you also never explicitly wrote that he can ...

+4
source
 class User < ActiveRecord::Base belongs_to :role delegate :permissions, :to => :role def method_missing(method_id, *args) if match = matches_dynamic_role_check?(method_id) tokenize_roles(match.captures.first).each do |check| return true if role.name.downcase == check end return false elsif match = matches_dynamic_perm_check?(method_id) return true if permissions.find_by_name(match.captures.first) else super end end private def matches_dynamic_perm_check?(method_id) /^can_([a-zA-Z]\w*)\?$/.match(method_id.to_s) end def matches_dynamic_role_check?(method_id) /^is_an?_([a-zA-Z]\w*)\?$/.match(method_id.to_s) end def tokenize_roles(string_to_split) string_to_split.split(/_or_/) end end 

Using:

user.is_an? admin

user.can_delete?

0
source

All Articles