Проверка параметров действия в Rails CanCanCan Авторизация

Можно ли получить доступ к параметрам контроллера при определении способностей в ability.rb?

У меня есть мероприятие и пользователи, которые могут принять в нем участие или создать его. Похоже, я мог бы создать другое действие контроллера для каждого возможного сценария, например. пользователь подписывается на событие, или создатель удаляет кого-то из мероприятия. Однако я думаю, что было бы намного легче читать, если бы было меньше действий и было бы возможность определять возможности на основе того, какие параметры передаются от клиента.

Отвечать

У @chumakoff ниже есть полезная информация, которая помогла объяснить, как работает CanCanCan. Я решил разрешить эти действия по умолчанию в ability.rb, а затем выдать ошибку, например raise CanCan::AccessDenied.new("You cannot delete someone else from this event") в контроллере, если я обнаружил, что отправляются неверные идентификаторы параметров пользователя / события.


person James L.    schedule 05.09.2017    source источник


Ответы (2)


Если я правильно понимаю, вы используете помощник контроллера cancan authorize_resource или load_and_authorize_resource, который вычисляет возможности пользователя на основе имен действий контроллера.

Но использовать этот помощник для всех действий не обязательно. Вы можете пропустить его для действий со сложной логикой способностей и проверить способности вручную.

Например:

class ParticipationsController < ApplicationController
  authorize_resource except: :create # skiping `authorize_resource` for `create` action

  # ...

  def create
    if creator_adds_someone_to_event?
      authorize! :add_to, @event
    end

    if user_signs_up_for_event?
      authorize! :sign_up_for, @event
    end
    # ...
  end

Таким образом, вы можете проверить множество разных способностей в одном и том же действии контроллера. Просто отключите cancancan's поведение по умолчанию для действия.

person chumakoff    schedule 05.09.2017
comment
Эй, это выглядит довольно близко! Источник: github.com/CanCanCommunity/cancancan/wiki/ Почему вы разрешаете другие действия внутри действия create? Я думал, что проверю / разрешу внутри каждого соответствующего действия. Судя по тестированию, похоже, что ключевое слово authorize! применяет любые разрешения, установленные в ability.rb, поэтому я предполагаю, что алгоритм будет заключаться в том, чтобы не создавать никаких правил для этих действий в ability.rb, а затем authorize! внутри действия, когда обнаруживаются неправильные разрешения. Это почему-то плохая практика? Кажется немного запутанным. - person James L.; 05.09.2017
comment
Похоже, вы можете вручную выдавать ошибки в действиях контроллера вместо того, чтобы пытаться зафиксировать эту функциональность с помощью authorize! - какой вариант, по вашему мнению, лучше? raise CanCan::AccessDenied.new("Not authorized!") - github.com/CanCanCommunity/cancancan/wiki/Exception-Handling - person James L.; 05.09.2017
comment
Объединять сложную логику в одно действие может быть плохой практикой. Наличие действий способностей, не соответствующих действиям контроллера, - нормальный случай. Вам следует raise CanCan::AccessDenied только в том случае, если authorize! не делает именно то, что вы хотите. Например, если вы хотите изменить сообщение об ошибке. - person chumakoff; 05.09.2017
comment
Что вы подразумеваете под действиями способностей, а не действиями контроллера? Я вижу, насколько сложно поддерживать распространение логики способностей из capacity.rb на разные действия, но если я хочу получить доступ к параметрам клиента, не похоже, что у меня большой выбор. Имея все это в виду, вот о чем я думаю. Разрешите эти действия в ability.rb и проверьте параметры внутри действия контроллера. Если они ссылаются на неправильного пользователя / событие, raise возникает ошибка. Звучит неплохо? - person James L.; 05.09.2017
comment
Трудно сказать, не видя вашего кода и логики. Удачи! ) - person chumakoff; 05.09.2017

Да, есть инструмент отладки под названием «pry». Используйте это, чтобы помочь вам. Просто используйте binding.pry везде, где вы хотите проверить значение параметров в коде, и консоль прекратит выполнение в этот момент, чтобы вы могли проверить значение параметров.

person Sarthak    schedule 05.09.2017