Reputation: 9895
I'm trying to restrict access to Projects that a user did not create. This seems to be working fine with:
if user.has_role?(:Student)
can :create, Project
can :manage, Project, :user_id => user.id
end
(Side Question: Is there a better way to write that? ^^)
However, I can still access the URL: /users/5/projects
I just can't see the projects as expected. I'd rather it tell me that I cannot access the page, and redirect. I do have this in my application controller:
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
But I don't receive a redirection or error message. Do I need to add something else to the abilities to make that work?
I do have load_and_authorize_resource
in both the ProjectsController and UsersController.
For the record, my routes look like this:
resources :users do
resources :projects
end
Upvotes: 1
Views: 1661
Reputation: 23770
If you want to enable the redirect behavior if the user cannot read any project in the current collection, override the index action and add extra enforcement:
def index
# @projects is loaded by the CanCan before filter load_and_authorize_resource
unless @projects.any?{|project| can?(:read, project)}
raise CanCanAccessDenied.new("no project readable there", :read, Project)
end
end
In index-like (collection) controller actions, CanCan enforces ACL via authorize :read, ModelClass
.
https://github.com/ryanb/cancan/wiki/Checking-Abilities see "Checking with Class" section.
As you can read, if there is the possibility that the user to :read any of the ModelClass instances (even if these instances do not yet exist) the query authorize :action, ModelClass
will authorize.
Given your URL /users/5/projects
and routes resources :users do resources :projects end
I belive this action is an index on projects for a specific user. So the CanCan index action will authorize, given can :manage, Project, :user_id => user.id
, so there can exist projects the user can :read as such => authorize. Later on in the view I belive you authorize each specific project instance can? :read, project
, and there is where they get filtered, as such the page remains empty.
Upvotes: 0
Reputation: 3692
Try this one
if user.has_role?(:Student)
can :create, Project
can :manage, Project do |P|
user && P.user == user
end
It will check whether current user owns the project or not. If he doesn't own the project then he won't be able to modify it.
First condition is take just to check whether user
object exist or not, you can also use exception handler there. Here's an example of that:
comment.try(:user) == user
Upvotes: 1