# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true

require 'contrast/framework/rails/patch/rails_application_configuration'
require 'contrast/agent/patching/policy/after_load_patch'

module Contrast
  module Framework
    module Rails
      module Patch
        # Extension point allowing for the registration of Patches required to
        # support the Rails framework.
        module Support
          # (See BaseSupport#before_load_patches!)
          def before_load_patches!
            return unless defined?(::Rails)

            # In Rails, session configuration occurs extremely early & only once.
            # If we defer our patching of the rails session configuration too long
            # (i.e., where we normally patch) we will miss the configuration
            # and will never be able to report session misconfiguration rules.
            Contrast::Framework::Rails::Patch::RailsApplicationConfiguration.instrument
            require 'contrast/framework/rails/railtie' if ::Rails::VERSION::MAJOR.to_i >= 3
          end

          # (See BaseSupport#after_load_patches)
          def after_load_patches
            patches = Set.new([
                                Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                    'ActionController::Live::Buffer',
                                    'contrast/framework/rails/patch/action_controller_live_buffer',
                                    instrumenting_module:
                                      'Contrast::Framework::Rails::Patch::ActionControllerLiveBuffer'),
                                Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                    'Rails::Application::Configuration',
                                    'contrast/framework/rails/patch/rails_application_configuration',
                                    method_to_instrument: :session_store,
                                    instrumenting_module:
                                      'Contrast::Framework::Rails::Patch::RailsApplicationConfiguration')
                              ])
            if RUBY_VERSION < '2.6.0'
              patches.merge([
                              # TODO: RUBY-714 remove w/ EOL of 2.5
                              #
                              # @deprecated  Everything past here is used for Rewriting and can
                              #   be removed once we no longer support 2.5.
                              Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                  'ActionController::Railties::Helper::ClassMethods',
                                  'contrast/framework/rails/rewrite/action_controller_railties_helper_inherited',
                                  method_to_instrument: :inherited,
                                  instrumenting_module:
                                    'Contrast::Framework::Rails::Rewrite::ActionControllerRailtiesHelperInherited'),
                              Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                  'ActiveRecord::AttributeMethods::Read::ClassMethods',
                                  'contrast/framework/rails/rewrite/active_record_attribute_methods_read',
                                  instrumenting_module:
                                    'Contrast::Framework::Rails::Rewrite::ActiveRecordAttributeMethodsRead'),
                              Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                  'ActiveRecord::Scoping::Named::ClassMethods',
                                  'contrast/framework/rails/rewrite/active_record_named',
                                  instrumenting_module: 'Contrast::Framework::Rails::Rewrite::ActiveRecordNamed'),
                              Contrast::Agent::Patching::Policy::AfterLoadPatch.new(
                                  'ActiveRecord::AttributeMethods::TimeZoneConversion::ClassMethods',
                                  'contrast/framework/rails/rewrite/active_record_time_zone_inherited',
                                  method_to_instrument: :inherited,
                                  instrumenting_module:
                                    'Contrast::Framework::Rails::Rewrite::ActiveRecordTimeZoneInherited')
                            ])
            end
            patches
          end
        end
      end
    end
  end
end