使用 CanCan 进行上下文感知授权

发布于 2024-11-30 07:29:21 字数 822 浏览 5 评论 0原文

我想使用 CanCan 来处理我的权限。我的网站有许多不同的权限级别,其中大多数都是上下文感知的。例如,以下是我的 3 个主要模型中的关系:

class User < ActiveRecord::Base
  has_many :league_relations
  has_many :leagues, :through => :league_relations
end

class League < ActiveRecord::Base
  has_many :league_relations
  has_many :users, :through => :league_relations
end

class LeagueRelation < ActiveRecord::Base
  belongs_to :user
  belongs_to :league
end

注意,LeagueRelations 是 Leagues 的嵌套资源。我想要做的是允许用户修改联赛,并根据 league_relation 中存储的数据评估每个用户的授权。然后,我希望用户仅根据用户模型中存储的数据来修改联赛关系。

简而言之:我基本上希望使用 LeagueRelations 来授权 League 操作,并使用 Users 来授权 LeagueRelations 操作。即 league_relation.owner = true 删除一个 League,但是 user.owner 呢?必须为 true 才能删除 LeagueRelation。如何在联盟控制器内部根据 league_relation 的属性进行授权,并在其他模型上的其他控制器中授权其他操作。如果您需要更多说明,请发表评论。

谢谢。

I want to use CanCan to handle my permissions. My site has many different permissions levels, and most of them are context aware. For instance, Here are the relations in my 3 main models:

class User < ActiveRecord::Base
  has_many :league_relations
  has_many :leagues, :through => :league_relations
end

class League < ActiveRecord::Base
  has_many :league_relations
  has_many :users, :through => :league_relations
end

class LeagueRelation < ActiveRecord::Base
  belongs_to :user
  belongs_to :league
end

Note, LeagueRelations is a nested resource of Leagues. What I want to do is allow a user to modify leagues, and gauge each user's authorization based off of data stored in league_relation. I would then like a user to modify league relation, based only the data stored in the user model.

To be succinct: I basically want LeagueRelations to be used to authorize League actions, and Users to be used to authorize LeagueRelations actions. i.e. league_relation.owner = true to delete a League, but user.owner? must be true to delete a LeagueRelation. How can I authorize based on the attributes of league_relation when inside the league controller, and authorize other actions in other controllers on other models. Please leave a comment if you need more clarification.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心是晴朗的。 2024-12-07 07:29:21

好的,我解决了问题。 CanCan 自述文件的开头简要提到了我的用例,但我错过了。您可以在 app/models/ 中定义新的能力类,该类接受除 current_user 之外的不同参数。为此,您可以将以下内容放入控制器中:

def current_ability 
  if params[:controller] == 'leagues'
    @current_ability = LeagueAbility.new(current_user_league_relation)
  elsif params[:controller] == 'league_relations'
    @current_ability = LeagueRelationAbility.new(current_user_league_relation)
  else
    @current_ability = Ability.new(current_user)
  end
end

现在您可以在 app/models/ 中创建 league_ability.rb。

class LeagueAbility
  include CanCan::Ability

  def initialize(league_relation)
    league_relation ||= LeagueRelation.new

    if league_relation.owner?
      can :manage, League, :id => league_relation.league_id
    elsif league_relation.moderator?
      can :manage, League, :id => league_relation.league_id
      cannot [:delete, :destroy], League
    else
      can :read, League
      can :create, League
    end    
  end
end

需要注意的一件事是,这依赖于您的应用程序控制器调用子类中的方法。希望有帮助!

Ok, I solved the problem. My use case is briefly mentioned in the beginning of the CanCan README and I missed it. You can define new Ability classes in app/models/ that take in a different parameter other than current_user. To do so, you put the following in your controller:

def current_ability 
  if params[:controller] == 'leagues'
    @current_ability = LeagueAbility.new(current_user_league_relation)
  elsif params[:controller] == 'league_relations'
    @current_ability = LeagueRelationAbility.new(current_user_league_relation)
  else
    @current_ability = Ability.new(current_user)
  end
end

Now you can create league_ability.rb in app/models/.

class LeagueAbility
  include CanCan::Ability

  def initialize(league_relation)
    league_relation ||= LeagueRelation.new

    if league_relation.owner?
      can :manage, League, :id => league_relation.league_id
    elsif league_relation.moderator?
      can :manage, League, :id => league_relation.league_id
      cannot [:delete, :destroy], League
    else
      can :read, League
      can :create, League
    end    
  end
end

One thing to note is that this relies on your application controller calling a method in a child class. Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文