2013-05-14 25 views
0

我有一個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

您可以重寫大部分在慘慘這些塊,使他們少了很多複雜。

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主要用於定義基於資源的能力,所以我會這樣做。

+0

謝謝你的幫助!那些並非真正授權導向的東西,比如實施,如果開放的話只能關閉一家晚餐俱樂部,反之亦然,我還應該用康康來做這件事,還是您有更好的建議? – jokklan 2013-05-14 16:01:33

+0

我現在已經改寫了很多我的能力邏輯,看起來好多了。不過,我仍然覺得CanCan不是我的授權類型的最佳選擇...... – jokklan 2013-05-14 16:27:27

+0

你很可能想爲此使用狀態機。查看https://github.com/pluginaweek/state_machine。我相信Ryan Bates也有一個關於此的railscast,你也可以看看。 – Arjan 2013-05-14 16:32:19