0

Я борюсь с авторизацией действия индекса вложенного ресурса при использовании Pundit. Пандит настолько скользкий и потенциально легкий, что я ненавижу отбрасывать его, потому что я не могу понять это. Я понимаю, как только я пойму эту часть, все остальное упадет в линию. Я читал много сообщений о людях, задавая очень похожие вопросы тем, которые я задаю, и кажется, что сообщения, которые ближе всего подходят к вопросу, который я прошу, никогда не решаются. Итак, я все еще ищу ответ.Как ограничить авторизацию действием индекса ресурса пользователя с помощью Pundit? Я не думаю, что ответ является областью

class User < ApplicationRecord 
    enum role: [:user, :admin] 
    after_initialization :set_default_role, :if => :new_record? 
    def set_default_role 
    self.role ||= :user 
    has_many :galleries, dependent: :destroy 
end 

class Gallery < ApplicationRecord 
    belongs_to :user 
    validates :user_id, presence: true 
    validates :title,, presence: true 
end 

У меня есть пользовательский настрой, как я хочу его с помощью UserPolicy. Он не наследуется от ApplicationPolicy, потому что учебник, на который я смотрел, сказал, что мне это не нужно.

моих маршрутов выглядеть следующим образом:

devise_for :users, path: 'accounts 
resources :users, shallow: true do 
    resources :galleries 
end 

По существу я не хочу один пользователь, чтобы увидеть другие пользователь вещи, т.е. индекс, шоу ... действия. Я считаю, что это называется закрытой системой. Мой маршрут для просмотра галереи пользователя (мой вложенный ресурс) Индекс выглядит следующим образом:

localhost:/users/20/galleries 

Я не хочу пользователя 19, чтобы когда-либо видеть, что пользователь 20 имеет в своей галерее индекс. Как мне это сделать?

Это то, что мой GalleryController выглядит следующим образом:

before_action :authenticate_user! #I'm using devise 
def index 
    @galleries = current_user.galleries.all 
    #authorize ????? <<part of what I don't understand 
end 

private 
def gallery_params 
    params.require(:gallery).permit(:title) 
end 

Действительно, я не знаю, что я должен делать в GalleryPolicy для индекса. Я разработал действие show, потому что он просто проверяет экземпляр галереи на экземпляр идентификатора пользователя. Здесь представлено GalleryPolicy

attr_reader :user, :model 

def initialize(user, model) 
    @user = user 
    @gallery = gallery 
end 

def show? 
    @gallery.user_id == user.id 
end 

def index? 
    # I can't figure it out 
end 

def new? 
    #actually this is confusing too 
end 

ответ

1

Прежде всего, я всегда писал политика Пандита, наследуемая от ApplicationPolicy так что давайте начнем оттуда. ApplicationPolicy инициализируется пользователем и записью. Запись будет вашей моделью, которую вы хотите, чтобы пользователь получил разрешение на просмотр. В этом случае галерея.

Во-вторых, каждая политика должна включать область действия. Это также инициализируется внутри ApplicationPolicy, но ваша задача - ограничить область по мере необходимости.

class GalleryPolicy < ApplicationPolicy 
    class Scope < Scope 
    def resolve 
     scope.where(:user_id => user.id) 
    end 
    end 

    # no need for an index? method here. we will see this in the controller 

    # essentially here we are checking that the user associated to the record 
    # is the same as the current user 
    def show? 
    record.user == user 
    end 

    # this is actually already the case in ApplicationPolicy but I added 
    # it here for clarity 
    def new? 
    create? 
    end 

    # who do we want to be able to create a gallery? anyone! 
    # so this simple returns true 
    def create? 
    true 
    end 
end 

Затем в вашем GalleryController вы будете авторизовать модели каждый раз. Только действие индекса немного отличается, как мы увидим сейчас:

# controllers/gallery_controller.rb 
def index 
@galleries = policy_scope(Gallery) 
# as we specified the scope in GalleryPolicy to only include galleries which belong 
# to the current user this is all we need here! 
end 

# your other actions will look something like this: 
def show 
    @gallery = Gallery.find(params[:gallery_id] 
    authorize @gallery 
end 

def new 
    @gallery = Gallery.new # or @gallery = current_user.galleries.build 
    authorize @gallery 
end 

[...] 

Надеюсь, это поможет! Pundit - отличный инструмент, когда вы справитесь с этим.

+0

Я ценю ваш комментарий. Я реализовал все, как вы сказали, но это не изменило ситуацию. 1st: UserA все еще может видеть индекс галереи UserB. 2nd: Каждый индекс галереи пользователя имеет все галереи других пользователей. Я хочу перенаправить UserA на другую страницу со флэш-сообщением, в котором говорится «Доступ запрещен», если они попытаются перейти на страницу индекса галереи галереи UserB. И я не хочу, чтобы галереи других пользователей отображались в другом индексе галереи пользователя. – Lenocam

+0

На самом деле, я думаю, ты прав. Проблема, с которой я сейчас сталкиваюсь, связана, но не та, которую я попросил помочь. Это работает. Благодаря! – Lenocam

+0

рад, что я мог бы помочь! Если вы разместите еще один вопрос с вашей новой проблемой, пришлите мне ссылку здесь, и я посмотрю на нее, чтобы посмотреть, смогу ли я помочь :) – cdimitroulas