Skip to content

Instantly share code, notes, and snippets.

@sosolidkk
Last active November 17, 2023 20:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sosolidkk/a1665e0a924a663e7e045ac95b5af662 to your computer and use it in GitHub Desktop.
Save sosolidkk/a1665e0a924a663e7e045ac95b5af662 to your computer and use it in GitHub Desktop.
Devise Middleware Backdoor
module Middlewares
# Middleware which allows signing in by passing as=USER_ID in a query
# parameter.
#
# Designed to eliminate time in integration tests wasted by visiting and
# submitting the sign in form.
#
# This code snippet is heavily inspired by and based on the Toughtbot Clearance gem Backdoor
# For more details, see the source code here:
# https://github.com/thoughtbot/clearance/blob/main/lib/clearance/back_door.rb
#
# @example Usage in Rails application:
# In config/application.rb or an initializer
# Rails.application.config.middleware.use Middlewares::Backdoor
#
# @example Usage URL with query parameter to sign in as a specific user:
# http://localhost:3000/some_path?as=123
#
class Backdoor
# @see https://stackoverflow.com/a/44747266
include Warden::Test::Helpers
# Initialize the Backdoor Middleware
#
# @param [Object] app ActionDispatch::Routing::RouteSet
# The application to call.
#
def initialize(app, &block)
raise error_message unless allowed?
@app = app
@block = block
end
# Calls the Middleware operation
#
# @param [Hash] env The Rack environment keys and values.
#
def call(env)
run(env)
@app.call(env)
end
private
# Run the Backdoor middleware.
#
# @param [Hash] env The Rack environment keys and values.
#
# @return [void]
#
def run(env)
params = Rack::Utils.parse_query(env['QUERY_STRING'])
user_param = params.fetch('as')
return if user_param.blank?
user = User.find_by(id: user_param)
return if user.blank?
login_as(user, scope: :user)
Rails.logger.info("Backdoor: Signed in as User #{user.username} [id: #{user.id}]")
end
# Check if the Backdoor is allowed in the current environment.
#
# @return [Boolean] true if allowed, false otherwise.
#
def allowed?
allowed_environments.include?(Rails.env)
end
# List of environments where the Backdoor is allowed.
#
# @return [Array<String>] List of allowed environments.
#
def allowed_environments
%w[staging development]
end
# Error message when Backdoor is not allowed in the current environment.
#
# @return [String] The error message.
#
def error_message
<<-MSG.squish
Can't use auth backdoor outside of
configured environments (#{allowed_environments.join(', ')}).
MSG
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment