简体   繁体   中英

Accessing main app's CanCan rules from within Rails 3.1 engine

I am trying to use a Forem gem which happens to utilise CanCan authorisation framework as well as my main application. Both the main application and Rails Engine have their own ability.rb files.

The problem happens in the layout, when I am trying to do some authorisation checks:

    <% if can? :update, User %>
        <%= link_to_current_user :content_method => :login %>.
    <% else %>

When I am utilising the layout file on the engine it consults it's own ability.rb file for authorisation. Naturally, there are no rules from my main application so authorisation fails when it should not. Is there any way for me to force it to go to the "main" CanCan?

Thanks.

I think the easiest solution is going to be to monkey-patch forem's definition to add your own declarations:

class Forem::Ability
  alias_method :orig_init, :initialize
  def initialize(user)
    orig_init(user)

    # Put your own authorization code here.
  end
end

class Ability < Forem::Ability; end

When in the context of the engine the can? method must be using the engine's controller/namespace to authorize actions ( Forem::Ability ), when in your own application's context it is using your own controller and no namespace to do the same.

Therefore, I think this solution here (which will add all authorization actions to both Ability and Forem::Ability should solve your problem.

UPDATE: I realize now that the engine's controller's current_ability method probably reads something like:

def current_ability
  @current_ability ||= Forem::Ability.new(current_user)
end

And yours (defaulted from the cancan gem) reads something like:

def current_ability
  @current_ability ||= Ability.new(current_user)
end

So my solution above should fix your problem, but this is likely the specific issue that it's having.

The only way I found so far is to combine both files into a single, separate it into module and monkey patch both abilities on startup. Not pretty..

I'm still a beginner in ruby but I hope help you with the following.

Update

Another issue to try, as said on cancan/wiki/admin-namespace , is to choose which ability file to load for your models.

Create your own model :

# in models/admin_ability.rb

class AdminAbility
  include CanCan::Ability

  def initialize(user)
    # define admin abilities here ....
  end
end

Then, use it for your model

def current_ability
   @current_ability ||= AdminAbility.new(current_user)
end

I hope this solution answered to your problem.

Steph

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