Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

cancan rules creation problem #201

Closed
alec-c4 opened this Issue Nov 30, 2010 · 24 comments

Comments

Projects
None yet
3 participants

alec-c4 commented Nov 30, 2010

Hi, i have rails app that contains following models - User, Blog, Post, BlogMembership.

 class BlogMembership < ActiveRecord::Base
   belongs_to :user
   belongs_to :blog

   # Membership types:
   SUBSCRIBER = 0
   AUTHOR = 1
   MODERATOR = 2
 end

 class Blog < ActiveRecord::Base
   has_many :posts
   has_many :memberships, :class_name => "BlogMembership"

   # Blog memberships
   def subscribers
     self.memberships.where(:membership_type => [BlogMembership::SUBSCRIBER, BlogMembership::AUTHOR, BlogMembership::MODERATOR]).collect(&:user)
   end

   def authors
     self.memberships.where(:membership_type => [BlogMembership::AUTHOR, BlogMembership::MODERATOR]).collect(&:user)
   end

   def moderators
     self.memberships.where(:membership_type =>  BlogMembership::MODERATOR).collect(&:user)
   end

end
In Ability class (because i use cancan for access restriction) i try to limit access of users and moderators to the blogs, but with following rule

 if user.is? :moderator
   can :manage, Post do |post|
     post.blog.moderators.include? user
   end
 end

all users can send Posts to the any blog.

Could you tell me please - how to properly configure rule in Ability class for following relations scheme?

Owner

ryanb commented Dec 3, 2010

It looks like you're doing it correctly. Is this the only can :manage, Post line in your Ability file? Perhaps there is another one which is allowing all users to manage posts.

alec-c4 commented Dec 3, 2010

Nothing allows :( plz habe a look at my routes - http://pastie.org/1337785 , maybe there two "resources :posts" causes my problem?

Owner

ryanb commented Dec 3, 2010

If you want to manage posts when it's not nested under the blog you can do :shallow => true option.

load_and_authorize_resource :post, :through => :blog, :shallow => true

However I don't think that's your problem here. The best thing to do is try it in the console or in tests.

user = User.first # fetch some user
post = Post.first # some post
ability = Ability.new(user)
ability.can? :edit, post

See what the can? call returns and make sure it has the behavior you expect. If it doesn't, tell me what it is returning and what you are expecting.

alec-c4 commented Dec 8, 2010

Thanks for idea with shallow_routes, but the problem still exists. Main idea is to manage permissions for posts depending on user's membership in blog. If user is moderator and has BlogMembership s moderator it means that user must have all abilities for post creation/management in this blog, but if it is a regular user - only view permissions.

unfortunately rules like

     if user.is? :moderator
       can :manage, [Blog, Post] do |blog, post|
         Blog.find(blog).moderators.include? user
       end
     end

not working :(

Owner

ryanb commented Dec 8, 2010

Did you try experimenting with it in the Rails console like I showed above? I think I need to see a specific case of it not working in order to debug it further. Please paste the entire console session here of it not working.

alec-c4 commented Dec 8, 2010

ok - there are some pasties
http://pastie.org/1359654 <-- some data from db
http://pastie.org/1359666 <-- Posts and Blogs controllers

case 1 - http://pastie.org/1359730
case 2 - http://pastie.org/1359758

Owner

ryanb commented Dec 9, 2010

Thanks for posting those pasties.

Rules like this won't work.

     if user.is? :moderator
       can :manage, [Blog, Post] do |blog, post|
         Blog.find(blog).moderators.include? user
       end
     end

Because if you pass an array to can it will match either a post or blog and pass that single object into the block. There is no second argument on that block.

What you originally had should be correct. You can add the blogs to that as well but it must be done separately.

 if user.is? :moderator
   can :manage, Post do |post|
     post.blog.moderators.include? user
   end
   can :manage, Blog do |blog|
     blog.moderators.include? user
   end
 end

Let me know if that doesn't work.

alec-c4 commented Dec 17, 2010

Doesn't work :( With your configuration moderator have access to they blog, but not to others (to anything). It's so strange because i have following lines on the bottom of config

     can [:index, :list, :show, :feed], Blog
     can [:index, :show, :tag, :feed], Post

alec-c4 commented Dec 20, 2010

any idea?

Owner

ryanb commented Dec 20, 2010

What is the can? call you are using to determine permissions? Are you doing this?

can? :manage, @post

Normally :manage is not used in a can? call because you should be checking on a specific controller action.

can? :show, @post

Try that and see if it gets the behavior you want.

alec-c4 commented Dec 20, 2010

for the last configuration i have attempted to access posts#index page (without any "can?") for the blog without moderator permissions and saw "Access denied" page. But on attempt to access blog with moderator permissions - everything work good.

as i have written - it's so strange because i have
can [:index, :list, :show, :feed], Blog
can [:index, :show, :tag, :feed], Post
at bottom :(

Owner

ryanb commented Dec 20, 2010

Does it work when you do this in the console?

user = User.first # some user
ability = Ability.new(user)
ability.can? :index, Post

That should return true if you have those rules at the bottom. If not then this is a bug in CanCan.

alec-c4 commented Dec 20, 2010

it returns true, but (i have checked once again) - on attempt to visit blog without moderators rights - still access denied

Owner

ryanb commented Dec 20, 2010

Which action of which controller specifically are you visiting? Sorry if you've said before, but I'm just trying to figure out why it's behaving differently in the console.

alec-c4 commented Dec 20, 2010

ok :)
in both cases i'm visiting the same action - index of posts_controller.

Owner

ryanb commented Dec 21, 2010

Try adding the :read action to the list of Blog actions. You won't need the index/show actions with :read since they are aliased.

can [:list, :read, :feed], Blog

The reason you need this is that posts are nested under Blog and CanCan checks there there is :read access to the parent blog. I should probably change this to :show action now that I think about it.

alec-c4 commented Dec 23, 2010

Hi,
much better, but there are some problems still exists.
For now - any user can see list of posts in any blog (correct), on attempt to create new post for moderated by this user blog post created (correct) and in not moderated - acess denied exception (correct). But for both blogs - "if can? :create, Post" returns true and show content inside if-block (wrong) :(

alec-c4 commented Dec 26, 2010

Of course - i can add validation "is User in moderators list", but could you check - maybe there are any possible way to use only "if can? :create, Post"? Maybe we can use something like "if can? :create, Post, @blog"?

Owner

ryanb commented Dec 28, 2010

You can represent nesting with can? :create, @blog => Post, does that work for you?

alec-c4 commented Dec 28, 2010

the same result :( protected link to create new post still shown but on click - access denied

Owner

ryanb commented Mar 9, 2011

Closing this because it is an old issue. I'm sorry your problem was never resolved, I'm not sure what the issue could have been.

alec-c4 commented Mar 9, 2011

ok. i have solved this issue with migration to declarative_authorization :)

Hi, i've got the same issue.

I have a user, that has many clubs, and the user is a member of each club, through member model.

When a user is moderator of club, he could manage everything.

In abilities.rb:

# Category abilities with issue
can :manage, Category do |category|
  user.moderator_of? category.club
end

but even who is not moderator can :create categories...

then i tried this:

# Category abilities still with issue
can :manage, Category do |category|
  user.moderator_of? category.club
end
cannot :create, Category do |category|
  !user.moderator_of? category.club
end

but now even the moderators can't create categories.

it happend before in my Page abilities, like this:

# Page  abilities with the same issue fixed
can :read, Page
can :manage, Page do |page|
  user.moderator_of? page.club
end
cannot :create, Page do |page|
  !user.moderator_of? page.club
end

but the cannot method fixed the issue of Page, the same issue of Category, unhappily i couldn't fix Category the same way.

Hey, I fixed my issue. Described in issue #455

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment