require 'apartment' require 'ims/lti' require 'attr_encrypted' require 'secure_headers' require_relative './helpers/console_helpers' module PandaPal class Engine < ::Rails::Engine isolate_namespace PandaPal config.generators do |g| g.test_framework :rspec g.fixture_replacement :factory_girl, :dir => 'spec/factories' end initializer :append_migrations do |app| config.paths["db/migrate"].expanded.each do |expanded_path| app.config.paths["db/migrate"] << expanded_path end # Apartment will modify this, but it doesn't fully support engine migrations, so we'll reset it here ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a end initializer 'interop dependencies' do begin require 'sidekiq' rescue LoadError end if defined?(Sidekiq) begin require 'apartment-sidekiq' rescue LoadError raise "Sidekiq is used, but apartment-sidekiq is not installed. Add [gem 'ros-apartment-sidekiq'] to your Gemfile" end end if $LOADED_FEATURES.grep(/\/ros-apartment-\d/).present? if $LOADED_FEATURES.grep(/\/apartment-\d/).present? || $LOADED_FEATURES.grep(/\/apartment-sidekiq-\d/).present? raise "ros-apartment is used, but apartment or apartment-sidekiq is loaded. Do not mix legacy and ros- variants! (You most likely need to update your Gemfile to use the ros- variant)" end end end initializer 'Sidekiq Scheduler Hooks' do ActiveSupport.on_load(:active_record) do if defined?(Sidekiq) && Sidekiq.server? Rails.application.reloader.to_prepare do PandaPal::Organization.sync_schedules if PandaPal::Organization.respond_to?(:sync_schedules) end end end end initializer "panda_pal.globals" do |app| class ::Object unless defined?(switch_tenant) def switch_tenant(tenant, &block) if block_given? Apartment::Tenant.switch(tenant, &block) else Apartment::Tenant.switch!(tenant) end end end unless defined?(switch_org) def switch_org(org, &block) org = PandaPal::Organization.for_apt_tenant(org) if org.is_a?(String) org.switch_tenant(&block) end end unless defined?(current_organization) def current_organization PandaPal::Organization.for_apt_tenant(Apartment::Tenant.current) end end end end initializer "panda_pal.prompts" do |app| class ::Object def _panda_pal_console_app_name app_class = Rails.application.class app_name = app_class.respond_to?(:parent) ? app_class.parent : app_class.module_parent app_name.to_s end def _panda_pal_short_console_app_name _panda_pal_console_app_name[0...10] end def _panda_pal_console_env if Rails.env.production? env = ENV["SENTRY_CURRENT_ENV"].presence || "PROD" if env.downcase.include?("prod") PandaPal::ConsoleHelpers.red(env) else PandaPal::ConsoleHelpers.cyan(env) end elsif Rails.env.development? PandaPal::ConsoleHelpers.cyan("dev") elsif Rails.env.test? PandaPal::ConsoleHelpers.cyan("test") end end def _panda_pal_console_prefix pfx = [ PandaPal::ConsoleHelpers.cyan(_panda_pal_short_console_app_name), _panda_pal_console_env, PandaPal::ConsoleHelpers.cyan(Apartment::Tenant.current), ].compact.join('-') pfx end end if defined? IRB module PandaPalIrbPrompt def prompt(prompt, ltype, indent, line_no) formatted = super(prompt, ltype, indent, line_no) app_bit = _panda_pal_console_prefix "[#{app_bit}] #{formatted}" end end module ::IRB class Irb prepend PandaPalIrbPrompt end end end if defined?(Pry) default_prompt = Pry::Prompt[:default] env = Pry::Helpers::Text.red(Rails.env.upcase) Pry.config.prompt = Pry::Prompt.new( 'custom', 'my custom prompt', [ ->(*args) { app_bit = _panda_pal_console_prefix "#{app_bit}#{default_prompt.wait_proc.call(*args)}" }, ->(*args) { app_bit = _panda_pal_console_prefix "#{app_bit}#{default_prompt.incomplete_proc.call(*args)}" }, ], ) end if defined? Rails::Console module PandaPal::ConsoleExtPrefix extend ActiveSupport::Concern def start(*args) print "\033];#{_panda_pal_console_app_name} Rails Console\007" super end end Rails::Console.prepend(PandaPal::ConsoleExtPrefix) end end initializer "panda_pal.autoswitch" do |app| if defined? Rails::Console module PandaPal::ConsoleExtAutoSwitch extend ActiveSupport::Concern def start(*args) begin org = nil if Rails.env.development? org = PandaPal::Organization.find_by(name: 'local') || PandaPal::Organization.first elsif PandaPal::Organization.count == 1 org = PandaPal::Organization.first end if org org.switch_tenant puts "PandaPal: Auto Switched to tenant '#{org.name}'" end rescue => err puts "PandaPal: Error occurred auto-switching tenant: #{err}" end super end end Rails::Console.prepend(PandaPal::ConsoleExtAutoSwitch) end end initializer "panda_pal.serialze_symbols" do |app| app.config.active_record.yaml_column_permitted_classes ||= [] app.config.active_record.yaml_column_permitted_classes |= [ Symbol, ActiveSupport::Duration, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, Time, ] rescue end initializer 'panda_pal.app_controller' do |app| OAUTH_10_SUPPORT = true ActiveSupport.on_load(:action_controller) do include PandaPal::Helpers::ControllerHelper include PandaPal::Concerns::AbilityHelper end end initializer 'panda_pal.route_helper' do |route| ActionDispatch::Routing::Mapper.send :include, PandaPal::Helpers::RouteHelper end config.after_initialize do |app| ActiveSupport.on_load(:action_controller) do Rails.application.reload_routes! PandaPal::validate_pandapal_config! end end initializer "panda_pal.assets.precompile" do |app| app.config.assets.precompile << "panda_pal_manifest.js" rescue nil end initializer :secure_headers do |app| begin ::SecureHeaders::Configuration.default do |config| PandaPal::SecureHeaders.apply_defaults(config) end rescue ::SecureHeaders::Configuration::AlreadyConfiguredError # The App already applied settings end ::SecureHeaders::Configuration.override(:safari_override) do |config| config.cookies = ::SecureHeaders::OPT_OUT end end end end