app/controllers/impersonate_controller.rb
# Controller for performing Impersonate Operation in Expertiza
class ImpersonateController < ApplicationController
include SecurityHelper
# This function checks if the logged in user is a student or not.
# If it is a student, do not allow the impersonate mode.
# If the logged in user has the role or anything other than the student,
# we allow that user to use the impersonate mode.
before_action :check_if_input_is_valid
def action_allowed?
# Check for TA privileges first since TA's also have student privileges.
if ['Student'].include? current_role_name
!session[:super_user].nil?
else
['Super-Administrator',
'Administrator',
'Instructor',
'Teaching Assistant'].include? current_role_name
end
end
# This function gives the dropdown where we have all the usernames based on the name we enter.
# We should ideally be able to search for whichever username we want to impersonate.
# This function does not seem to work
def auto_complete_for_user_name
@users = session[:user].get_available_users(params[:user][:name])
render inline: "<%= auto_complete_result @users, 'name' %>", layout: false
end
# Called whenever we want to enter the impersonate mode in the application.
def start
flash[:error] = "This page doesn't take any query string." unless request.GET.empty?
end
# This method is created to return the impersonated session
# It was created to implement the DRY Principle that was not followed in the overwrite_session method
# It sets session user as the user that is being impersonated.
# The session is then returned to the overwrite_session
def generate_session(user)
AuthController.clear_user_info(session, nil)
session[:original_user] = @original_user
session[:impersonate] = true
session[:user] = user
end
# Method to overwrite the session details that are corresponding to the user or one being impersonated
# The first 'if' statement is executed if the logged in user tried to access the impersonate feature from his account.
# The 'elsif' statement is executed if the user is impersonating someone and then tried to impersonate another person.
# The 'else' statement has not been executed and we believe it can be removed.
def overwrite_session
if params[:impersonate].nil?
user = real_user(params[:user][:name])
session[:super_user] = session[:user] if session[:super_user].nil?
generate_session(user)
elsif !params[:impersonate][:name].empty?
user = real_user(params[:impersonate][:name])
generate_session(user)
else
session[:user] = session[:super_user]
session[:super_user] = nil
end
end
# Checks if special characters are present in the username provided, only alphanumeric should be used
# warn_for_special_chars is a method in SecurityHelper class.SecurityHelper class has methods to handle this.
# special_chars method-Initialises string with special characters /\?<>|&$# .
# contains_special_chars method-converts it to regex and compares with the string
# warn_for_special_chars takes the output from above method and flashes an error if there are any special characters(/\?<>|&$#) in the string
def check_if_input_is_valid
if params[:user] && warn_for_special_chars(params[:user][:name], 'Username')
flash[:error] = 'Please enter valid user name'
redirect_back fallback_location: root_path
elsif params[:impersonate] && warn_for_special_chars(params[:impersonate][:name], 'Username')
flash[:error] = 'Please enter valid user name'
redirect_back fallback_location: root_path
end
end
# Checking if the username provided can be impersonated or not
# If the user is in anonymized view,then fetch the real user else fetch the user using params
# can_impersonate method in user.rb checks whether the original user can impersonate the other user in params
# This method checks whether the user is a superadmin or teaching staff or recursively adds the child users till it reached highest hierarchy which is SuperAdmin
# If original user can impersonate the user ,then session will be overwrite to get the view of the user who is getting impersonated
def check_if_user_impersonateable
if params[:impersonate].nil?
user = real_user(params[:user][:name])
unless @original_user.can_impersonate? user
@message = "You cannot impersonate '#{params[:user][:name]}'."
temp
AuthController.clear_user_info(session, nil)
else
overwrite_session
end
else
unless params[:impersonate][:name].empty?
overwrite_session
end
end
end
# Impersonate using form on /impersonate/start, based on the username provided
# This method looks to see if that's possible by calling the check_if_user_impersonateable method
# checking if user impersonateable, if not throw corresponding error message
def impersonate
begin
@original_user = session[:super_user] || session[:user]
if params[:impersonate].nil?
@message = "You cannot impersonate '#{params[:user][:name]}'."
@message = 'User name cannot be empty' if params[:user][:name].empty?
user = real_user(params[:user][:name])
check_if_user_impersonateable if user
elsif !params[:impersonate][:name].empty?
# Impersonate a new account
@message = "You cannot impersonate '#{params[:impersonate][:name]}'."
user = real_user(params[:impersonate][:name])
check_if_user_impersonateable if user
# Revert to original account when currently in the impersonated session
elsif !session[:super_user].nil?
AuthController.clear_user_info(session, nil)
session[:user] = session[:super_user]
user = session[:user]
session[:super_user] = nil
end
# Navigate to user's home location as the default landing page after impersonating or reverting
AuthController.set_current_role(user.role_id, session)
redirect_to action: AuthHelper.get_home_action(session[:user]),
controller: AuthHelper.get_home_controller(session[:user])
rescue StandardError
flash[:error] = @message
redirect_back fallback_location: root_path
end
end
# This method checks if the user is in anonymized view and accordingly returns the user object associated with the parameter
def real_user(name)
if User.anonymized_view?(session[:ip])
user = User.real_user_from_anonymized_name(name)
else
user = User.find_by(name: name)
end
return user
end
end