Home > Back-end >  Pundit policy for personalized routes
Pundit policy for personalized routes

Time:04-21

I'm working on a rails app where I wrote a personalized route called "all_designs"; with the corresponding method on the controller and the view, before I add pundit to my project it was working fine.

Now I'm having this error:

Pundit::AuthorizationNotPerformedError in DesignsController#all_designs

I understand that I'm missing a policy for this action, but the way I'm trying is not working.

How can I add a policy for this method?

Controller:

class DesignsController < ApplicationController
  before_action :set_design, only: [:show,:edit,:update,:destroy]
  def index
    @designs = policy_scope(Design.where(user: current_user, status: 'activo'))
    @user = current_user
  end

  def all_designs
    @designs = Design.where(user: current_user)
    @user = current_user
  end
  
  ...
end

Policy:

class DesignPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all
    end
  end

  def create?
    true
  end

  def show?
    true
  end

  def destroy?
    user == record.user
  end

  def update?
    # If the user is the owner of the design
    user == record.user
  end

  def all_designs?
    true
  end

end

CodePudding user response:

I would consider separate controller and policy for this as what you're doing is really just a nested route (designs belonging to a singleton resource).

scope 'user', module: :users do
  resources :designs, only: :index
end
module Users
  class DesignsPolicy
    class Scope < Scope
      def resolve
        @user.designs # make sure user has a `has_many :designs` assocation.
      end
    end
  end

  def index?
    true
  end
end
# Represents designs belonging to the current user
module Users
  class DesignsController < ApplicationController
    # GET /user/designs
    def index
      @designs = policy_scope
    end
  end
end

This lets you separate the logic of displaying the the current users designs from /designs which would display everything in a clean way.

CodePudding user response:

Every method on the controller which needs to be authorized, needs to contains an explicit declaration like this:

def all_designs
    @designs = Design.where(user: current_user)
    @user = current_user
    authorize @designs
  end

The reason it wasn't working was: I missed the authorize line

  • Related