Pundit Headless Policy
Asked Answered
I

6

9

I'm using pundit for access control in the admin section of my app. I have a dashboards controller that looks like this:

class Admin::DashboardsController < AdminController
  def index
    @total_revenue = Order.total_revenue
    authorize :dashboards, :index?
  end

  ...

end

and a policy that looks like this:

class DashboardPolicy < Struct.new(:user, :dashboard)
  def index?
    true
  end
end

When I try to access /admin/dashboards/ I get a Pundit::NotDefinedError, unable to find policy SymbolPolicy for dashboards

I've also tried namespacing the policy and got the same error.

Imperator answered 5/8, 2014 at 14:32 Comment(0)
M
14

jizak's answer did not work for me, I found following solution for headless name-spaced policies, the trick being with the [:admin, :policy] first argument.

  class Admin::HomeController < AdminController
    def dashboard
      authorize [:admin, :home], :dashboard?
    end
  end

And then for the policy:

Admin::HomePolicy < AdminPolicy
  def dashboard?
    return false unless user && user.admin?
    true
  end
end
Microphyte answered 24/4, 2015 at 3:55 Comment(2)
I don't think you need :dashboard? on authorize method on controller since the method name is the same (dashboard vs dashboard?, well a little bit different on ?) so you don't have to specify the policy's method,Ghostly
Thank you! This answer solved my problem and helped me to understand deeply how to manage namespaces with headless policies.Trilbi
T
4

I have such headless policy:

app/policies/admin/statistic_policy.rb

class Admin::StatisticPolicy < Struct.new(:user, :statistic)

  def show?
    user.admin?
  end

end

app/controllers/admin/statistics_controller.rb

class Admin::StatisticsController < Admin::ApplicationController

  def show
    per_today Time.zone.now
    authorize :statistics, :show?
  end
  ...
end

and it works for me.

Try to update gem, because these changes are new (https://github.com/elabs/pundit/issues/77). Delete your Gemfile.lock from the project and do 'bundle install'.

Tipton answered 6/8, 2014 at 7:46 Comment(0)
S
3

I recently had the same issue. The problem that I faced was that the controller was without a model.

Remember that Pundit is a model based authorization, not so much of controller based.

Before creating an Admin class (in the models), I was getting the same error as you were. Also, take note of the authorization statement on my dashboard action in the controller.

controllers/admin_controller.rb

class AdminController < ApplicationController
  after_action :verify_authorized

  def dashboard
    authorize Admin, :dashboard?
  end
end

models/admin.rb

class Admin
  def self.policy_class
    AdminPolicy
  end
end

policies/admin_policy

class AdminPolicy < Struct.new(:user, :admin)

  def dashboard?
    user.admin?
  end

end
Sisal answered 14/8, 2014 at 18:3 Comment(1)
The version of Pundit available on RubyGems now allows for headless policies. Jizak's answer below has the correct information for the namespacing.Pedicular
B
3

I managed to use Pundit on namespaced controller actions regardless of the model by using this:

In my /private/scrapers_controller.rb I have

module Private
  class ScrapersController < Private::PrivateApplicationController

    # Pundit authorizations
    before_action { authorize [:private, :scrapers] }
    def index
    end
...

And then in policies/private/scrapers_policy.rb

class Private::ScrapersPolicy < ApplicationPolicy
  def index?
    return true if user.has_role?(:super_admin)
    return false
  end
end

This will disallow visiting scrapers#index or any other action within the controller to any user who's not an :super_admin

To disallow only index explicitly you can use:

before_action { authorize [:private, :scrapers], :index? }
Backstitch answered 21/10, 2016 at 10:3 Comment(0)
D
1

Check yout pundit version. You may need to run 'bundle update pundit', because headless policies were merged to master quite recently and before that you had need to install pundit from github: 'elabs/pundit' to use them.

Described issue

Merged headless policies

Dependable answered 2/10, 2014 at 13:23 Comment(1)
Yes I'm pretty sure this is a version issue in my case.Lunchroom
H
0

if you just want to render landing page for controller dashboard#index for example, where no need to authorize users you can just skip authorization like

dashboard_controller.rb

class DashboardController < ApplicationController  
  def index        
    skip_policy_scope
  end  
end

And therefore you don't have to create DashboardPolicy at all.

Hachman answered 31/3, 2016 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.