Понимание того, как использовать Pundit

Я пытался уложить в голове концепцию политики, которая кажется достаточно простой: политика — это набор правил, по которым определяется доступ к системным привилегиям и ресурсам.

Достаточно просто.

Итак, чтобы пользователь в системе мог получить доступ к списку, скажем, всех остальных пользователей в этой системе, ему потребуются необходимые учетные данные (например, быть администратором или просто войти в систему как зарегистрированный пользователь). Что я изо всех сил пытаюсь понять даже на самом базовом уровне, так это то, как на самом деле ИСПОЛЬЗОВАТЬ Pundit для достижения этой цели. Как и в случае с документацией для многих программ с открытым исходным кодом, которые я пытался изучить, документация Pundit, кажется, в лучшем случае намекает на то, как должен работать инструмент, но не дает полного и конкретного примера хотя бы базового. вариант использования. Все, что я ищу здесь, это пример «hello world», чтобы я не тратил три или четыре дня на сборку запутанной и наполовину работающей реализации для чего-то такого маленького, как это. Более того, примеры, которые приводит Пандит, только еще больше запутывают дело.

В основном я создал тестовое приложение, которое пытается использовать Devise (которое я, кажется, понимаю и умею использовать достаточно хорошо) и Pundit в комбинации. Уже:

  • Пользователь может зарегистрироваться на сайте.
  • Пользователь может войти и выйти.

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

Что я пробовал до сих пор?

  • Я установил Pundit в соответствии с документацией.
  • Я включил Pundit в свой application_controller.rb
  • Я создал политику пользователя, которая выглядит так:

    class UserPolicy < ApplicationPolicy
      class Scope < Scope
        puts "Inside UserPolicy scope."
        attr_reader :user
    
        def initialize(user)
          @user = user
        end
    
        def index
          puts "You've hit the index."
        end
    
        def resolve
          scope
        end
      end
    end
    
    
    class UsersController < ApplicationController
      before_filter :authenticate_user!
      after_action :verify_authorized
      def index
        @users = User.all
        authorize current_user
      end
    end
    

На данный момент я совершенно не понимаю, как связать два класса — класс UserPolicy и UsersController.

Кажется, я, по крайней мере, могу напечатать на своей консоли сообщение «Внутри области действия UserPolicy». но в противном случае просто увидите следующее сообщение об ошибке в браузере:

"не разрешено индексировать? это #"

Чего мне не хватает и, по крайней мере, где пробел в моих собственных знаниях, который делает этот и другие инструменты, связанные с Rails, такими трудными для изучения? Я профессиональный инженер-программист (исторически я был фронтенд-инженером и в последние пару лет работал над тем, чтобы стать разработчиком полного стека), но я слишком часто застреваю с открытым кодом. исходные инструменты, подобные этому.


person Michael P.    schedule 14.06.2015    source источник


Ответы (2)


В вашей реализации есть несколько проблем:

  1. Авторизация действия (например, index?) передается родительскому классу UserPolicy, а не внутреннему классу Scope.
  2. Результат вызова авторизации должен возвращать true или false. Ваш вызов index? возвращает puts "You've hit the index.", что оценивается как nil.
  3. Управление доступом на основе того, вошел ли пользователь в систему, является аутентификацией, а не авторизацией. Pundit должен вступить во владение только после того, как пользователь прошел аутентификацию.
person fylooi    schedule 15.06.2015

На самом деле Pundit — это простые рубиновые объекты, установленные в структуру, подобную рельсам.

Я думаю, что ваша путаница заключается в попытке авторизовать пользователя, подумайте об этом больше с точки зрения ресурсов. Вы ограничиваете доступ пользователей к определенному объекту с помощью определенного успокаивающего действия. Области ограничивают то, что они могут видеть, например, администратор, вероятно, может сделать scope.all, один пользователь, вероятно, не будет допущен или просто сможет ограничить себя на контроллере пользователей.

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

class TicketPolicy < ApplicationPolicy
  class Scope < Struct.new(:user, :scope)
     def resolve
       #Allows government to see their organization
       # only allows citizens to see nothing
       if user.government?
         scope.where(:organization_id => user.organization_id)
       else
         scope.where(:id => 0)
       end
     end
  end


  def index?
    is_government
  end

  def show?
    is_government && is_inside_organization(@record)
  end

  def create?
    is_government && is_inside_organization(@record)
  end

  def new?
    is_government && is_inside_organization(@record)
  end

  def update?
    is_government && is_inside_organization(@record)
  end

  def edit?
    if user.employee?
      return is_mine(@record) && is_inside_organization(@record)
    end
    is_government && is_inside_organization(@record)
  end

  def destroy?
    false
  end
end

Это ограничивает доступ к группам/ролям, а затем в моем контроллере я просто вызываю

authorize @thing

Затем pundit позаботится о доступе на основе политики.

person Austio    schedule 15.06.2015