Newer
Older
dmpopidor / app / controllers / application_controller.rb
# frozen_string_literal: true

class ApplicationController < ActionController::Base

  include Dmpopidor::Controllers::Application
  # Set Static Pages to use in navigation
  before_filter :set_nav_static_pages

  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

  # Look for template overrides before rendering
  before_filter :prepend_view_paths

  before_filter :set_gettext_locale

  after_filter :store_location

  include GlobalHelpers
  include Pundit
  helper_method GlobalHelpers.instance_methods

  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  # When we are in production reroute Record Not Found errors to the branded 404 page
  if Rails.env.production?
    rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
  end

  private

  def current_org
    current_user.org
  end

  def user_not_authorized
    if user_signed_in?
      redirect_to plans_url, alert: _("You are not authorized to perform this action.")
    else
      redirect_to root_url, alert: _("You need to sign in or sign up before continuing.")
    end
  end

  # Sets FastGettext locale for every request made
  def set_gettext_locale
    FastGettext.locale = LocaleFormatter.new(current_locale, format: :fast_gettext).to_s
  end

  def current_locale
    session[:locale] || FastGettext.default_locale
  end

  def store_location
    # store last url - this is needed for post-login redirect to whatever the user last
    # visited.
    unless ["/users/sign_in",
            "/users/sign_up",
            "/users/password",
            "/users/invitation/accept",
           ].any? { |ur| request.fullpath.include?(ur) } \
    or request.xhr? # don't store ajax calls
      session[:previous_url] = request.fullpath
    end
  end

  def after_sign_in_path_for(resource)
    referer_path = URI(request.referer).path unless request.referer.nil? or nil
    if from_external_domain? || referer_path.eql?(new_user_session_path) ||
         referer_path.eql?(new_user_registration_path) ||
         referer_path.nil?
      root_path
    else
      request.referer
    end
  end

  def after_sign_up_path_for(resource)
    referer_path = URI(request.referer).path unless request.referer.nil?
    if from_external_domain? ||
         referer_path.eql?(new_user_session_path) ||
         referer_path.nil?
      root_path
    else
      request.referer
    end
  end

  def after_sign_in_error_path_for(resource)
    (from_external_domain? ? root_path : request.referer || root_path)
  end

  def after_sign_up_error_path_for(resource)
    (from_external_domain? ? root_path : request.referer || root_path)
  end

  def authenticate_admin!
    # currently if admin has any super-admin task, they can view the super-admin
    unless user_signed_in? && (current_user.can_add_orgs? ||
                               current_user.can_change_org? ||
                               current_user.can_super_admin?)
      redirect_to root_path
    end
  end

  def failure_message(obj, action = "save")
    _("Unable to %{action} the %{object}.%{errors}") % {
      object: obj_name_for_display(obj),
      action: action || "save",
      errors: errors_for_display(obj),
    }
  end

  def success_message(obj, action = "saved")
    _("Successfully %{action} the %{object}.") % {
      object: obj_name_for_display(obj),
      action: action || "save",
    }
  end

  def errors_for_display(obj)
    if obj.present? && obj.errors.any?
      msgs = obj.errors.full_messages.uniq.collect { |msg| "<li>#{msg}</li>" }
      "<ul>#{msgs.join('')}</li></ul>"
    end
  end

  def obj_name_for_display(obj)
    display_name = {
      ExportedPlan: _("plan"),
      GuidanceGroup: _("guidance group"),
      Note: _("comment"),
      Org: _("organisation"),
      Perm: _("permission"),
      Pref: _("preferences"),
      User: obj == current_user ? _("profile") : _("user")
    }
    if obj.respond_to?(:customization_of) && obj.send(:customization_of).present?
      display_name[:Template] = "customization"
    end
    display_name[obj.class.name.to_sym] || obj.class.name.downcase || "record"
  end

  # Override rails default render action to look for a branded version of a
  # template instead of using the default one. If no override exists, the
  # default version in ./app/views/[:controller]/[:action] will be used
  #
  # The path in the app/views/branded/ directory must match the the file it is
  # replacing. For example:
  #  app/views/branded/layouts/_header.html.erb -> app/views/layouts/_header.html.erb
  def prepend_view_paths
    prepend_view_path "app/views/branded"
  end

  ##
  # Sign out of Shibboleth SP local session too.
  # -------------------------------------------------------------
  def after_sign_out_path_for(resource_or_scope)
    if Rails.application.config.shibboleth_enabled
      return Rails.application.config.shibboleth_logout_url + root_url
      super
    else
      super
    end
  end
  # -------------------------------------------------------------

  def from_external_domain?
    if request.referer.present?
      referer = URI.parse(request.referer)
      home = URI.parse(root_url)
      referer.host != home.host
    else
      false
    end
  end

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:accept_invitation, keys: [:firstname, :surname, :org_id])
  end
end