Rails 3.1中的授权:CanCan,CanTango,declarative_authorization?

时间:2012-01-18 06:45:52

标签: ruby-on-rails ruby-on-rails-3 rails-authorization

我看过declarative_authorization,CanCan和CanTango。他们都善于为应用程序添加授权,但我想知道如何将授权添加到模型的特定实例,即一个人可以在一个项目中拥有管理访问权限并且仅限于(读取少于管理:有限更新等)在另一个。

你能以更好的方式取悦吗?如果我的问题听起来太微不足道,请道歉。可能是因为我是RoR的新手。

感谢, 约翰

2 个答案:

答案 0 :(得分:4)

我知道CanCan和declarative_authorization,并且我实现了两者的基于角色的授权,我推荐CanCan。只是我的两分钱。

示例(未经测试,很遗憾,我无法在此测试,也无法访问我的代码)

所以我们假设我们有这样的结构:

class User < ActiveRecord::Base
  belongs_to :role
end

class Role < ActiveRecord::Base
  has_many :users

  # attributes: project_read, project_create, project_update
end

然后,CanCan看起来像这样:

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

您可以在github上的CanCan wiki中找到所需的所有信息。个人推荐阅读:

基本上你只需要扩展上面的例子,通过你的关系包括你的角色。为了简单起见,您还可以在ability.rb中创建其他帮助方法。

您可能会遇到的主要警告(至少我这样做):在定义用户不能可以对某个模型执行某些操作>。否则你会沮丧地坐在那里思考“但为什么?我从未写过用户不能。”是啊。但你也从未明确写过他可以......

答案 1 :(得分:0)

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

用法:

  

user.is_an?管理员

     

user.can_delete?