Is it possible to use single method to authorise multiple controller action in Rails Pundit?

I am created new rails application and I want to restrict user actions based on only one condition like record can be editable by owner(created_by) and sub-owner(Added by owner). I have models like App, User and controller like AppController. In AppController I have more than one actions like index, create, show, update, delete. I have one policy like AppPolicy. Here I need to create only one method to verify all actions but by default each action requires another method like action_name? in policy class.

Example

Existing code:

class AppPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
     scope
   end
 end

 def action1?
  record.users.include? (user)
 end

 def action2?
  record.users.include? (user)
 end

 def action3?
   record.users.include? (user)
 end

end

From above code we can see a same condition reside in all methods. I need to use only one method to verify action1, action2, action3. I don't know this is possible or not in Pundit.

Upvotes: 2

Views: 1515

Answers (3)

gmm
gmm

Reputation: 1022

I also just had this same problem.

Ive done it with an admin policy. In any controller action, do authorize [:admin, :user], :admin?

The first part tells Pundit what policy to use, the second which authorization method.

The policy class:

class Admin::UserPolicy
  attr_reader :current_user, :model

  def initialize(current_user, model)
    @current_user = current_user
  end

  def admin?
    @current_user.has_admin_privilege?('full_admin')
  end
end

Upvotes: 0

Lorenzo Baracchi
Lorenzo Baracchi

Reputation: 1968

I know this is an old question but I just had the same problem.

I can think about 2 solutions:

solution 1

When you know all the actions that could be called.

You can use define_method, like this

[:action1?, :action2?].each do |m|
  define_method(m) { record.users.include? (user) }
end

solution 2

When you don't know all the actions. (this could be dangerous)

You can use a combination of method_missing and respond_to_missing. The latter is needed since pundit will call internally respond_to before calling the corresponding method of the policy. Example:

  def method_missing(m, *args, &block)
    record.users.include? (user)
  end

  def respond_to_missing?(method_name, include_private = false)
    true #Here it would be better to add some conditions
  end

Upvotes: 0

Fabio Ros
Fabio Ros

Reputation: 164

You can use cancan (or cancancan) gem rubygems link

You can create the ability configuration file with

rails g cancan:ability

The authorize! method in your controller will raise an exception if the user is not able to perform the given action, so call it on before_action callback.

Documentation here

Upvotes: -4

Related Questions