WikiEducationFoundation/WikiEduDashboard

View on GitHub
app/controllers/application_controller.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

# The application controller is the parent for all other controllers.
# It includes methods are relevant across the application, such as permissions
# and login.
require_dependency "#{Rails.root}/lib/errors/authentication_errors"
require_dependency "#{Rails.root}/lib/errors/rescue_development_errors"
require_dependency "#{Rails.root}/lib/errors/rescue_errors"

class ApplicationController < ActionController::Base
  include Errors::RescueDevelopmentErrors if Rails.env.development? || Rails.env.test?
  include Errors::RescueErrors
  include Errors::AuthenticationErrors
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_action :check_for_expired_oauth_credentials
  before_action :check_for_unsupported_browser
  before_action :check_onboarded
  before_action :set_locale
  before_action :set_paper_trail_whodunnit
  before_action :authorize_rmp

  def after_sign_out_path_for(_resource_or_scope)
    '/'
  end

  def after_sign_in_path_for(_resource_or_scope)
    request.env['omniauth.origin'] || '/'
  end

  def check_onboarded
    return unless current_user
    return if Features.disable_onboarding? || current_user.onboarded
    full_path = request.fullpath
    non_redirect_paths = [onboarding_path,
                          onboard_path,
                          new_user_session_path,
                          destroy_user_session_path,
                          true_destroy_user_session_path]
    return if non_redirect_paths.any? { |path| full_path.starts_with? path }
    redirect_to onboarding_path(return_to: full_path)
  end

  def require_signed_in
    raise NotSignedInError unless user_signed_in?
  end

  def require_permissions
    require_signed_in
    course = Course.find_by!(slug: params[:id] || params[:slug] || params[:course_id])
    raise NotPermittedError unless current_user.can_edit? course
  end

  def require_admin_permissions
    require_signed_in
    raise NotAdminError unless current_user.admin?
  end

  def require_super_admin_permissions
    require_signed_in
    exception = NotAdminError.new('Only super administrators may do that.')
    raise exception unless current_user.super_admin?
  end

  def require_participating_user
    require_signed_in
    course = Course.find_by(slug: params[:id])
    return if current_user.nonvisitor?(course)
    raise ParticipatingUserError
  end

  def check_for_expired_oauth_credentials
    return unless current_user&.wiki_token == 'invalid'

    flash[:notice] = t('error.oauth_invalid')
    sign_out current_user
    redirect_to root_path
  end

  def check_for_unsupported_browser
    supported = !browser.ie?
    flash[:notice] = t('error.unsupported_browser.explanation') unless supported
  end

  def authorize_rmp
    return unless current_user&.super_admin?
    Rack::MiniProfiler.authorize_request
  end

  def course_slug_path(slug, args={})
    slug_parts = slug.split('/')
    show_path(args.merge(school: slug_parts[0], titleterm: slug_parts[1]))
  end
  helper_method :course_slug_path

  def rtl?
    tag = I18n::Locale::Tag::Rfc4646.tag(I18n.locale)
    tag.language.in? %w[ar dv fa he ku ps sd ug ur yi]
  end
  helper_method :rtl?

  def new_session_path(_scope)
    new_user_session_path
  end
  helper_method :new_session_path

  def can_administer?
    current_user&.admin?
  end

  private

  def set_locale
    # Saved user locale takes precedence over language preferences from HTTP headers.
    preferred_locale_from_user
    # Param takes precedence over saved user local
    preferred_locale_from_param

    preferred_locale = http_accept_language.preferred_language_from I18n.available_locales
    I18n.locale = preferred_locale || I18n.default_locale
  end

  def preferred_locale_from_user
    return unless current_user&.locale
    http_accept_language.user_preferred_languages.unshift(current_user.locale)
  end

  def preferred_locale_from_param
    return unless params[:locale]
    http_accept_language.user_preferred_languages.unshift(params[:locale])
  end
end