Pundit with Rails plus User, Admin and Roles Model

2019-05-20 09:03发布

问题:

Following on from Rails_admin: Should I have admin_user or user with admin role to manage users and admin panel I'm wanting to adopt Pundit for its policy elegance for an application. The application has both a User model and an Admin model - one for customers, the other for staff. It is also multi-tenanted, though that should not impact the problem terribly.

I'd also like to have a separate Role model, allowing customers to mix-and-match their own "title" for a Role as they need. This again shouldn't be terribly difficult in implementation.

The hard part is the support for the Pundit Policies to support two different user models - the User (Customer) and Admin (Staff).

Is it a case that I should be using the pundit_user method to set either the Admin or User as the pundit_user (based on the availability of these through current_user and current_admin_user) or is there another method. I haven't found much good documentation on this use case (other than the short line on github).

def pundit_user
  if !current_admin_user.nil?
    current_admin_user
  elsif !current_user.nil?
    current_user
  else
    nil
  end        
end

回答1:

In the publicly accesible part of my application, the User model is used. The default Pundit configuration works since pundit_user returns current_user.

In the admin part of my application, the Administrator model is used. One reason for this is that an admin can stay logged in while impersonating a user (to see what they see in their profile and help troubleshoot).

In admin controllers pundit_user returns current_administrator.

In Rails Admin, the current user is set to the current administrator:

config.authenticate_with do
  warden.authenticate! :scope => :administrator
end
config.current_user_method(&:current_administrator)

While I don't use authorization in Rails Admin(all admins have all powers), you should be able to use the rails_admin_pundit gem since it does

@controller.class.send(:alias_method, :pundit_user, :_current_user)

which is defined in Rails Admin as

def _current_user
  instance_eval(&RailsAdmin::Config.current_user_method)
end