Project

General

Profile

Download (10.3 KB) Statistics
| Branch: | Tag: | Revision:
require 'foreman/controller/auto_complete_search'

class ApplicationController < ActionController::Base
protect_from_forgery # See ActionController::RequestForgeryProtection for details
rescue_from ScopedSearch::QueryNotSupported, :with => :invalid_search_query
rescue_from Exception, :with => :generic_exception if Rails.env.production?
rescue_from ActiveRecord::RecordNotFound, :with => :not_found

# standard layout to all controllers
helper 'layout'

before_filter :require_ssl, :require_login
before_filter :session_expiry, :update_activity_time, :unless => proc {|c| c.remote_user_provided? || c.api_request? } if SETTINGS[:login]
before_filter :set_taxonomy, :require_mail
before_filter :welcome, :only => :index, :unless => :api_request?
before_filter :authorize


cache_sweeper :topbar_sweeper, :unless => :api_request?

def welcome
@searchbar = true
klass = controller_name == "dashboard" ? "Host" : controller_name.camelize.singularize
if (klass.constantize.first.nil? rescue false)
@searchbar = false
render :welcome rescue nil and return
end
rescue
not_found
end

protected

# Authorize the user for the requested action
def authorize(ctrl = params[:controller], action = params[:action])
return true if request.xhr?
allowed = User.current.allowed_to?({:controller => ctrl.gsub(/::/, "_").underscore, :action => action})
allowed ? true : deny_access
end

def deny_access
User.current.logged? ? render_403 : require_login
end

def require_ssl
# if SSL is not configured, don't bother forcing it.
return true unless SETTINGS[:require_ssl]
# don't force SSL on localhost
return true if request.host=~/localhost|127.0.0.1/
# finally - redirect
redirect_to :protocol => 'https' and return if request.protocol != 'https' and not request.ssl?
end


# Force a user to login if authentication is enabled
# Sets User.current to the logged in user, or to admin if logins are not used
def require_login
unless session[:user] and (User.current = User.unscoped.find(session[:user]))
# User is not found or first login
if SETTINGS[:login]
# authentication is enabled

# If REMOTE_USER is provided by the web server then
# authenticate the user without using password.
if remote_user_provided?
user = User.unscoped.find_by_login(@remote_user)
logger.warn("Failed REMOTE_USER authentication from #{request.remote_ip}") unless user
# Else, fall back to the standard authentication mechanism,
# only if it's an API request.
elsif api_request?
user = authenticate_or_request_with_http_basic { |u, p| User.try_to_login(u, p) }
logger.warn("Failed Basic Auth authentication request from #{request.remote_ip}") unless user
end

if user.is_a?(User)
logger.info("Authorized user #{user.login}(#{user.to_label})")
User.current = user
session[:user] = User.current.id unless api_request?
return !User.current.nil?
end

unless api_request?
session[:original_uri] = request.fullpath # keep the old request uri that we can redirect later on
redirect_to login_users_path and return
end
else
# We assume we always have a user logged in, if authentication is disabled, the user is the build-in admin account.
User.current = User.admin
session[:user] = User.current.id unless api_request?
end
end
end

def require_mail
if User.current && User.current.mail.blank?
notice "Mail is Required"
redirect_to edit_user_path(:id => User.current)
end
end

# this method is returns the active user which gets used to populate the audits table
def current_user
User.current
end

def invalid_request
render :text => 'Invalid query', :status => 400
end

def not_found(exception = nil)
logger.debug "not found: #{exception}" if exception
respond_to do |format|
format.html { render "common/404", :status => 404 }
format.json { head :status => 404}
format.yaml { head :status => 404}
format.yml { head :status => 404}
end
true
end

def api_request?
request.format.json? or request.format.yaml?
end

# this method sets the Current user to be the Admin
# its required for actions which are not authenticated by default
# such as unattended notifications coming from an OS, or fact and reports creations
def set_admin_user
User.current = User.admin
end

# searches for an object based on its name and assign it to an instance variable
# required for models which implement the to_param method
#
# example:
# @host = Host.find_by_name params[:id]
def find_by_name
not_found and return if (id = params[:id]).blank?

obj = controller_name.singularize
# determine if we are searching for a numerical id or plain name
cond = "find_by_" + ((id =~ /^\d+$/ && (id=id.to_i)) ? "id" : "name")
not_found and return unless eval("@#{obj} = #{obj.camelize}.#{cond}(id)")
end

def notice notice
flash[:notice] = notice
end

def error error
flash[:error] = error
end

def warning warning
flash[:warning] = warning
end

# this method is used with nested resources, where obj_id is passed into the parameters hash.
# it automatically updates the search text box with the relevant relationship
# e.g. /hosts/fqdn/reports # would add host = fqdn to the search bar
def setup_search_options
params[:search] ||= ""
params.keys.each do |param|
if param =~ /(\w+)_id$/
unless params[param].blank?
query = "#{$1} = #{params[param]}"
params[:search] += query unless params[:search].include? query
end
end
end
end

def session_expiry
if session[:expires_at].blank? or (session[:expires_at].utc - Time.now.utc).to_i < 0
expire_session
session[:original_uri] = request.fullpath # keep the old request uri that we can redirect later on
end
rescue => e
logger.warn "failed to determine if user sessions needs to be expired, expiring anyway: #{e}"
expire_session
end

def update_activity_time
session[:expires_at] = Setting[:idle_timeout].minutes.from_now.utc
end

def expire_session
logger.info "Session for #{current_user} is expired."
reset_session
flash[:warning] = "Your session has expired, please login again"
redirect_to login_users_path
end

def ajax?
request.xhr?
end

def ajax_request
return head(:method_not_allowed) unless ajax?
end

def remote_user_provided?
return false unless Setting["authorize_login_delegation"]
return false if api_request? and not Setting["authorize_login_delegation_api"]
(@remote_user = request.env["REMOTE_USER"]).present?
end

private
def detect_notices
@notices = current_user.notices
end

def require_admin
unless User.current.admin?
render_403
return false
end
true
end

def render_403
respond_to do |format|
format.html { render :template => "common/403", :layout => !request.xhr?, :status => 403 }
format.atom { head 403 }
format.yaml { head 403 }
format.yml { head 403 }
format.xml { head 403 }
format.json { head 403 }
end
false
end

def process_success hash = {}
hash[:object] ||= eval("@#{controller_name.singularize}")
hash[:object_name] ||= hash[:object].to_s
hash[:success_msg] ||= "Successfully #{action_name.pluralize.sub(/es$/,"ed").sub(/ys$/, "yed")} #{hash[:object_name]}."
hash[:success_redirect] ||= eval("#{controller_name}_url")
hash[:json_code] = :created if action_name == "create"

return render :json => {:redirect => hash[:success_redirect]} if hash[:redirect_xhr]

respond_to do |format|
format.html do
notice hash[:success_msg]
redirect_to hash[:success_redirect] and return
end
format.json { render :json => hash[:object], :status => hash[:json_code]}
end
end

def process_error hash = {}
hash[:object] ||= eval("@#{controller_name.singularize}")

case action_name
when "create" then hash[:render] ||= "new"
when "update" then hash[:render] ||= "edit"
else
hash[:redirect] ||= eval("#{controller_name}_url")
end

hash[:json_code] ||= :unprocessable_entity
logger.info "Failed to save: #{hash[:object].errors.full_messages.join(", ")}" if hash[:object].respond_to?(:errors)
hash[:error_msg] ||= [hash[:object].errors[:base] + hash[:object].errors[:conflict].map{|e| "Conflict - #{e}"}].flatten
hash[:error_msg] = [hash[:error_msg]].flatten
respond_to do |format|
format.html do
hash[:error_msg] = hash[:error_msg].join("<br/>")
if hash[:render]
flash.now[:error] = hash[:error_msg] unless hash[:error_msg].empty?
render :action => hash[:render]
return
elsif hash[:redirect]
error(hash[:error_msg]) unless hash[:error_msg].empty?
redirect_to hash[:redirect]
return
end
end
format.json { render :json => {"errors" => hash[:object].errors.full_messages} , :status => hash[:json_code]}
end
end

def redirect_back_or_to url
redirect_to request.referer.empty? ? url : :back
end

def generic_exception(exception)
logger.warn "Operation FAILED: #{exception}"
logger.debug exception.backtrace.join("\n")
render :template => "common/500", :layout => !request.xhr?, :status => 500, :locals => { :exception => exception}
end

def set_taxonomy
return if User.current.nil?

if SETTINGS[:organizations_enabled]
orgs = Organization.my_organizations
Organization.current = if orgs.count == 1
orgs.first
elsif session[:org_id]
orgs.find(session[:org_id])
else
nil
end
end

if SETTINGS[:locations_enabled]
locations = Location.my_locations
Location.current = if locations.count == 1
locations.first
elsif session[:location_id]
locations.find(session[:location_id])
else
nil
end
end
end

end
(1-1/41)