Как я могу использовать cancan для авторизации массива ресурсов? - PullRequest
5 голосов
/ 27 марта 2011

У меня есть контроллер без перерыва, который я пытаюсь использовать для авторизации cancan!метод применения разрешений к.

У меня есть действие delete_multiple, которое начинается примерно так:

def delete_multiple
    @invoices = apparent_user.invoices.find(params[:invoice_ids])

Я хочу проверить, что у пользователя есть разрешение на удаление всех этих счетов, прежде чем продолжить.Если я использую

authorize! :delete_multiple, @invoices

разрешение будет отклонено.В моем файле powers.rb содержится следующее

if user.admin?
  can :manage, :all
elsif user.approved_user?
  can [:read, :update, :destroy, :delete_multiple], Invoice, :user_id => user.id
end

Это цикл по моему массиву и индивидуальный вызов авторизации или есть более разумный способ сделать что-то?Я начинаю чувствовать, что делать авторизацию проще, чем вручную, используя cancan для сложного контроллера без перегрузки (хотя в моем приложении много других контроллеров restful, где он прекрасно работает).

Ответы [ 2 ]

11 голосов
/ 15 сентября 2011

Здесь немного поздно, но вы можете написать это в своем классе способностей

can :delete_multiple, Array do |arr|
  arr.inject(true){|r, el| r && can?(:delete, el)}
end

РЕДАКТИРОВАТЬ

Это также можно записать как:

can :delete_multiple, Array do |arr|
  arr.all? { |el| can?(:delete, el) }
end
1 голос
/ 17 августа 2012

Кажется, что authorize! работает только для одного экземпляра, а не для массива.Вот как я справился с этим с Rails 3.2.3 и CanCan 1.6.7.

Основная идея состоит в том, чтобы подсчитать общее количество записей, которые пользователь пытается удалить, подсчитать записи, которые accessible_by (current_ability, :destroy), а затем сравнить их.

Если вы просто хотели получить массив иззаписи, которые пользователь имеет право уничтожать, вы можете использовать массив, возвращаемый accessible_by (current_ability, :destroy).Однако я использую destroy_all, который работает непосредственно с моделью, поэтому я решил использовать это решение для подсчета и сравнения.

Стоит проверить журнал разработки, чтобы увидеть, как два SELECT COUNTоператоры выглядят следующим образом: во втором должны быть добавлены WHERE фразы для ограничений авторизации, наложенных CanCan.

Мой пример касается удаления нескольких сообщений.

способность.rb

if user.role_atleast? :standard_user
  # Delete messages that user owns
  can [:destroy, :multidestroy], Message, :owner_id => user.id
end

messages_controller.rb

# Suppress load_and_authorize_resource for actions that need special handling:
load_and_authorize_resource :except => :multidestroy
# Bypass CanCan's ApplicationController#check_authorization requirement:
skip_authorization_check :only => :multidestroy

...

def multidestroy
  # Destroy multiple records (selected via check boxes) with one action.
  @messages = Message.scoped_by_id(params[:message_ids]) # if check box checked
  to_destroy_count =  @messages.size
  @messages = @messages.accessible_by(current_ability, :destroy) # can? destroy
  authorized_count =  @messages.size

  if to_destroy_count != authorized_count
    raise CanCan::AccessDenied.new # rescue should redirect and display message
  else # user is authorized to destroy all selected records
    if to_destroy_count > 0
      Message.destroy_all :id => params[:message_ids]
      flash[:success] = "Permanently deleted messages"
    end
    redirect_to :back
  end
end 
...