Почему Declarative_Authorization нарушает функциональность моего контроллера?- Рельсы 3 - PullRequest
2 голосов
/ 26 августа 2011

У меня есть Coupons контроллер с двумя действиями.

class CouponsController < ApplicationController
  filter_resource_access

  def index
    @coupons = Coupon.all
  end

  #generates 10 new coupons on each call
  def generate
    plan_id = params[:plan_id]
    numdays = params[:num_days]

    (1..10).each do |i|
      validChars = %w{ 1 2 3 4 5 6 7 9 a A b B d D e E f g G h H j J k K m M n N p P q Q r R t T }.to_a

      code = (0...6).map{ validChars[ rand(validChars.size) ] }.join

      coupon = Coupon.new
      coupon.code = code
      coupon.plan_id = plan_id
      coupon.active = false
      coupon.subdays = numdays
      coupon.save
    end
    redirect_to :coupons_path
  end

end

Генерирующее действие вызывается, на мой взгляд, так:

<h2 class="page-title">Coupons</h2>
<div class="main">
   <%= form_tag "coupons/generate" do -%>
        <%= hidden_field_tag 'user[plan_id]', "1" %>
        <%= hidden_field_tag 'user[num_days]', "150" %>
      <%= submit_tag "Generate 10 Coupons!", :class => "primary button" %>
   <% end -%>
    <table border="0" class="list">
        <thead>
            <tr>
                <th>Code</th><th>Plan</th><th>Duration</th><th>Activated</th>
            </tr>
        </thead>
        <tbody>
        <% if !@coupons.nil? %>
            <% @coupons.each do |coupon| %>
            <tr class="<%#= list_entry or list_entry_alt %>">
                <td><%= coupon.code %></td>
                <td><%= coupon.plan_id  %></td>
                <td><%= coupon.subdays %> days</td>
                <td><% if coupon.started.nil? == true  %>
                    <%= 'Not yet' %>
                    <% else %>
                    <%= time_ago_or_time_stamp coupon.started %>
                    <% end %>
                    </td>
            </tr>
            <% end %>
        <% end %>
        </tbody>
     </table>
</div>

Мой config/authorization_rules.rb выглядит так:

has_permission_on [:coupons], :to => [:index, :show, :step, :new, :create, :edit, :update, :destroy, :generate]

Ошибка всех приведенных выше бросков такова:

filter_access_to tried to find Coupon from params[:id] (nil), because attribute_check is enabled and @coupon isn't set, but failed: ActiveRecord::RecordNotFound: Couldn't find Coupon without an ID
Completed 404 Not Found in 245ms

ActiveRecord::RecordNotFound (Couldn't find Coupon without an ID):

Однако, как только я изменяю filter_resource_access на filter_access_to :all, :except => :generate, это больше не дает мне ошибки и вроде работает.

т.е. он генерирует некоторые коды купонов, которые я ищу, но он не включает номер plan_id или количество дней в выводе в представлении.

Почему это? Что я делаю не так?

Редактировать 1: Кстати, это действительно ограничивает правильных людей ... то есть. только указанные роли могут просматривать coupons index view. Так что фильтр частично работает.

Ответы [ 5 ]

2 голосов
/ 23 февраля 2012

filter_resource_access запускает декларативную платформу аутентификации для поиска параметра: id для вашего ресурса (в методах, не относящихся к коллекции / создателю).

В вашем примере это будет делать @coupon = Coupon.найти (params [: id]) и установить эту переменную-член для вашего контроллера.Однако, поскольку в это действие по этому маршруту не поступают params [: id], он терпит неудачу.

Обойти его, сохраняя при этом разрешения контроллера, довольно просто.Просто поместите это в верхней части вашего контроллера в строке filter_resource_access:

filter_resource_access :additional_collection => { :generate => :read } 
# I tried the two lines below but to no avail
#filter_resource_access :additional_collection => { :generate => :read }, :no_attribute_check => [ :generate ]
# filter_access_to :generate, :attribute_check => false

Это поддерживает ваши проверки разрешений на действия других контроллеров, а также действие «генерировать», но освобождает метод «генерировать» отавтоматический поиск искателя.

Для получения дополнительной информации см .: http://rubydoc.info/github/stffn/declarative_authorization/master/Authorization/AuthorizationInController/ClassMethods

1 голос
/ 12 июня 2012

Проблема в том, что с filter_resource_access предполагается, что контроллер использует действия ресурса по умолчанию и пытается найти дилера, если params [: id] для действий, которые не являются стандартными. Что вам нужно сделать, это добавить

filter_access_to :all

И добавьте соответствующее правило для: generate к вашему authorization_rules.rb. Как

role :someone do
    has_permission_on :coupon, :to => :generate
    ...
end
1 голос
/ 26 августа 2011

Я предполагаю, что filter_resource_access обрабатывает все действия в контроллере так, как будто они имеют дело с одним ресурсом и пытается выполнить Coupon.find(params[:id]).Изменив его на следующее:

filter_access_to :all, :except => :generate

Вы говорите, что не запустите этот метод перед этим действием, то есть он не будет пытаться найти купон.

0 голосов
/ 02 сентября 2011

filter_resource_access пытается создать объект ресурса для вас, поэтому вам нужно посмотреть на параметры :additional_member или :additional_collection или использовать параметр except, как вы отметили.

Что касается отсутствующих параметров плана, вы уверены, что они входят как params[:plan_id]? проверьте ваши логи devel, чтобы увидеть, как выглядят входящие параметры.

Вы также не проверяете успешность вызова save, поэтому, если возникнет ошибка, вы ее не узнаете.

0 голосов
/ 02 сентября 2011

Декларативная авторизация требует, чтобы вы объявили купон как переменную экземпляра.

В вашем контроллере попробуйте изменить coupon = Coupon.new на @coupon = Coupon.new (очевидно, измените последующие строки соответственно.)

...