2013-05-14 3 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

Спасибо, что это помогает! Что относительно того, что на самом деле не является авторизацией, ориентированной, как реализация, что вы можете закрыть только клуб обеда, если он открыт, и наоборот, должен ли я также делать это с cancan или у вас есть какие-то лучшие предложения? – jokklan

+0

Теперь я переписал много логики моей способности, и это выглядит намного лучше. Однако я все еще чувствую, что CanCan не лучший выбор для моего вида авторизации ... – jokklan

+0

Вы, вероятно, хотите использовать для этого конечный автомат. Проверьте https://github.com/pluginaweek/state_machine. Я полагаю, что Рейанс об этом также говорит Райан Бэйтс, вы тоже могли бы посмотреть на это. – Arjan

Смежные вопросы