Пандит: как дать возможность пользователю иметь доступ либо ко всем садам, либо только к его собственным? - PullRequest
1 голос
/ 12 марта 2019

Я пытаюсь определить 2 возможных индекса для пользователей, чтобы дать им возможность иметь доступ ко всем опубликованным садам или только к тому, который они опубликовали самостоятельно (2 разные страницы).Я полностью теряюсь, когда делаю это с pundit, так как это зависит не от статуса пользователя, а только от того, что он хочет отобразить.Любая идея ??Спасибо:)

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!
include Pundit

  # Pundit: white-list approach.
  after_action :verify_authorized, except: [:index, :my_gardens], unless: :skip_pundit?
  after_action :verify_policy_scoped, only: [:index, :my_gardens], unless: :skip_pundit?

  # Uncomment when you *really understand* Pundit!
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
  def user_not_authorized
    flash[:alert] = "You are not authorized to perform this action."
    redirect_to(root_path)
  end

  private

  def skip_pundit?
    devise_controller? || params[:controller] =~ /(^(rails_)?admin)|(^pages$)/
  end
end

garden_controller.rb

class GardensController < ApplicationController
  before_action :set_garden, only: [:show, :destroy, :edit, :update ]
  def new
    @garden = Garden.new
    authorize @garden
  end

  def create
    @garden = Garden.new(garden_params)
    authorize @garden

    @garden.user = current_user
# OU :     @garden = current_user.gardens.build(garden_params)

    respond_to do |format|
      if @garden.save
        format.html { redirect_to @garden, notice: 'Garden was successfully created.' }
        format.json { render :show, status: :created, location: @garden }
      else
        format.html { render :new }
        format.json { render json: @garden.errors, status: :unprocessable_entity }
      end
    end
  end

  def index
      @gardens = policy_scope(Garden)
  end

  def my_gardens
    @gardens = policy_scope(Garden).find(params[user_id: current_user.id])
  end

  def show
    authorize @garden
  end

  def destroy
    authorize @garden

    @garden.destroy
    respond_to do |format|
      format.html { redirect_to gardens_url, notice: 'garden was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def edit
    authorize @garden
  end

 def update
  authorize @garden

  respond_to do |format|
    if @garden.update(garden_params)
      format.html { redirect_to @garden, notice: 'Garden was successfully updated.' }
      format.json { render :show, status: :ok, location: @garden }
    else
      format.html { render :edit }
      format.json { render json: @garden.errors, status: :unprocessable_entity }
    end
  end
end

  private

  def garden_params
    params.require(:garden).permit(:title, :details, :surface, :address)
  end

  def set_garden
    @garden = Garden.find(params[:id])
  end
end

application_policy.rb

class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end

  def index?
    false
  end

  def my_gardens?
    false
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  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

garden_policy.rb

class GardenPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
      scope.all #>> permet d'afficher tous les restos dans index
    end
  end

  def create?
    true
  end

  def update?
    user_is_the_owner_or_admin?
  end

  def destroy?
    user_is_the_owner_or_admin?
  end

  def index?
    true
  end

  def show
    scope.where(:id => record.id).exists?
  end

  private

  def user_is_the_owner_or_admin?
    user.admin || record.user == user
  end
end

schema.rb

  create_table "gardens", force: :cascade do |t|
    t.string "title"
    t.text "details"
    t.integer "surface"
    t.text "address"
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "admin", default: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

1 Ответ

0 голосов
/ 13 марта 2019

Вы можете решить эту проблему, просто создав отдельную область.

class GardenPolicy < ApplicationPolicy
  # ...
  class MyScope < ApplicationPolicy::Scope
    def resolve
      scope.where(user: user)
    end
  end 
end

Используйте параметр policy_scope_class, чтобы сообщить Pundit о своей пользовательской области:

class GardensController < ApplicationController
  # ...
  def my_gardens
    @gardens = policy_scope(Garden, policy_scope_class: GardenPolicy::MyScope)
  end
end

Подробно в файле readme .

...