title: Rails 3.2 & Devise: custom authenticate_user! that authenticates Users and Admins
body: <p>I am using devise with two separate models for User and Admin. I wanted to replace authenticate_user! with my own function, auth_user! such that an Admin's permissions is a superset of the User's permissions. I also wrote a function, actions_permitted, that makes it easier to call skip_before_filter. My added code in ApplicationController.rb is below. For example, I use it in a controller by writing: actions_permitted :public => [:show], user: [:new, :create].</p>
  
  <p>However, the code is not functioning as expected: some actions aren't properly authenticated, and others require an admin to also sign in as a user when an admin should always have user abilities. After some googling, I suspect that the issue may be that when the inherited models call actions_permitted, it happens on the ApplicationController level rather than in a particular model. I also found that many on Stackoverflow recommended CanCan, although I'd prefer to stick with the simple syntax of actions_permitted if you can help me get it working!</p>
  
  <pre><code># app/controllers/application_controller.rb
  #
  # call with :user and :public defined as either :all or an array
  # of symbols that represent methods. Admins can do everything that users
  # can (by definition of auth_user!).
  def self.actions_permitted(hash)
    # first process exceptions to user authentication
    if hash[:public] == :all
      # skip all filters and return
      skip_before_filter :auth_user!
      skip_before_filter :authenticate_admin!
      return
    elsif hash[:public].kind_of?(Array)
      # skip user authentication for methods in :public array
      skip_before_filter :auth_user!, only: hash[:public]
    end
  
    # then process exceptions to admin authentication
    if hash[:user] == :all
      # users can do everything, so skip all admin authenticatoin
      skip_before_filter :authenticate_admin!
  
    elsif hash[:user].kind_of?(Array)
      if hash[:public].kind_of?(Array)
        # Join the two arrays and skip admin authentication as not to filter
        # actions allowed by the public or by users
        skip_before_filter :authenticate_admin!, only: (hash[:user] | hash[:public])
      else
        # otherwise, simply skip admin authentication for actions allowed by users
        skip_before_filter :authenticate_admin!, only: hash[:user]
      end
  
    elsif hash[:public].kind_of?(Array)
      # skip admin authentication for actions allowed by the public
      skip_before_filter :authenticate_admin!, only: hash[:public]
    end
  
  end
  
  # checks if user OR admin is authenticated.
  def auth_user!(opts = {})
    # return (authenticate_user! || authenticate_admin!)
    return (env['warden'].authenticated?(:user) ||
            env['warden'].authenticated?(:admin))
  end
  </code></pre>