CircuitVerse/CircuitVerse

View on GitHub
app/controllers/application_controller.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

class ApplicationController < ActionController::Base
  include Pundit::Authorization
  protect_from_forgery with: :exception

  before_action :store_user_location!, if: :storable_location?
  before_action :set_notifications, if: :current_user
  around_action :switch_locale

  rescue_from Pundit::NotAuthorizedError, with: :auth_error
  rescue_from ApplicationPolicy::CustomAuthException, with: :custom_auth_error
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  def auth_error
    render plain: "You are not authorized to do the requested operation"
  end

  def custom_auth_error(exception)
    render plain: "Not Authorized: #{exception.custom_message}", status: :forbidden
  end

  def not_found
    render "errors/not_found", status: :not_found
  end

  def switch_locale(&block)
    logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
    locale = current_user&.locale ||
             extract_locale_from_accept_language_header ||
             I18n.default_locale
    logger.debug "* Locale set to '#{locale}'"
    begin
      I18n.with_locale(locale, &block)
    rescue I18n::InvalidLocale
      locale = I18n.default_locale
      retry
    end
  end

  # Overrides Devise::Controller::StoreLocation.store_location_for to check if
  # URL is too long to store in the session
  def store_location_for(resource_or_scope, location)
    max_location_size = 200 # bytes
    if location && location.length > max_location_size
      super resource_or_scope, "/"
    else
      super
    end
  end

  private

    def extract_locale_from_accept_language_header
      request.env["HTTP_ACCEPT_LANGUAGE"]&.scan(/^[a-z]{2}/)&.first
    end

    def set_notifications
      @unread = NoticedNotification.where(recipient: current_user).unread
      @notification = NoticedNotification.where(recipient: current_user).newest_first.limit(5)
    end

    def storable_location?
      request.get? && is_navigational_format? && !devise_controller? && !request.xhr?
    end

    def store_user_location!
      store_location_for(:user, request.fullpath)
    end

    def after_sign_in_path_for(resource_or_scope)
      stored_location_for(resource_or_scope) || super
    end
end