ardavis
ardavis

Reputation: 9895

Rails 3.2 CanCan - Restrict access to projects url not Owned

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

Answers (2)

clyfe
clyfe

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

VivekVarade123
VivekVarade123

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

Related Questions