The question is about getting Rails 5 and authorizing Pundit working with namespaces.
With Pundit in the controller I wanted to use policy_scope([:admin, @car]that will use Pundit policy file located at: app/policies/admin/car_policy.rb. I have problems with Pundit working with this namespace - without a namespace, it works fine.
The application is running:
- Rails 5
- Configure for authentication
- Pundit for authorization
My namespace for adminsexample.
The file route.rblooks like this:
devise_for :admins
root: 'cars#index'
resources :cars
namespace :admin do
root 'cars#index'
resources :cars
end
Pundit ApplicationPolicy , Pundit authorize: @record = record.is_a?(Array) ? record.last : record
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record.is_a?(Array) ? record.last : record
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
Admin::CarsController authorize [:admin, @cars]
class Admin::CarsController < Admin::BaseController
def index
@cars = Car.order(created_at: :desc)
authorize [:admin, @cars]
end
def show
@car = Car.find(params[:id])
authorize [:admin, @car]
end
end
Policy Scope
class Admin::CarPolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user?
scope.all
else
scope.where(published: true)
end
end
end
def update?
user.admin? or not post.published?
end
end
Admin::CarsController
class Admin::CarssController < Admin::BaseController
def index
@cars = policy_scope([:admin, @cars])
authorize [:admin, @cars]
end
def show
@car = policy_scope([:admin, @car])
authorize [:admin, @car]
end
end
, Pundit Admin::CarPolicy. , .
, - policy_scope(Admin::Car), :).
.
Update
Pundit Github: https://github.com/elabs/pundit/pull/391
policy_scope, .
Pudit gem → policy_scope! lib/pundit.rb.
From:
def policy_scope!(user, scope)
PolicyFinder.new(scope).scope!.new(user, scope).resolve
end
To:
def policy_scope!(user, scope)
model = scope.is_a?(Array) ? scope.last : scope
PolicyFinder.new(scope).scope!.new(user, model).resolve
end
: Rails? ?
pundit.rb config/initializer module_eval, , , policy_scope! module Pundit class << self.
, , - , , policy_scope! class << self.
Pundit::module_eval do
def policy_scope!(user, scope)
model = scope.is_a?(Array) ? scope.last : scope
PolicyFinder.new(scope).scope!.new(user, model).resolve
end
end