Cancan not loading nested resources as I expect it to
Cancan is working fine when user's are logged in. But when a user is a "guest" I would like them to be able to see some photos, but not those where the Photo's parent Post has a restriction employees_only
flag set.
Problem is if there is any photo related to an employee_only
post in the @photos
array then Cancan will throw CanCan::AccessDenied in PhotosController#index
. But shouldn't load_and_authorize_resource :photo, :through => :event
in the controller have eliminated those unauthorized records from @photos
?
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest use开发者_Python百科r (not logged in)
if user.role? :admin
can :manage, :all
elsif user.role? :moderator
can :read, :all
can :manage, Post
can :manage, Event
elsif user.role? :employee
can :read, :all
can :create, Post
can :update, Post, :user_id => user.id
can :destroy, Post, :user_id => user.id
can :update, User, :id => user.id
can :create, Photo
can :update, Photo, :id => user.id
can :destroy, Photo, :id => user.id
else
can :read, :all
cannot :read, Post, :employee_only => true
cannot :read, Photo, :post => { :employee_only => true } ## <- problem?
end
end
end
event.rb:
class Event < ActiveRecord::Base
Event has_many :posts
Event has_many :photos, :through => :posts
post.rb
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :event
has_many :photos, :dependent => :destroy
photos_controller:
class PhotosController < ApplicationController
load_and_authorize_resource :event ## <- problem?
load_and_authorize_resource :photo, :through => :event ## <- problem?
def index
# @event = Event.find(params[:event_id])
# @photos = @event.photos.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @events }
end
end
...
user.rb # not sure this is necessary to troubleshoot this issue but J.I.C.:
class User < ActiveRecord::Base
attr_protected :roles_mask
has_many :posts
has_many :photos, :through => :posts
...
First, in your ability file remove
cannot :read, Photo, :post => { :employee_only => true } ## <- problem?
I don't think you need that as you are limiting on the post.
Then in your controller change
load_and_authorize_resource :event ## <- problem?
load_and_authorize_resource :photo, :through => :event ## <- problem?
To
load_and_authorize_resource :post
load_and_authorize_resource :photo, :through => :post
I believe what you are trying to do is load the photos through the post- and because the post is limited to those with employee_only = false, you are implicitly limiting the photos. Then, in your photos controller you need to load the post so that it can be used to load and authorize the photos. What should happen in cancan (I think) is an inner join is done between posts and photos where posts.employee_only = false.
精彩评论