最佳能力授权

时间:2013-05-14 14:28:11

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

我有一个Rails 3应用程序,我使用CanCan进行授权,但我正在寻找更适合我需求的东西。我的授权不是基于角色,而是更具情境性。

该应用程序用于管理大学/宿舍的每日晚餐俱乐部,其中人们轮流为其余的晚餐做晚餐。因此,厨师对他负责的晚餐俱乐部(如更改菜单)拥有更多权限,参与者拥有更多权限(如添加客人),然后是未参加该单一晚宴俱乐部的人。

因此我需要的是一些授权系统,它取决于用户与晚餐俱乐部或厨房之间的关系(厨房有许多晚餐俱乐部),而不是用户角色。

如果它有帮助,我现在的康康技能(你看它们相当复杂)

# In ability.rb

def initialize(user)
  # edit (like changing time or menu) for a dinner club
  can :edit, DinnerClub do |dinner_club|
    dinner_club.is_chef?(user) &&
    !dinner_club.canceled?
  end

  # open or close a dinner club
  can [:open, :close], DinnerClub do |dinner_club|
    !dinner_club.passed? &&
    dinner_club.is_chef?(user)
  end

  # cancel or resume a dinner club
  can [:cancel, :resume], DinnerClub do |dinner_club|
    !dinner_club.passed? &&
    dinner_club.is_chef?(user)
  end

  # register or unregister for at specific dinner club
  can [:register, :unregister], DinnerClub do |dinner_club|
    dinner_club.open? &&
    (dinner_club.kitchen_id == user.kitchen_id || dinner_club.kitchen.open_registrations?) &&
    !dinner_club.is_chef?(user)
  end

  # add guests to a dinner club
  can [:add_guests], DinnerClub do |dinner_club|
    dinner_club.open? &&
    (dinner_club.kitchen_id == user.kitchen_id || dinner_club.kitchen.open_registrations?) &&
    dinner_club.registered?(user)
  end

  # take the dinner club from another use if the dinner club is canceled
  can [:take], DinnerClub do |dinner_club|
    dinner_club.canceled? &&
    (dinner_club.kitchen_id == user.kitchen_id || dinner_club.kitchen.open_registrations?) &&
    !dinner_club.passed? &&
    !dinner_club.is_chef?(user)
  end

  # create a new dinner club
  can [:create], DinnerClub do |dinner_club|
    (dinner_club.kitchen_id == user.kitchen_id || dinner_club.kitchen.open_registrations?)
  end

  # comment on existing dinner clubs
  can [:comment], DinnerClub do |dinner_club|
    dinner_club.registered?(user)
  end

  # can see dinner clubs for this kitchen
  can :read, Kitchen do |kitchen|
    (kitchen.id == user.kitchen_id || kitchen.open_registrations?)
  end

  # can manage the kitchen, like changing name and configuration options
  can :manage, Kitchen, admin_id: user.id
end

1 个答案:

答案 0 :(得分:1)

你可以在CanCan中重写大部分这些块,使它们的复杂性降低很多。

can :edit, DinnerClub, cancelled: false, chef_id: user.id

# open or close a dinner club
can [:open, :close], DinnerClub, passed: false, chef_id: user.id

# take the dinner club from another use if the dinner club is canceled
can [:take], DinnerClub, cancelled: true, kitchen_id: user.kitched_id, passed: false  
can [:take], DinnerClub, cancelled: true, kitchen: { open_registrations: true }, passed: false
cannnot [:take], DinnerClub, chef_id: user.id

这假设cancelled?passed?方法是从DinnerClub模型的布尔属性派生的,is_chef?方法检查chef_id。但它说明了这个想法。

CanCan主要用于根据资源定义能力,所以我会选择。