2016-01-25 1 views
1

Я использую CanCan 1.6.1 в приложении Rails 3.2. Я использую authorize_resource в своих контроллерах, чтобы ограничить то, что пользователи могут :read, :create, :update: and :delete.CanCan Rails Как ограничить пользователей чтением данных, которые они не создали

В моем V2Posts controller звонок authorize_resource не работает для моего :show действия.

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

class V2PostsController < ApplicationController 
    layout 'panel_layout', only: :show 
    before_filter :redirect_if_existing, only: [:new, :create] 

    authorize_resource 

    def show 
    @v2_post = V2Post.find(params[:id], include: :user_updates) 
    @organization = @v2_post.organization 

    respond_to do |format| 
     format.html 
     format.js 
    end 
    end 
    ... 
end 

ability.rb:

class Ability 
    include CanCan::Ability 

    @user = nil 

    def initialize(user) 
    alias_action :taco, 
       :sandwich, 
       to: :read 

    @user = user 

    if user.is_in_role?(:admin) 
     can :manage, :all 
    else 
     default_rules 

     user.roles_list.each do |role| 
     meth = :"#{role}_rules" 
     send(meth) if respond_to? meth 
     end 
    end 
    end 

    def default_rules 
    cannot [:read, :create, :update, :destroy], :all 
    ... 
    end 

    def pro_user_rules 
    can :read, V2Post, proid: @user.id 
    end 
... 
end 

модели/v2_post.rb:

class V2Post < ActiveRecord::Base 
    attr_accessible :proid, :user_updates_attributes, :organization 

    belongs_to :user, :foreign_key => "proid" 
    has_many :user_updates, as: :pro_post, dependent: :destroy 
    accepts_nested_attributes_for :user_updates 

end 

load_and_authorize_resource работы для хранения пользователей от просмотра сообщений других пользователей. Но он загружает ресурс для меня, а также добавляет дополнительные вызовы базы данных для других действий. Не должно authorize_resource работать для моего дела? Я явно определил @ v2_posts в действии show (загружая ресурс самостоятельно). Почему он не переходит к вызову authorize_resource?

  • Я хочу, чтобы избежать требующих дополнительных вызовов к базе данных
  • Я не хочу, чтобы автоматически загрузить ресурс для пользовательских действий
  • Я хочу, чтобы разрешить все CRUD действия.

Учитывая, что, какой из load_and_authorize_resource и authorize_resource работает лучше, и какие преимущества/недостатки каждого из них? Я читал документацию, я в замешательстве.

ответ

0

Проблема заключается в том, что authorize_resource запускается как фильтр before, и экземпляр не устанавливается до тех пор, пока внутри вашего действия - после вызова authorize_resource. Когда экземпляр равен нулю, метод authorize_resource по умолчанию разрешает класс V2Report. Авторизация класса игнорирует условия атрибута (например, можно: прочитать V2Report, user_id: @ v2_post.user_id).

Вы можете использовать ресурс load_and_authorize, а CanCan установить переменную экземпляра в контроллере перед каждым действием. Для действий, которые загружают ресурс более сложным способом, например ваш V2Post.find(params[:id], include: :user_updates), вы можете создать настраиваемый метод prepend_before_filter, который загружает ресурс для определенных действий. Пока это добавлено, этот загруженный экземпляр будет передан методу authorize_resource. load_and_authorize_resource не будет выполнять дополнительный вызов в базу данных, если экземпляр уже загружен.

class V2PostsController < ApplicationController 
    prepend_before_filter :custom_load_resource, only: [:show, :edit] 
    load_and_authorize_resource 

    def show 
    render @v2_post 
    end 

    private 

    def custom_load_resource 
    @v2_post = V2Post.find(params[:id], include: :user_updates) 
    end 

end 

Вы также можете забыть load_resource вообще, и использовать свой собственный before_filter 100% времени. Или вы можете отключить фильтры и вызвать authorize! из-за действий. В моем недавнем опыте описанный выше подход хорошо работает для контроллеров RESTful.