I have built a web app using rails 4.2.4, devise and a pins scaffolding where users can CRUD a pin.
I am about to medicate myself trying to get pundit working so that only the Admin can CRUD a pin, all users signed in or guests can only view and cannot create, update or destroy.
I get a litany of errors like this>
Facts:
I have 2 models pin.rb and user.rb
I have a pins_controller.rb
I done a migration add_admin_to_users.rb (do i need further intervention in the console to set something up for admin besides this)
Can I get help with the syntax and my failed approach
class ApplicationPolicy
attr_reader :user, :pin
def initialize(user, pin)
raise Pundit::NotAuthorizedError, "must be logged in" unless user
@user = user
@pin = pin
end
def index?
true
end
def show?
scope.where(:id => record.id).exists?
end
def create?
user.admin?
end
def new?
user.admin?
end
def update?
user.admin?
end
def edit?
update?
end
def destroy?
user.admin?
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
Blockquote
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
if params[:search].present? && !params[:search].nil?
@pins = Pin.where("description LIKE ?", "%#{params[:search]}%").paginate(:page => params[:page], :per_page => 15)
else
@pins = Pin.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 15)
end
end
def show
end
def new
@pin = current_user.pins.build
end
def edit
end
def create
@pin = current_user.pins.build(pin_params)
if @pin.save
redirect_to @pin, notice: 'Pin was successfully created.'
else
render :new
end
end
def update
if @pin.update(pin_params)
redirect_to @pin, notice: 'Pin was successfully updated.'
else
render :edit
end
end
def destroy
@pin.destroy
redirect_to pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
@pin = Pin.find_by(id: params[:id])
end
def correct_user
@pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if @pin.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description, :image)
end
end
Blockquote
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
devise_parameter_sanitizer.for(:account_update) << :name
end
private
def user_not_authorized
flash[:warning] = "You are not authorized to perform this action."
redirect_to(request.referrer || root_path)
end
end
The errors occur most likely simply do to the fact, that, well, as the exception states, there is no PinPolicy
class. Apart from general ApplicationPolicy
you should also define the policy for each resource (which inherits from main ApplicationPolicy
).
Add it under /policies
directory:
class PinPolicy < ApplicationPolicy
class Scope < Scope
def resolve
return scope if user.admin?
fail 'scope is not defined'
end
end
end