lhs 21.2.2 → 21.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +208 -107
 - data/lhs.gemspec +1 -1
 - data/lib/lhs.rb +8 -0
 - data/lib/lhs/concerns/autoload_records.rb +20 -3
 - data/lib/lhs/concerns/o_auth.rb +25 -0
 - data/lib/lhs/concerns/record/configuration.rb +28 -11
 - data/lib/lhs/concerns/record/request.rb +29 -8
 - data/lib/lhs/config.rb +1 -1
 - data/lib/lhs/interceptors/auto_oauth/interceptor.rb +33 -0
 - data/lib/lhs/interceptors/auto_oauth/thread_registry.rb +18 -0
 - data/lib/lhs/version.rb +1 -1
 - data/spec/auto_oauth_spec.rb +129 -0
 - data/spec/autoloading_spec.rb +35 -8
 - data/spec/dummy/app/controllers/application_controller.rb +15 -0
 - data/spec/dummy/app/controllers/automatic_authentication_controller.rb +22 -0
 - data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +2 -2
 - data/spec/dummy/app/controllers/extended_rollbar_controller.rb +2 -2
 - data/spec/dummy/app/controllers/option_blocks_controller.rb +2 -2
 - data/spec/dummy/app/models/dummy_customer.rb +6 -0
 - data/spec/dummy/app/models/{record.rb → dummy_record.rb} +1 -1
 - data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
 - data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
 - data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
 - data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
 - data/spec/dummy/app/models/{user.rb → dummy_user.rb} +1 -1
 - data/spec/dummy/app/models/providers/customer_system.rb +7 -0
 - data/spec/dummy/config/routes.rb +4 -0
 - data/spec/option_blocks/ensure_reset_between_requests_spec.rb +2 -1
 - data/spec/record/error_handling_integration_spec.rb +1 -1
 - data/spec/record/includes_spec.rb +41 -0
 - data/spec/request_cycle_cache_spec.rb +3 -3
 - data/spec/support/reset.rb +31 -9
 - metadata +29 -10
 
| 
         @@ -246,7 +246,9 @@ class LHS::Record 
     | 
|
| 
       246 
246 
     | 
    
         
             
                  def skip_loading_includes?(data, included)
         
     | 
| 
       247 
247 
     | 
    
         
             
                    if data.collection?
         
     | 
| 
       248 
248 
     | 
    
         
             
                      data.to_a.none? { |item| item[included].present? }
         
     | 
| 
       249 
     | 
    
         
            -
                    elsif data 
     | 
| 
      
 249 
     | 
    
         
            +
                    elsif data.dig(included).blank?
         
     | 
| 
      
 250 
     | 
    
         
            +
                      true
         
     | 
| 
      
 251 
     | 
    
         
            +
                    elsif data[included].item? && data[included][:href].blank?
         
     | 
| 
       250 
252 
     | 
    
         
             
                      true
         
     | 
| 
       251 
253 
     | 
    
         
             
                    else
         
     | 
| 
       252 
254 
     | 
    
         
             
                      !data._raw.key?(included)
         
     | 
| 
         @@ -515,20 +517,39 @@ class LHS::Record 
     | 
|
| 
       515 
517 
     | 
    
         
             
                    options[:url] = compute_url!(options[:params]) unless options.key?(:url)
         
     | 
| 
       516 
518 
     | 
    
         
             
                    merge_explicit_params!(options[:params])
         
     | 
| 
       517 
519 
     | 
    
         
             
                    options.delete(:params) if options[:params]&.empty?
         
     | 
| 
       518 
     | 
    
         
            -
                     
     | 
| 
      
 520 
     | 
    
         
            +
                    inject_interceptors!(options)
         
     | 
| 
       519 
521 
     | 
    
         
             
                    options
         
     | 
| 
       520 
522 
     | 
    
         
             
                  end
         
     | 
| 
       521 
523 
     | 
    
         | 
| 
       522 
     | 
    
         
            -
                   
     | 
| 
       523 
     | 
    
         
            -
             
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
      
 524 
     | 
    
         
            +
                  def inject_interceptors!(options)
         
     | 
| 
      
 525 
     | 
    
         
            +
                    if LHS.config.request_cycle_cache_enabled
         
     | 
| 
      
 526 
     | 
    
         
            +
                      inject_interceptor!(
         
     | 
| 
      
 527 
     | 
    
         
            +
                        options,
         
     | 
| 
      
 528 
     | 
    
         
            +
                        LHS::Interceptors::RequestCycleCache::Interceptor,
         
     | 
| 
      
 529 
     | 
    
         
            +
                        LHC::Caching,
         
     | 
| 
      
 530 
     | 
    
         
            +
                        "[WARNING] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured (see https://github.com/local-ch/lhc/blob/master/README.md#caching-interceptor)!"
         
     | 
| 
      
 531 
     | 
    
         
            +
                      )
         
     | 
| 
      
 532 
     | 
    
         
            +
                    end
         
     | 
| 
      
 533 
     | 
    
         
            +
             
     | 
| 
      
 534 
     | 
    
         
            +
                    endpoint = find_endpoint(options[:params], options.fetch(:url, nil))
         
     | 
| 
      
 535 
     | 
    
         
            +
                    if auto_oauth? || (endpoint.options&.dig(:oauth) && LHS.config.auto_oauth)
         
     | 
| 
      
 536 
     | 
    
         
            +
                      inject_interceptor!(
         
     | 
| 
      
 537 
     | 
    
         
            +
                        options.merge!(record: self),
         
     | 
| 
      
 538 
     | 
    
         
            +
                        LHS::Interceptors::AutoOauth::Interceptor,
         
     | 
| 
      
 539 
     | 
    
         
            +
                        LHC::Auth,
         
     | 
| 
      
 540 
     | 
    
         
            +
                        "[WARNING] Can't enable auto oauth as LHC::Auth interceptor is not enabled/configured (see https://github.com/local-ch/lhc/blob/master/README.md#authentication-interceptor)!"
         
     | 
| 
      
 541 
     | 
    
         
            +
                      )
         
     | 
| 
      
 542 
     | 
    
         
            +
                    end
         
     | 
| 
      
 543 
     | 
    
         
            +
                  end
         
     | 
| 
      
 544 
     | 
    
         
            +
             
     | 
| 
      
 545 
     | 
    
         
            +
                  def inject_interceptor!(options, interceptor, dependecy, warning)
         
     | 
| 
       525 
546 
     | 
    
         
             
                    interceptors = options[:interceptors] || LHC.config.interceptors
         
     | 
| 
       526 
     | 
    
         
            -
                    if interceptors.include?( 
     | 
| 
      
 547 
     | 
    
         
            +
                    if interceptors.include?(dependecy)
         
     | 
| 
       527 
548 
     | 
    
         
             
                      # Ensure interceptor is prepend
         
     | 
| 
       528 
     | 
    
         
            -
                      interceptors = interceptors.unshift( 
     | 
| 
      
 549 
     | 
    
         
            +
                      interceptors = interceptors.unshift(interceptor)
         
     | 
| 
       529 
550 
     | 
    
         
             
                      options[:interceptors] = interceptors
         
     | 
| 
       530 
551 
     | 
    
         
             
                    else
         
     | 
| 
       531 
     | 
    
         
            -
                      warn( 
     | 
| 
      
 552 
     | 
    
         
            +
                      warn(warning)
         
     | 
| 
       532 
553 
     | 
    
         
             
                    end
         
     | 
| 
       533 
554 
     | 
    
         
             
                  end
         
     | 
| 
       534 
555 
     | 
    
         | 
    
        data/lib/lhs/config.rb
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ require 'singleton' 
     | 
|
| 
       5 
5 
     | 
    
         
             
            class LHS::Config
         
     | 
| 
       6 
6 
     | 
    
         
             
              include Singleton
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
              attr_accessor :request_cycle_cache_enabled, :request_cycle_cache, :trace
         
     | 
| 
      
 8 
     | 
    
         
            +
              attr_accessor :request_cycle_cache_enabled, :request_cycle_cache, :trace, :auto_oauth
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
              def initialize
         
     | 
| 
       11 
11 
     | 
    
         
             
                self.request_cycle_cache_enabled ||= true
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_support'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module LHS
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Interceptors
         
     | 
| 
      
 7 
     | 
    
         
            +
                module AutoOauth
         
     | 
| 
      
 8 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  class Interceptor < LHC::Interceptor
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    def before_request
         
     | 
| 
      
 13 
     | 
    
         
            +
                      request.options[:auth] = { bearer: token }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def tokens
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @tokens ||= LHS::Interceptors::AutoOauth::ThreadRegistry.access_token
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    def token
         
     | 
| 
      
 21 
     | 
    
         
            +
                      if tokens.is_a?(Hash)
         
     | 
| 
      
 22 
     | 
    
         
            +
                        tokens.dig(
         
     | 
| 
      
 23 
     | 
    
         
            +
                          request.options[:oauth] ||
         
     | 
| 
      
 24 
     | 
    
         
            +
                          request.options[:record]&.auto_oauth
         
     | 
| 
      
 25 
     | 
    
         
            +
                        )
         
     | 
| 
      
 26 
     | 
    
         
            +
                      else
         
     | 
| 
      
 27 
     | 
    
         
            +
                        tokens
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_support'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'active_support/per_thread_registry'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module LHS
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Interceptors
         
     | 
| 
      
 8 
     | 
    
         
            +
                module AutoOauth
         
     | 
| 
      
 9 
     | 
    
         
            +
                  extend ActiveSupport::Concern
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class ThreadRegistry
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
         
     | 
| 
      
 12 
     | 
    
         
            +
                    # Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v4.
         
     | 
| 
      
 13 
     | 
    
         
            +
                    extend ActiveSupport::PerThreadRegistry
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attr_accessor :access_token
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/lhs/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,129 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rails_helper'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe 'Auto OAuth Authentication', type: :request, dummy_models: true do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              context 'without LHC::Auth interceptor enabled' do
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                before do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  LHS.configure do |config|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    config.auto_oauth = -> { access_token }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                it 'shows a warning that it can not perform auto authentication' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  expect(lambda do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    get '/automatic_authentication/oauth'
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end).to output(
         
     | 
| 
      
 19 
     | 
    
         
            +
                    %r{\[WARNING\] Can't enable auto oauth as LHC::Auth interceptor is not enabled\/configured \(see https://github.com/local-ch/lhc/blob/master/README.md#authentication-interceptor\)!}
         
     | 
| 
      
 20 
     | 
    
         
            +
                  ).to_stderr
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              context 'with LHC::Auth interceptor enabled' do
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                context 'with only one auth provider' do
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  let(:token) { ApplicationController::ACCESS_TOKEN }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  let(:record_request) do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_oauth/1")
         
     | 
| 
      
 32 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 33 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}" }
         
     | 
| 
      
 34 
     | 
    
         
            +
                      ).to_return(status: 200, body: { name: 'Record' }.to_json)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  let(:records_request) do
         
     | 
| 
      
 38 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_oauth?color=blue")
         
     | 
| 
      
 39 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 40 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}" }
         
     | 
| 
      
 41 
     | 
    
         
            +
                      ).to_return(status: 200, body: { items: [{ name: 'Record' }] }.to_json)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    LHS.configure do |config|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      config.auto_oauth = -> { access_token }
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    LHC.configure do |config|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      config.interceptors = [LHC::Auth]
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    record_request
         
     | 
| 
      
 52 
     | 
    
         
            +
                    records_request
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  after do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    LHC.config.reset
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  it 'applies OAuth credentials for the individual request automatically' do
         
     | 
| 
      
 60 
     | 
    
         
            +
                    get '/automatic_authentication/oauth'
         
     | 
| 
      
 61 
     | 
    
         
            +
                    expect(record_request).to have_been_requested
         
     | 
| 
      
 62 
     | 
    
         
            +
                    expect(records_request).to have_been_requested
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                context 'with multiple auth providers' do
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 69 
     | 
    
         
            +
                    LHS.configure do |config|
         
     | 
| 
      
 70 
     | 
    
         
            +
                      config.auto_oauth = proc do
         
     | 
| 
      
 71 
     | 
    
         
            +
                        {
         
     | 
| 
      
 72 
     | 
    
         
            +
                          provider1: access_token_provider_1,
         
     | 
| 
      
 73 
     | 
    
         
            +
                          provider2: access_token_provider_2
         
     | 
| 
      
 74 
     | 
    
         
            +
                        }
         
     | 
| 
      
 75 
     | 
    
         
            +
                      end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                    LHC.configure do |config|
         
     | 
| 
      
 78 
     | 
    
         
            +
                      config.interceptors = [LHC::Auth]
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
                    record_request_provider_1
         
     | 
| 
      
 81 
     | 
    
         
            +
                    records_request_provider_2
         
     | 
| 
      
 82 
     | 
    
         
            +
                    records_request_per_endpoint_provider_1
         
     | 
| 
      
 83 
     | 
    
         
            +
                    record_request_per_endpoint_provider_2
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  let(:token) { ApplicationController::ACCESS_TOKEN }
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  let(:record_request_provider_1) do
         
     | 
| 
      
 89 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_multiple_oauth_providers_1/1")
         
     | 
| 
      
 90 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 91 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}_provider_1" }
         
     | 
| 
      
 92 
     | 
    
         
            +
                      ).to_return(status: 200, body: { name: 'Record' }.to_json)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  let(:records_request_provider_2) do
         
     | 
| 
      
 96 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_multiple_oauth_providers_2?color=blue")
         
     | 
| 
      
 97 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 98 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}_provider_2" }
         
     | 
| 
      
 99 
     | 
    
         
            +
                      ).to_return(status: 200, body: { items: [{ name: 'Record' }] }.to_json)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  let(:records_request_per_endpoint_provider_1) do
         
     | 
| 
      
 103 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_multiple_oauth_providers_per_endpoint?color=blue")
         
     | 
| 
      
 104 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 105 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}_provider_1" }
         
     | 
| 
      
 106 
     | 
    
         
            +
                      ).to_return(status: 200, body: { items: [{ name: 'Record' }] }.to_json)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  let(:record_request_per_endpoint_provider_2) do
         
     | 
| 
      
 110 
     | 
    
         
            +
                    stub_request(:get, "http://datastore/v2/records_with_multiple_oauth_providers_per_endpoint/1")
         
     | 
| 
      
 111 
     | 
    
         
            +
                      .with(
         
     | 
| 
      
 112 
     | 
    
         
            +
                        headers: { 'Authorization' => "Bearer #{token}_provider_2" }
         
     | 
| 
      
 113 
     | 
    
         
            +
                      ).to_return(status: 200, body: { name: 'Record' }.to_json)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  after do
         
     | 
| 
      
 117 
     | 
    
         
            +
                    LHC.config.reset
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                  it 'applies OAuth credentials for the individual request automatically no matter how many auth providers are configured ' do
         
     | 
| 
      
 121 
     | 
    
         
            +
                    get '/automatic_authentication/oauth_with_multiple_providers'
         
     | 
| 
      
 122 
     | 
    
         
            +
                    expect(record_request_provider_1).to have_been_requested
         
     | 
| 
      
 123 
     | 
    
         
            +
                    expect(records_request_provider_2).to have_been_requested
         
     | 
| 
      
 124 
     | 
    
         
            +
                    expect(records_request_per_endpoint_provider_1).to have_been_requested
         
     | 
| 
      
 125 
     | 
    
         
            +
                    expect(record_request_per_endpoint_provider_2).to have_been_requested
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
              end
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/autoloading_spec.rb
    CHANGED
    
    | 
         @@ -4,18 +4,45 @@ require "rails_helper" 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            describe LHS, type: :request do
         
     | 
| 
       6 
6 
     | 
    
         
             
              context 'autoloading' do
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                  expect( 
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                let(:endpoints) { LHS::Record::Endpoints.all }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                it "pre/re-loads all LHS classes initialy, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  expect(endpoints['http://datastore/v2/users']).to be_present
         
     | 
| 
      
 13 
     | 
    
         
            +
                  expect(endpoints['http://datastore/v2/users/{id}']).to be_present
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       13 
15 
     | 
    
         
             
                  expect(
         
     | 
| 
       14 
     | 
    
         
            -
                     
     | 
| 
      
 16 
     | 
    
         
            +
                    DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users' }
         
     | 
| 
       15 
17 
     | 
    
         
             
                  ).to be_present
         
     | 
| 
       16 
18 
     | 
    
         
             
                  expect(
         
     | 
| 
       17 
     | 
    
         
            -
                     
     | 
| 
      
 19 
     | 
    
         
            +
                    DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users/{id}' }
         
     | 
| 
       18 
20 
     | 
    
         
             
                  ).to be_present
         
     | 
| 
       19 
21 
     | 
    
         
             
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                it "also pre/re-loads all LHS classes that inherited from an LHS provider, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  expect(endpoints['http://customers']).to be_present
         
     | 
| 
      
 26 
     | 
    
         
            +
                  expect(endpoints['http://customers/{id}']).to be_present
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  expect(
         
     | 
| 
      
 29 
     | 
    
         
            +
                    DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers' }
         
     | 
| 
      
 30 
     | 
    
         
            +
                  ).to be_present
         
     | 
| 
      
 31 
     | 
    
         
            +
                  expect(
         
     | 
| 
      
 32 
     | 
    
         
            +
                    DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers/{id}' }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  ).to be_present
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  customer_request = stub_request(:get, "http://customers/1")
         
     | 
| 
      
 36 
     | 
    
         
            +
                    .with(
         
     | 
| 
      
 37 
     | 
    
         
            +
                      headers: {
         
     | 
| 
      
 38 
     | 
    
         
            +
                        'Authorization' => 'token123'
         
     | 
| 
      
 39 
     | 
    
         
            +
                      }
         
     | 
| 
      
 40 
     | 
    
         
            +
                    )
         
     | 
| 
      
 41 
     | 
    
         
            +
                    .to_return(body: { name: 'Steve' }.to_json)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  DummyCustomer.find(1)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  expect(customer_request).to have_been_requested
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
       20 
47 
     | 
    
         
             
              end
         
     | 
| 
       21 
48 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,6 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            class ApplicationController < ActionController::Base
         
     | 
| 
      
 4 
     | 
    
         
            +
              include LHS::OAuth
         
     | 
| 
      
 5 
     | 
    
         
            +
              ACCESS_TOKEN = 'token-12345'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       4 
7 
     | 
    
         
             
              # Prevent CSRF attacks by raising an exception.
         
     | 
| 
       5 
8 
     | 
    
         
             
              # For APIs, you may want to use :null_session instead.
         
     | 
| 
       6 
9 
     | 
    
         
             
              protect_from_forgery with: :exception
         
     | 
| 
         @@ -8,4 +11,16 @@ class ApplicationController < ActionController::Base 
     | 
|
| 
       8 
11 
     | 
    
         
             
              def root
         
     | 
| 
       9 
12 
     | 
    
         
             
                render nothing: true
         
     | 
| 
       10 
13 
     | 
    
         
             
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def access_token
         
     | 
| 
      
 16 
     | 
    
         
            +
                ACCESS_TOKEN
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              def access_token_provider_1
         
     | 
| 
      
 20 
     | 
    
         
            +
                "#{ACCESS_TOKEN}_provider_1"
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def access_token_provider_2
         
     | 
| 
      
 24 
     | 
    
         
            +
                "#{ACCESS_TOKEN}_provider_2"
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
       11 
26 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class AutomaticAuthenticationController < ApplicationController
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def o_auth
         
     | 
| 
      
 6 
     | 
    
         
            +
                render json: {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  record: DummyRecordWithOauth.find(1).as_json,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  records: DummyRecordWithOauth.where(color: 'blue').as_json
         
     | 
| 
      
 9 
     | 
    
         
            +
                }
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def o_auth_with_multiple_providers
         
     | 
| 
      
 13 
     | 
    
         
            +
                render json: {
         
     | 
| 
      
 14 
     | 
    
         
            +
                  record: DummyRecordWithMultipleOauthProviders1.find(1).as_json,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  records: DummyRecordWithMultipleOauthProviders2.where(color: 'blue').as_json,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  per_endpoint: {
         
     | 
| 
      
 17 
     | 
    
         
            +
                    record: DummyRecordWithMultipleOauthProvidersPerEndpoint.find(1).as_json,
         
     | 
| 
      
 18 
     | 
    
         
            +
                    records: DummyRecordWithMultipleOauthProvidersPerEndpoint.where(color: 'blue').as_json
         
     | 
| 
      
 19 
     | 
    
         
            +
                  }
         
     | 
| 
      
 20 
     | 
    
         
            +
                }
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,7 +5,7 @@ class ErrorHandlingWithChainsController < ApplicationController 
     | 
|
| 
       5 
5 
     | 
    
         
             
              # Example where the query chain is resolved
         
     | 
| 
       6 
6 
     | 
    
         
             
              # in the view (during render 'show')
         
     | 
| 
       7 
7 
     | 
    
         
             
              def fetch_in_view
         
     | 
| 
       8 
     | 
    
         
            -
                @records =  
     | 
| 
      
 8 
     | 
    
         
            +
                @records = DummyRecord
         
     | 
| 
       9 
9 
     | 
    
         
             
                  .handle(LHC::Error, ->(error) { handle_error(error) })
         
     | 
| 
       10 
10 
     | 
    
         
             
                  .where(color: 'blue')
         
     | 
| 
       11 
11 
     | 
    
         
             
                render 'show'
         
     | 
| 
         @@ -15,7 +15,7 @@ class ErrorHandlingWithChainsController < ApplicationController 
     | 
|
| 
       15 
15 
     | 
    
         
             
              # Example where the query chain is resolved
         
     | 
| 
       16 
16 
     | 
    
         
             
              # before the view is rendered
         
     | 
| 
       17 
17 
     | 
    
         
             
              def fetch_in_controller
         
     | 
| 
       18 
     | 
    
         
            -
                @records =  
     | 
| 
      
 18 
     | 
    
         
            +
                @records = DummyRecord
         
     | 
| 
       19 
19 
     | 
    
         
             
                  .handle(LHC::Error, ->(error) { handle_error(error) })
         
     | 
| 
       20 
20 
     | 
    
         
             
                  .where(color: 'blue').fetch
         
     | 
| 
       21 
21 
     | 
    
         
             
                render 'show'
         
     | 
| 
         @@ -3,8 +3,8 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            class ExtendedRollbarController < ApplicationController
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
              def extended_rollbar
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
      
 6 
     | 
    
         
            +
                DummyRecord.where(color: 'blue').fetch
         
     | 
| 
      
 7 
     | 
    
         
            +
                DummyRecord.where(color: 'red').fetch
         
     | 
| 
       8 
8 
     | 
    
         
             
                raise "Let's see if rollbar logs information about what kind of requests where made around here!"
         
     | 
| 
       9 
9 
     | 
    
         
             
              end
         
     | 
| 
       10 
10 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,12 +4,12 @@ class OptionBlocksController < ApplicationController 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
              def first
         
     | 
| 
       6 
6 
     | 
    
         
             
                LHS::OptionBlocks::CurrentOptionBlock.options = { params: { request: 'first' } }
         
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
      
 7 
     | 
    
         
            +
                DummyRecord.where(request: 'second').fetch
         
     | 
| 
       8 
8 
     | 
    
         
             
                render text: 'ok'
         
     | 
| 
       9 
9 
     | 
    
         
             
              end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
              def second
         
     | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
      
 12 
     | 
    
         
            +
                DummyRecord.where(request: 'second').fetch
         
     | 
| 
       13 
13 
     | 
    
         
             
                render text: 'ok'
         
     | 
| 
       14 
14 
     | 
    
         
             
              end
         
     | 
| 
       15 
15 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class DummyRecordWithMultipleOauthProviders1 < LHS::Record
         
     | 
| 
      
 4 
     | 
    
         
            +
              oauth(:provider1)
         
     | 
| 
      
 5 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_1'
         
     | 
| 
      
 6 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_1/{id}'
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class DummyRecordWithMultipleOauthProviders2 < LHS::Record
         
     | 
| 
      
 4 
     | 
    
         
            +
              oauth(:provider2)
         
     | 
| 
      
 5 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_2'
         
     | 
| 
      
 6 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_2/{id}'
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,6 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class DummyRecordWithMultipleOauthProvidersPerEndpoint < LHS::Record
         
     | 
| 
      
 4 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_per_endpoint', oauth: :provider1
         
     | 
| 
      
 5 
     | 
    
         
            +
              endpoint 'http://datastore/v2/records_with_multiple_oauth_providers_per_endpoint/{id}', oauth: :provider2
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     |