J'utilise le pundit gem
afin de donner des permissions à trois utilisateurs différents (Admin, vendeur, spectateur). Actuellement, j'ai tout ce qui fonctionne, l'administrateur a accès à tout, le vendeur à ses propres produits et le spectateur peut simplement voir les produits.Rails pundit gem, permettre la vue aux utilisateurs non-signés
Le seul problème que j'ai, c'est que je voudrais que les utilisateurs de non signed_up/signed_in puissent voir les produits via les résultats de recherche. Actuellement, les utilisateurs non sign_up/signed_in peuvent voir les résultats de la recherche mais n'ont pas accès à la vue du diaporama.
Voici la configuration que j'ai:
class ItemPolicy < ApplicationPolicy
attr_reader :item
def initialize(user, record)
super(user, record)
@user = user
@item = record
end
def update?
@user.is_a?(Admin) ? item.all : @user.items
end
def index?
@user.is_a?(Admin) ? item.all : @user.items
end
def show?
@user.is_a?(Admin) ? item.all : @user.items
end
def create?
@user.is_a?(Admin) ? item.all : @user.items
end
def new?
@user.is_a?(Admin) ? item.all : @user.items
end
def edit?
@user.is_a?(Admin) ? item.all : @user.items
end
def destroy?
@user.is_a?(Admin) ? item.all : @user.items
end
class Scope < Struct.new(:user, :scope)
def resolve
if user.is_a?(Admin)
scope.where(:parent_id => nil)
elsif user.is_a?(Seller)
scope.where(:id => user.items)
end
end
def show?
return true if user.is_a?(Admin)
return true if user.seller_id == seller.id && user.is_a?(Seller)
false
end
end
end
le contrôleur:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update, :destroy]
def index
authorize Item
@items = policy_scope(Item)
end
def search
if params[:term]
@items = Item.search(params[:term]).order("created_at DESC")
else
@items = []
end
end
def show
@comments = Comment.where(item_id: @item).order("created_at DESC")
@items = policy_scope(Item).find(params[:id])
authorize @item
end
def new
@item = Item.new
authorize @item
@categories = Category.order(:name)
end
def edit
authorize @item
@categories = Category.order(:name)
end
def create
@item = Item.new(item_params)
authorize @item
respond_to do |format|
if @item.save
format.html { redirect_to @item, notice: 'Item was successfully created.' }
format.json { render :show, status: :created, location: @item }
else
format.html { render :new }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
def update
authorize @item
respond_to do |format|
if @item.update(item_params)
format.html { redirect_to @item, notice: 'Item was successfully updated.' }
format.json { render :show, status: :ok, location: @item }
else
format.html { render :edit }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
def destroy
authorize @item
@item.destroy
respond_to do |format|
format.html { redirect_to items_url, notice: 'Item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_item
@item = Item.find(params[:id])
authorize @item
end
def item_params
params.require(:item).permit(:title, :description, :image, :price, :category_id)
end
end
application_contoller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery prepend: true
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def pundit_user
current_seller || current_admin || current_viewer
end
private
def user_not_authorized(exception)
policy_name = exception.policy.class.to_s.underscore
flash[:warning] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
redirect_to(request.referrer || root_path)
end
end
Update 1
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
raise Pundit::NotAuthorizedError, "must be logged in" unless user
@user = user
@record = record
end
def index?
true # anybody can view
end
def show?
true # anybody can view
end
def search?
index?
end
def new?
create?
end
def edit?
update?
end
def destroy?
update?
end
private
# don't repeat yourself
def admin?
user.is_a?(Admin)
end
def seller?
user.is_a?(Seller)
end
end
class ItemPolicy < ApplicationPolicy
attr_reader :item
class Scope < Struct.new(:user, :scope)
def resolve
if admin?
scope.where(parent_id: nil)
elsif seller?
# avoids a query for user.items
scope.where(seller: user)
end
end
end
def initialize(user, record)
super(user, record)
@user = user
@item = record
end
def update?
admin? || is_owner?
end
def create?
# just guessing here
admin? || seller?
end
private
def is_owner?
# or whatever the association between the item and its owner is
item.seller == user
end
end
Merci pour l'info et aide encore une fois @max !!! J'ai mis à jour mon code en fonction de votre réponse, mais je ne peux toujours pas obtenir les «utilisateurs non autorisés» pour voir la page d'affichage ... même lorsqu'un utilisateur est connecté, il peut voir et modifier tous les éléments maintenant. J'ai ajouté la mise à jour 1 à ma question afin que vous puissiez voir ce que j'ai fait jusqu'à présent. – Theopap
Un administrateur peut voir et modifier tous les éléments. Si ce n'est pas ce que vous voulez changer la logique dans le #update? méthode. Aussi, pour permettre aux utilisateurs non autorisés d'accéder à une ressource, vous devez ignorer le 'authorize_user' de Devise. (Ou quoi que ce soit) rappel. – max
Oui c'est exactement je veux, l'administrateur d'avoir accès à tous, le vendeur seulement son sur les articles, le spectateur seulement l'index des résultats de recherche et de montrer .... mais actuellement avec vos modifications ... un vendeur connecté peut modifier/afficher/supprimer tous les éléments. – Theopap