9

I'd like to put my app into maintenance mode but still have admins / moderators be able to log in and use the site.

Two reasons:

  1. I'm making some changes within the app that are best applied using the in-app interface rather than the console.

  2. Moderators don't have access to the console, but can definitely help with the maintenance tasks we have ahead of us.

How would you recommend this be done? I have been experimenting with setting an environment variable ADMIN_MODE and changing all the permissions when it is true, but that seems pretty cludgy and slow.

I'm using CanCan and Devise, for what it's worth, but I'm definitely open to any suggestions.

Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
Andrew
  • 42,517
  • 51
  • 181
  • 281

3 Answers3

11

This would probably be a fairly simple solution:

class ApplicationController < ActionController::Base
  before_filter :check_admin_mode

  protected

  def check_admin_mode
    if ENV['ADMIN_MODE'] && controller_name != 'sessions' && !current_user.admin?
      redirect_to '/maintenance.html'
    end
  end
end
aNoble
  • 7,033
  • 2
  • 37
  • 33
  • This looks good -- only problem I've got is I do still need to be able to let moderators / admins log in in case their session is expired when maintenance mode is enabled. It seems like this is preventing anyone not already logged in from successfully logging in. Any suggestions for how to keep just the login action open? – Andrew Jul 13 '11 at 13:27
  • I've updated the code with a check to exclude the Sessions controller which should be correct if you're using Devise. – aNoble Jul 13 '11 at 15:58
  • Ok, this works. The only thing missing is you have to check if `current_user` exists or else the check if a current user is admin will fail when current_user is nil. But this works, and is much faster than what I had going using CanCan alone. Thanks!! – Andrew Jul 13 '11 at 16:58
3

I think aNoble's solution is fine, another way might be to get your webserver to do this, I use Capistrano's cap deploy:web:disable task and then mod_rewrite to conditionally redirect either to the maintenance page or allow specific users through by IP address, but you may be able to write your own conditions.

# Redirect to system maintenance if exists - used by cap deploy:web:disable
RewriteCond %{REQUEST_URI} !\.(css|jpg|png|gif)$
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.php -f 
# Allow me through
RewriteCond %{REMOTE_ADDR} "!^XXX\.XXX\.XXX\.XXX"
RewriteCond %{SCRIPT_FILENAME} !maintenance.php [NC]
RewriteRule ^.*$ /system/maintenance.php [L]
Paul Groves
  • 3,983
  • 2
  • 23
  • 24
  • This is a good idea, thanks Paul. I'm on Heroku so I don't have mod_rewrite capability, but this is a good technique to keep in mind for other deployments in the future. – Andrew Jul 13 '11 at 16:46
0

I did something similar which might be useful to people who are still interested

class ApplicationController < ActionController::Base
  before_filter :check_maintenance_mode

  protected

  def check_maintenance_mode

    temp_var = self.class.to_s.split("::").first

    return if temp_var.casecmp("admin") == 0 || temp_var.casecmp("activeadmin") == 0

    if site_setting.maintenance_mode
      redirect_to maintenance_path unless request.fullpath.include?(maintenance_path)
    else
      redirect_to root_path if request.fullpath.include?(maintenance_path)
    end

  end

end

First, what I did is to split the class name to get the module name or controller name that I am accessing which I will exit from the method if I am entering the admin zone. You do not want the maintenance page to affect the admin module

Second, I check for maintenance mode and if its true, I will redirect the users to maintenance page UNLESS they are already on the page itself. If maintenance mode is not on, users will be redirected back to root_path

Fyi, I am using activeadmin as my admin page. Hope this helps someone in 2015.

Cedric Loy
  • 61
  • 1
  • 7