Authorizing non-logged-in user behavior in rails w

2019-07-21 00:37发布

问题:

Post: hidden: boolean

I want the logged in user could see all the posts, and the non-logged-in user only have access to posts whose hidden fields are false. So I write like this in cancan's Ability Model:

if user_signed_in?
    can :read, Post
else 
    can :read, Post, :hidden => false
end

but accessing the helper user_signed_in is not allowed in Model. As stated in this question: Rails 3 devise, current_user is not accessible in a Model ?. While we could using some tricks to access the helper, its not proper to do that

So, how could I authorize the not-logged-in user properly? Or just use "Include" to use this helper ??

Or should I put this in authentication part? but how?

回答1:

All you need to do is this:

def initialize(user)
  user ||= User.new # guest user (not logged in)

  can :read, Post, :hidden => false

  if User.exists?(user)
    can :read, Post
  end
end

With devise, the current_user helper method returns the current user when logged in but returns nil when not logged in. It is available in the controllers and views. By default, CanCan does all authorization checks against the return of the current_user method.

Now whenever the can? method is called from a view or a controller, the return of current_user will be passed to a new instance of Ability as the local variable user.

To check if the user was logged in, I choose to useUser.exists?(). It's a class method for ActiveRecord::Base that will check if that user object is persisted in the database. Any other way will work just as well though. For instance, this would work just as well or better:

if user.encrypted_password
  can :read, Post
end

This will check if the default devise password field exists for the user instance. If you haven't done anything too crazy, this will only return a value if the user is logged in. If the second option works for your situation, it may be superior because you won't even have to query the database.

Semi-relevant tip, check out a role handling gem like Rolify. It is great when used in conjunction with CanCan.