简体   繁体   中英

How do I define this creation permission in cancan?

I have a User , Product , and a Subscription model. Basically, a subscription is for a specific product, a product can have multiple subscriptions, and each product belongs to a user (ie, an author). Users can be administrators or regular users.

My question is: if I want to allow my regular users to create subscriptions only for products they have authored, how would I implement this using cancan?

This is what I have in my ability.rb currently.

class Ability
  include CanCan::Ability

  def initialize(user)
    if user
      if user.admin?
        can :manage, :all
      else # not an admin
        can :read, User
        can :manage, User, id: user.id
        cannot :create, User

        can :read, Product
        can :manage, Product, user: user

        can :read, Subscription
        # this is sort of what I want, but now nobody can create subscriptions
        can :create, Subscription, product: { user: user }
        can :manage, Subscription, product: { user: user }
      end
    else # not a user, just a guest
      can :create, User
      can :read, User
      can :read, Product
      can :read, Subscription
    end
  end
end

Am I going about this entirely wrong? Should I be doing this in the controller or using some sort of validation instead?

CanCan is a legitimate solution for your problem.

When you ask whether you should be doing this in the controller, the answer is that you should use your CanCan permissions inside your controller to check whether a given user is allowed to perform the requested action.

Typically you accomplish this by calling authorize_resource in your controller, but alternatively you can use authorize! :create, @subscription authorize! :create, @subscription .

Furthermore you can help your users by not providing them with links for actions that they have no permission for.

In your view you could do something like this:

<% if can? :create, @product.subscriptions.build %>
  <%= link_to new_product_subscription_path(@product) %>
<% end %>

Apart from that, there is one small issue with your ability.rb file.

can :manage, Subscription, product: { user: user }

should be

can :manage, Subscription, product: { user_id: user.id }

At least that is how it is documented on the CanCan wiki page.

this is sort of what I want, but now nobody can create subscriptions.

Did you make sure the subscription has a product_id before you attempt to authorize it?

Without a product_id your authorization for subscription fails, because it relies on it's product.

You can make sure it has a product_id by writing @product.subscriptions.build rather than Subscription.new . If you use load_and_authorize_resource, make sure you use the nested variant as shown here https://github.com/ryanb/cancan/wiki/Nested-Resources .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM