This repository has been archived by the owner on Jun 27, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Implementing a Superuser scope with Devise and Warden
dchandekstark edited this page Oct 18, 2014
·
4 revisions
- Users authorized to "act as superuser" should not be signed into
:superuser
scope by default. Conversely, signing out of:user
scope should sign out of:superuser
scope (Devise default is to sign out of all scopes when signing out of default scope.) - There are no scoped views.
- Signing in/out of
:superuser
scope should be a simple toggling. - There is no explicit re-authentication because the user is always required to sign into
:user
scope (via remote authentication)
# config block in config/initializers/devise.rb
# These settings may be commented out b/c defaults (don't have to uncomment)
config.scoped_views = false
config.default_scope = :user
config.sign_out_all_scopes = true
# This is the important part!
config.warden do |manager|
# The signed-in superuser has to be serialized/deserialized
# into/from session to persist across requests.
# This example assumes that your regular user model is `User`.
manager.serialize_into_session(:superuser) { |superuser| superuser.id }
manager.serialize_from_session(:superuser) { |id| User.find(id) }
end
You have to implement some mean of determining whether the user logged into default scope (current_user
) is authorized to act as superuser. In my case, the user has be a member of a certain group. Another way is to add a boolean column to your User model to authorize superuser ability.
# app/models/user.rb
def authorized_to_act_as_superuser?
# Your business logic here
end
I decided to have a special SuperuserController
, but you could implement the functionality in ApplicationController
.
Route
# config/routes.rb
get 'superuser' => 'superuser#toggle'
Controller
class SuperuserController < ApplicationController
def toggle
if acting_as_superuser?
# `acting_as_superuser?` will be defined in ApplicationController.
# As you'll see, we could have simply used `signed_in?(:superuser)`
# but this method isolat
sign_out(:superuser) # Devise method for signing out of a scope
flash[:success] = "You are no longer acting as Superuser."
else
authorize_to_act_as_superuser! # See protected method below
sign_in(:superuser, current_user) # Devise signs current_user into :superuser scope
flash[:alert] = "<strong>Caution!</strong> You are now acting as Superuser.".html_safe
end
redirect_to root_path # Example: redirect to root path after toggling
end
protected
def authorize_to_act_as_superuser!
unless current_user.authorized_to_act_as_superuser?
render nothing: true, status: 403 # Substitute your preferred "unauthorized" handling
end
end
end