forest_liana 2.15.4 → 2.15.5
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/app/services/forest_liana/resources_getter.rb +10 -2
 - data/lib/forest_liana/engine.rb +11 -13
 - data/lib/forest_liana/version.rb +1 -1
 - data/spec/dummy/README.rdoc +28 -0
 - data/spec/dummy/Rakefile +6 -0
 - data/spec/dummy/app/assets/javascripts/application.js +13 -0
 - data/spec/dummy/app/assets/stylesheets/application.css +15 -0
 - data/spec/dummy/app/config/routes.rb +3 -0
 - data/spec/dummy/app/controllers/application_controller.rb +5 -0
 - data/spec/dummy/app/helpers/application_helper.rb +2 -0
 - data/spec/dummy/app/models/island.rb +5 -0
 - data/spec/dummy/app/models/tree.rb +5 -0
 - data/spec/dummy/app/models/user.rb +4 -0
 - data/spec/dummy/app/views/layouts/application.html.erb +14 -0
 - data/spec/dummy/bin/bundle +3 -0
 - data/spec/dummy/bin/rails +4 -0
 - data/spec/dummy/bin/rake +4 -0
 - data/spec/dummy/bin/setup +29 -0
 - data/spec/dummy/config.ru +4 -0
 - data/spec/dummy/config/application.rb +26 -0
 - data/spec/dummy/config/boot.rb +5 -0
 - data/spec/dummy/config/database.yml +25 -0
 - data/spec/dummy/config/environment.rb +5 -0
 - data/spec/dummy/config/environments/development.rb +41 -0
 - data/spec/dummy/config/environments/production.rb +79 -0
 - data/spec/dummy/config/environments/test.rb +42 -0
 - data/spec/dummy/config/initializers/assets.rb +11 -0
 - data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
 - data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
 - data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
 - data/spec/dummy/config/initializers/forest_liana.rb +2 -0
 - data/spec/dummy/config/initializers/inflections.rb +16 -0
 - data/spec/dummy/config/initializers/mime_types.rb +4 -0
 - data/spec/dummy/config/initializers/session_store.rb +3 -0
 - data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
 - data/spec/dummy/config/routes.rb +3 -0
 - data/spec/dummy/config/secrets.yml +22 -0
 - data/spec/dummy/db/migrate/20190226172951_create_user.rb +9 -0
 - data/spec/dummy/db/migrate/20190226173051_create_isle.rb +10 -0
 - data/spec/dummy/db/migrate/20190226174951_create_tree.rb +12 -0
 - data/spec/dummy/db/schema.rb +42 -0
 - data/spec/dummy/db/test.sqlite3 +0 -0
 - data/spec/dummy/log/development.log +80 -0
 - data/spec/dummy/log/test.log +22549 -0
 - data/spec/helpers/forest_liana/query_helper_spec.rb +74 -0
 - data/spec/rails_helper.rb +61 -0
 - data/spec/requests/resources_spec.rb +97 -0
 - data/spec/services/forest_liana/apimap_sorter_spec.rb +172 -0
 - data/spec/services/forest_liana/ip_whitelist_checker_spec.rb +203 -0
 - data/spec/services/forest_liana/schema_adapter_spec.rb +17 -0
 - data/spec/spec_helper.rb +99 -0
 - data/test/dummy/config/routes.rb +0 -1
 - data/test/dummy/db/test.sqlite3 +0 -0
 - data/test/dummy/log/test.log +1213 -0
 - data/test/routing/route_test.rb +0 -2
 - metadata +98 -2
 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ForestLiana
         
     | 
| 
      
 2 
     | 
    
         
            +
              describe QueryHelper do
         
     | 
| 
      
 3 
     | 
    
         
            +
                before(:all) do
         
     | 
| 
      
 4 
     | 
    
         
            +
                  Tree.connection
         
     | 
| 
      
 5 
     | 
    
         
            +
                  User.connection
         
     | 
| 
      
 6 
     | 
    
         
            +
                  Island.connection
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                describe 'get_one_associations' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  context 'on a model having 2 hasMany associations' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                    it 'should not return any one-one associations' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                      associations = QueryHelper.get_one_associations(User)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      expect(associations.length).to eq(0)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  context 'on a model having 3 belongsTo associations' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    it 'should return the one-one associations' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                      associations = QueryHelper.get_one_associations(Tree)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      expect(associations.length).to eq(3)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      expect(associations.first.name).to eq(:owner)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      expect(associations.first.klass).to eq(User)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      expect(associations.second.name).to eq(:cutter)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      expect(associations.second.klass).to eq(User)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      expect(associations.third.name).to eq(:island)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      expect(associations.third.klass).to eq(Island)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                describe 'get_one_association_names_symbol' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  it 'should return the one-one associations names as symbols' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect(QueryHelper.get_one_association_names_symbol(Tree)).to eq([:owner, :cutter, :island])
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                describe 'get_one_association_names_string' do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  it 'should return the one-one associations names as strings' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    expect(QueryHelper.get_one_association_names_string(Tree)).to eq(['owner', 'cutter', 'island'])
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                describe 'get_tables_associated_to_relations_name' do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  context 'on a model having 2 hasMany associations' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    it 'should return an empty hash' do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      tables_associated_to_relations_name =
         
     | 
| 
      
 47 
     | 
    
         
            +
                        QueryHelper.get_tables_associated_to_relations_name(User)
         
     | 
| 
      
 48 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name.keys.length).to eq(0)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  context 'on a model having 2 belongsTo associations' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    tables_associated_to_relations_name =
         
     | 
| 
      
 54 
     | 
    
         
            +
                      QueryHelper.get_tables_associated_to_relations_name(Tree)
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    it 'should return the one-one associations' do
         
     | 
| 
      
 57 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name.keys.length).to eq(2)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    it 'should return relationships having a name different than the targeted model' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name['users'].length).to eq(2)
         
     | 
| 
      
 62 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name['users'].first).to eq(:owner)
         
     | 
| 
      
 63 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name['users'].second).to eq(:cutter)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    it 'should return relationships on models having a custom table name' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name['isle'].length).to eq(1)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      expect(tables_associated_to_relations_name['isle'].first).to eq(:island)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # This file is copied to spec/ when you run 'rails generate rspec:install'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 3 
     | 
    
         
            +
            ENV['RAILS_ENV'] ||= 'test'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require File.expand_path('../dummy/config/environment', __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Prevent database truncation if the environment is production
         
     | 
| 
      
 6 
     | 
    
         
            +
            abort("The Rails environment is running in production mode!") if Rails.env.production?
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'rspec/rails'
         
     | 
| 
      
 8 
     | 
    
         
            +
            # Add additional requires below this line. Rails is not loaded until this point!
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            # Requires supporting ruby files with custom matchers and macros, etc, in
         
     | 
| 
      
 11 
     | 
    
         
            +
            # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
         
     | 
| 
      
 12 
     | 
    
         
            +
            # run as spec files by default. This means that files in spec/support that end
         
     | 
| 
      
 13 
     | 
    
         
            +
            # in _spec.rb will both be required and run as specs, causing the specs to be
         
     | 
| 
      
 14 
     | 
    
         
            +
            # run twice. It is recommended that you do not name files matching this glob to
         
     | 
| 
      
 15 
     | 
    
         
            +
            # end with _spec.rb. You can configure this pattern with the --pattern
         
     | 
| 
      
 16 
     | 
    
         
            +
            # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
         
     | 
| 
      
 17 
     | 
    
         
            +
            #
         
     | 
| 
      
 18 
     | 
    
         
            +
            # The following line is provided for convenience purposes. It has the downside
         
     | 
| 
      
 19 
     | 
    
         
            +
            # of increasing the boot-up time by auto-requiring all files in the support
         
     | 
| 
      
 20 
     | 
    
         
            +
            # directory. Alternatively, in the individual `*_spec.rb` files, manually
         
     | 
| 
      
 21 
     | 
    
         
            +
            # require only the support files necessary.
         
     | 
| 
      
 22 
     | 
    
         
            +
            #
         
     | 
| 
      
 23 
     | 
    
         
            +
            # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            # Checks for pending migrations and applies them before tests are run.
         
     | 
| 
      
 26 
     | 
    
         
            +
            # If you are not using ActiveRecord, you can remove these lines.
         
     | 
| 
      
 27 
     | 
    
         
            +
            begin
         
     | 
| 
      
 28 
     | 
    
         
            +
              ActiveRecord::Migration.maintain_test_schema!
         
     | 
| 
      
 29 
     | 
    
         
            +
            rescue ActiveRecord::PendingMigrationError => e
         
     | 
| 
      
 30 
     | 
    
         
            +
              puts e.to_s.strip
         
     | 
| 
      
 31 
     | 
    
         
            +
              exit 1
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
      
 33 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 34 
     | 
    
         
            +
              # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
         
     | 
| 
      
 35 
     | 
    
         
            +
              config.fixture_path = "#{::Rails.root}/spec/fixtures"
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              # If you're not using ActiveRecord, or you'd prefer not to run each of your
         
     | 
| 
      
 38 
     | 
    
         
            +
              # examples within a transaction, remove the following line or assign false
         
     | 
| 
      
 39 
     | 
    
         
            +
              # instead of true.
         
     | 
| 
      
 40 
     | 
    
         
            +
              config.use_transactional_fixtures = true
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # RSpec Rails can automatically mix in different behaviours to your tests
         
     | 
| 
      
 43 
     | 
    
         
            +
              # based on their file location, for example enabling you to call `get` and
         
     | 
| 
      
 44 
     | 
    
         
            +
              # `post` in specs under `spec/controllers`.
         
     | 
| 
      
 45 
     | 
    
         
            +
              #
         
     | 
| 
      
 46 
     | 
    
         
            +
              # You can disable this behaviour by removing the line below, and instead
         
     | 
| 
      
 47 
     | 
    
         
            +
              # explicitly tag your specs with their type, e.g.:
         
     | 
| 
      
 48 
     | 
    
         
            +
              #
         
     | 
| 
      
 49 
     | 
    
         
            +
              #     RSpec.describe UsersController, :type => :controller do
         
     | 
| 
      
 50 
     | 
    
         
            +
              #       # ...
         
     | 
| 
      
 51 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 52 
     | 
    
         
            +
              #
         
     | 
| 
      
 53 
     | 
    
         
            +
              # The different available types are documented in the features, such as in
         
     | 
| 
      
 54 
     | 
    
         
            +
              # https://relishapp.com/rspec/rspec-rails/docs
         
     | 
| 
      
 55 
     | 
    
         
            +
              config.infer_spec_type_from_file_location!
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              # Filter lines from Rails gems in backtraces.
         
     | 
| 
      
 58 
     | 
    
         
            +
              config.filter_rails_from_backtrace!
         
     | 
| 
      
 59 
     | 
    
         
            +
              # arbitrary gems may also be filtered via:
         
     | 
| 
      
 60 
     | 
    
         
            +
              # config.filter_gems_from_backtrace("gem name")
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,97 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rails_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe 'Requesting Tree resources', :type => :request  do
         
     | 
| 
      
 4 
     | 
    
         
            +
              before(:each) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                user = User.create(name: 'Michel')
         
     | 
| 
      
 6 
     | 
    
         
            +
                tree = Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              after(:each) do
         
     | 
| 
      
 10 
     | 
    
         
            +
                User.destroy_all
         
     | 
| 
      
 11 
     | 
    
         
            +
                Tree.destroy_all
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              before(:each) do
         
     | 
| 
      
 15 
     | 
    
         
            +
                allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
         
     | 
| 
      
 16 
     | 
    
         
            +
                allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
         
     | 
| 
      
 17 
     | 
    
         
            +
                allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { true }
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              headers = {
         
     | 
| 
      
 23 
     | 
    
         
            +
                'Accept' => 'application/json',
         
     | 
| 
      
 24 
     | 
    
         
            +
                'Content-Type' => 'application/json',
         
     | 
| 
      
 25 
     | 
    
         
            +
                'Authorization' => 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOiIxODQ5ODc4ODYzIiwiZGF0YSI6eyJpZCI6IjM4IiwidHlwZSI6InVzZXJzIiwiZGF0YSI6eyJlbWFpbCI6Im1pY2hhZWwua2Vsc29AdGhhdDcwLnNob3ciLCJmaXJzdF9uYW1lIjoiTWljaGFlbCIsImxhc3RfbmFtZSI6IktlbHNvIiwidGVhbXMiOiJPcGVyYXRpb25zIn0sInJlbGF0aW9uc2hpcHMiOnsicmVuZGVyaW5ncyI6eyJkYXRhIjpbeyJ0eXBlIjoicmVuZGVyaW5ncyIsImlkIjoxNn1dfX19fQ.U4Mxi0tq0Ce7y5FRXP47McNPRPhUx37LznQ5E3mJIp4'
         
     | 
| 
      
 26 
     | 
    
         
            +
              }
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              describe 'index' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                describe 'without any filter' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  params = {
         
     | 
| 
      
 31 
     | 
    
         
            +
                    fields: { 'Tree' => 'id,name' },
         
     | 
| 
      
 32 
     | 
    
         
            +
                    page: { 'number' => '1', 'size' => '10' },
         
     | 
| 
      
 33 
     | 
    
         
            +
                    searchExtended: '0',
         
     | 
| 
      
 34 
     | 
    
         
            +
                    sort: '-id',
         
     | 
| 
      
 35 
     | 
    
         
            +
                    timezone: 'Europe/Paris'
         
     | 
| 
      
 36 
     | 
    
         
            +
                  }
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  it 'should respond 200' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    get '/forest/Tree', params, headers
         
     | 
| 
      
 40 
     | 
    
         
            +
                    expect(response.status).to eq(200)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  it 'should respond the tree data' do
         
     | 
| 
      
 44 
     | 
    
         
            +
                    get '/forest/Tree', params, headers
         
     | 
| 
      
 45 
     | 
    
         
            +
                    expect(JSON.parse(response.body)).to eq({
         
     | 
| 
      
 46 
     | 
    
         
            +
                      "data" => [{
         
     | 
| 
      
 47 
     | 
    
         
            +
                        "type" => "Tree",
         
     | 
| 
      
 48 
     | 
    
         
            +
                        "id" => "1",
         
     | 
| 
      
 49 
     | 
    
         
            +
                        "attributes" => {
         
     | 
| 
      
 50 
     | 
    
         
            +
                          "id" => 1,
         
     | 
| 
      
 51 
     | 
    
         
            +
                          "name" => "Lemon Tree"
         
     | 
| 
      
 52 
     | 
    
         
            +
                        },
         
     | 
| 
      
 53 
     | 
    
         
            +
                        "links" => {
         
     | 
| 
      
 54 
     | 
    
         
            +
                          "self" => "/forest/tree/1"
         
     | 
| 
      
 55 
     | 
    
         
            +
                        }
         
     | 
| 
      
 56 
     | 
    
         
            +
                      }],
         
     | 
| 
      
 57 
     | 
    
         
            +
                      "included" => []
         
     | 
| 
      
 58 
     | 
    
         
            +
                    })
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                describe 'with a filter on an association that is not a displayed column' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  params = {
         
     | 
| 
      
 64 
     | 
    
         
            +
                    fields: { 'Tree' => 'id,name' },
         
     | 
| 
      
 65 
     | 
    
         
            +
                    filterType: 'and',
         
     | 
| 
      
 66 
     | 
    
         
            +
                    filter: { 'owner:id' => '$present' },
         
     | 
| 
      
 67 
     | 
    
         
            +
                    page: { 'number' => '1', 'size' => '10' },
         
     | 
| 
      
 68 
     | 
    
         
            +
                    searchExtended: '0',
         
     | 
| 
      
 69 
     | 
    
         
            +
                    sort: '-id',
         
     | 
| 
      
 70 
     | 
    
         
            +
                    timezone: 'Europe/Paris'
         
     | 
| 
      
 71 
     | 
    
         
            +
                  }
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  it 'should respond 200' do
         
     | 
| 
      
 74 
     | 
    
         
            +
                    get '/forest/Tree', params, headers
         
     | 
| 
      
 75 
     | 
    
         
            +
                    expect(response.status).to eq(200)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  it 'should respond the tree data' do
         
     | 
| 
      
 79 
     | 
    
         
            +
                    get '/forest/Tree', params, headers
         
     | 
| 
      
 80 
     | 
    
         
            +
                    expect(JSON.parse(response.body)).to eq({
         
     | 
| 
      
 81 
     | 
    
         
            +
                      "data" => [{
         
     | 
| 
      
 82 
     | 
    
         
            +
                        "type" => "Tree",
         
     | 
| 
      
 83 
     | 
    
         
            +
                        "id" => "1",
         
     | 
| 
      
 84 
     | 
    
         
            +
                        "attributes" => {
         
     | 
| 
      
 85 
     | 
    
         
            +
                          "id" => 1,
         
     | 
| 
      
 86 
     | 
    
         
            +
                          "name" => "Lemon Tree"
         
     | 
| 
      
 87 
     | 
    
         
            +
                        },
         
     | 
| 
      
 88 
     | 
    
         
            +
                        "links" => {
         
     | 
| 
      
 89 
     | 
    
         
            +
                          "self" => "/forest/tree/1"
         
     | 
| 
      
 90 
     | 
    
         
            +
                        }
         
     | 
| 
      
 91 
     | 
    
         
            +
                      }],
         
     | 
| 
      
 92 
     | 
    
         
            +
                      "included" => []
         
     | 
| 
      
 93 
     | 
    
         
            +
                    })
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
                end
         
     | 
| 
      
 96 
     | 
    
         
            +
              end
         
     | 
| 
      
 97 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,172 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ForestLiana
         
     | 
| 
      
 2 
     | 
    
         
            +
              describe ApimapSorter do
         
     | 
| 
      
 3 
     | 
    
         
            +
                describe 'apimap reordering' do
         
     | 
| 
      
 4 
     | 
    
         
            +
                  context 'on a disordered apimap' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                    apimap = {
         
     | 
| 
      
 6 
     | 
    
         
            +
                      'meta': {
         
     | 
| 
      
 7 
     | 
    
         
            +
                        'orm_version': '4.34.9',
         
     | 
| 
      
 8 
     | 
    
         
            +
                        'liana_version': '1.5.24',
         
     | 
| 
      
 9 
     | 
    
         
            +
                        'database_type': 'postgresql',
         
     | 
| 
      
 10 
     | 
    
         
            +
                        liana: 'forest-rails',
         
     | 
| 
      
 11 
     | 
    
         
            +
                      },
         
     | 
| 
      
 12 
     | 
    
         
            +
                      'data': [{
         
     | 
| 
      
 13 
     | 
    
         
            +
                        id: 'users',
         
     | 
| 
      
 14 
     | 
    
         
            +
                        type: 'collections',
         
     | 
| 
      
 15 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 16 
     | 
    
         
            +
                          fields: [
         
     | 
| 
      
 17 
     | 
    
         
            +
                            { field: 'id', type: 'Number' },
         
     | 
| 
      
 18 
     | 
    
         
            +
                            { field: 'name', type: 'String' },
         
     | 
| 
      
 19 
     | 
    
         
            +
                            { field: 'firstName', type: 'String' },
         
     | 
| 
      
 20 
     | 
    
         
            +
                            { field: 'lastName', type: 'String' },
         
     | 
| 
      
 21 
     | 
    
         
            +
                            { field: 'email', type: 'String' },
         
     | 
| 
      
 22 
     | 
    
         
            +
                            { field: 'url', type: 'String' },
         
     | 
| 
      
 23 
     | 
    
         
            +
                            { field: 'createdAt', type: 'Date' },
         
     | 
| 
      
 24 
     | 
    
         
            +
                            { field: 'updatedAt', type: 'Date' },
         
     | 
| 
      
 25 
     | 
    
         
            +
                          ],
         
     | 
| 
      
 26 
     | 
    
         
            +
                          name: 'users',
         
     | 
| 
      
 27 
     | 
    
         
            +
                        }
         
     | 
| 
      
 28 
     | 
    
         
            +
                      }, {
         
     | 
| 
      
 29 
     | 
    
         
            +
                        id: 'guests',
         
     | 
| 
      
 30 
     | 
    
         
            +
                        type: 'collections',
         
     | 
| 
      
 31 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 32 
     | 
    
         
            +
                          fields: [
         
     | 
| 
      
 33 
     | 
    
         
            +
                            { field: 'id', type: 'Number' },
         
     | 
| 
      
 34 
     | 
    
         
            +
                            { field: 'email', type: 'String' },
         
     | 
| 
      
 35 
     | 
    
         
            +
                            { field: 'createdAt', type: 'Date' },
         
     | 
| 
      
 36 
     | 
    
         
            +
                            { field: 'updatedAt', type: 'Date' },
         
     | 
| 
      
 37 
     | 
    
         
            +
                          ],
         
     | 
| 
      
 38 
     | 
    
         
            +
                          name: 'guests',
         
     | 
| 
      
 39 
     | 
    
         
            +
                        }
         
     | 
| 
      
 40 
     | 
    
         
            +
                      }, {
         
     | 
| 
      
 41 
     | 
    
         
            +
                        type: 'collections',
         
     | 
| 
      
 42 
     | 
    
         
            +
                        id: 'animals',
         
     | 
| 
      
 43 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 44 
     | 
    
         
            +
                          fields: [
         
     | 
| 
      
 45 
     | 
    
         
            +
                            { 'is-sortable': false, field: 'id', 'is-filterable': false,  type: 'Number' },
         
     | 
| 
      
 46 
     | 
    
         
            +
                            { type: 'Date', field: 'createdAt' },
         
     | 
| 
      
 47 
     | 
    
         
            +
                            { field: 'updatedAt', type: 'Date' },
         
     | 
| 
      
 48 
     | 
    
         
            +
                          ],
         
     | 
| 
      
 49 
     | 
    
         
            +
                          name: 'animals',
         
     | 
| 
      
 50 
     | 
    
         
            +
                          integration: 'close.io',
         
     | 
| 
      
 51 
     | 
    
         
            +
                          'is-virtual': true,
         
     | 
| 
      
 52 
     | 
    
         
            +
                        }
         
     | 
| 
      
 53 
     | 
    
         
            +
                      }],
         
     | 
| 
      
 54 
     | 
    
         
            +
                      'included': [{
         
     | 
| 
      
 55 
     | 
    
         
            +
                        id: 'users.Women',
         
     | 
| 
      
 56 
     | 
    
         
            +
                        type: 'segments',
         
     | 
| 
      
 57 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 58 
     | 
    
         
            +
                          name: 'Women'
         
     | 
| 
      
 59 
     | 
    
         
            +
                        }
         
     | 
| 
      
 60 
     | 
    
         
            +
                      }, {
         
     | 
| 
      
 61 
     | 
    
         
            +
                        id: 'users.import',
         
     | 
| 
      
 62 
     | 
    
         
            +
                        type: 'actions',
         
     | 
| 
      
 63 
     | 
    
         
            +
                        links: {
         
     | 
| 
      
 64 
     | 
    
         
            +
                          self: '/actions'
         
     | 
| 
      
 65 
     | 
    
         
            +
                        },
         
     | 
| 
      
 66 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 67 
     | 
    
         
            +
                          name: 'import',
         
     | 
| 
      
 68 
     | 
    
         
            +
                          fields: [{
         
     | 
| 
      
 69 
     | 
    
         
            +
                            isRequired: true,
         
     | 
| 
      
 70 
     | 
    
         
            +
                            type: 'Boolean',
         
     | 
| 
      
 71 
     | 
    
         
            +
                            field: 'Save',
         
     | 
| 
      
 72 
     | 
    
         
            +
                            description: 'save the import file if true.',
         
     | 
| 
      
 73 
     | 
    
         
            +
                            defaultValue: 'true'
         
     | 
| 
      
 74 
     | 
    
         
            +
                          }, {
         
     | 
| 
      
 75 
     | 
    
         
            +
                            type: 'File',
         
     | 
| 
      
 76 
     | 
    
         
            +
                            field: 'File'
         
     | 
| 
      
 77 
     | 
    
         
            +
                          }],
         
     | 
| 
      
 78 
     | 
    
         
            +
                          'http-method': nil
         
     | 
| 
      
 79 
     | 
    
         
            +
                        }
         
     | 
| 
      
 80 
     | 
    
         
            +
                      }, {
         
     | 
| 
      
 81 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 82 
     | 
    
         
            +
                          name: 'Men'
         
     | 
| 
      
 83 
     | 
    
         
            +
                        },
         
     | 
| 
      
 84 
     | 
    
         
            +
                        id: 'users.Men',
         
     | 
| 
      
 85 
     | 
    
         
            +
                        type: 'segments'
         
     | 
| 
      
 86 
     | 
    
         
            +
                      }, {
         
     | 
| 
      
 87 
     | 
    
         
            +
                        id: 'animals.ban',
         
     | 
| 
      
 88 
     | 
    
         
            +
                        type: 'actions',
         
     | 
| 
      
 89 
     | 
    
         
            +
                        links: {
         
     | 
| 
      
 90 
     | 
    
         
            +
                          self: '/actions'
         
     | 
| 
      
 91 
     | 
    
         
            +
                        },
         
     | 
| 
      
 92 
     | 
    
         
            +
                        attributes: {
         
     | 
| 
      
 93 
     | 
    
         
            +
                          name: 'import',
         
     | 
| 
      
 94 
     | 
    
         
            +
                          global: true,
         
     | 
| 
      
 95 
     | 
    
         
            +
                          download: nil,
         
     | 
| 
      
 96 
     | 
    
         
            +
                          endpoint: nil,
         
     | 
| 
      
 97 
     | 
    
         
            +
                          redirect: nil,
         
     | 
| 
      
 98 
     | 
    
         
            +
                          'http-method': nil
         
     | 
| 
      
 99 
     | 
    
         
            +
                        }
         
     | 
| 
      
 100 
     | 
    
         
            +
                      }]
         
     | 
| 
      
 101 
     | 
    
         
            +
                    }
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    apimap = ActiveSupport::JSON.encode(apimap)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    apimap = ActiveSupport::JSON.decode(apimap)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    apimap_sorted = ApimapSorter.new(apimap).perform
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    it 'should sort the apimap sections' do
         
     | 
| 
      
 108 
     | 
    
         
            +
                      expect(apimap_sorted.keys).to eq(['data', 'included', 'meta'])
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    it 'should sort the data collections' do
         
     | 
| 
      
 112 
     | 
    
         
            +
                      expect(apimap_sorted['data'].map { |collection| collection['id'] }).to eq(
         
     | 
| 
      
 113 
     | 
    
         
            +
                        ['animals', 'guests', 'users'])
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                    it 'should sort the data collection values' do
         
     | 
| 
      
 117 
     | 
    
         
            +
                      expect(apimap_sorted['data'][0].keys).to eq(['type', 'id', 'attributes'])
         
     | 
| 
      
 118 
     | 
    
         
            +
                      expect(apimap_sorted['data'][1].keys).to eq(['type', 'id', 'attributes'])
         
     | 
| 
      
 119 
     | 
    
         
            +
                      expect(apimap_sorted['data'][2].keys).to eq(['type', 'id', 'attributes'])
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    it 'should sort the data collections attributes values' do
         
     | 
| 
      
 123 
     | 
    
         
            +
                      expect(apimap_sorted['data'][0]['attributes'].keys).to eq(['name', 'integration', 'is-virtual', 'fields'])
         
     | 
| 
      
 124 
     | 
    
         
            +
                      expect(apimap_sorted['data'][1]['attributes'].keys).to eq(['name', 'fields'])
         
     | 
| 
      
 125 
     | 
    
         
            +
                      expect(apimap_sorted['data'][2]['attributes'].keys).to eq(['name', 'fields'])
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                    it 'should sort the data collections attributes fields by name' do
         
     | 
| 
      
 129 
     | 
    
         
            +
                      expect(apimap_sorted['data'][0]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'id', 'updatedAt'])
         
     | 
| 
      
 130 
     | 
    
         
            +
                      expect(apimap_sorted['data'][1]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'email', 'id', 'updatedAt'])
         
     | 
| 
      
 131 
     | 
    
         
            +
                      expect(apimap_sorted['data'][2]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'email', 'firstName', 'id', 'lastName', 'name', 'updatedAt', 'url'])
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    it 'should sort the data collections attributes fields values' do
         
     | 
| 
      
 135 
     | 
    
         
            +
                      expect(apimap_sorted['data'][0]['attributes']['fields'][1].keys).to eq(['field', 'type', 'is-filterable', 'is-sortable'])
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                    it 'should sort the included actions and segments objects' do
         
     | 
| 
      
 139 
     | 
    
         
            +
                      expect(apimap_sorted['included'].map { |object| object['id'] }).to eq(
         
     | 
| 
      
 140 
     | 
    
         
            +
                        ['animals.ban', 'users.import', 'users.Men', 'users.Women'])
         
     | 
| 
      
 141 
     | 
    
         
            +
                    end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                    it 'should sort the included actions and segments objects values' do
         
     | 
| 
      
 144 
     | 
    
         
            +
                      expect(apimap_sorted['included'][0].keys).to eq(['type', 'id', 'attributes', 'links'])
         
     | 
| 
      
 145 
     | 
    
         
            +
                      expect(apimap_sorted['included'][1].keys).to eq(['type', 'id', 'attributes', 'links'])
         
     | 
| 
      
 146 
     | 
    
         
            +
                      expect(apimap_sorted['included'][2].keys).to eq(['type', 'id', 'attributes'])
         
     | 
| 
      
 147 
     | 
    
         
            +
                      expect(apimap_sorted['included'][3].keys).to eq(['type', 'id', 'attributes'])
         
     | 
| 
      
 148 
     | 
    
         
            +
                    end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    it 'should sort the included actions and segments objects attributes values' do
         
     | 
| 
      
 151 
     | 
    
         
            +
                      expect(apimap_sorted['included'][0]['attributes'].keys).to eq(['name', 'download', 'endpoint', 'global', 'http-method', 'redirect'])
         
     | 
| 
      
 152 
     | 
    
         
            +
                      expect(apimap_sorted['included'][1]['attributes'].keys).to eq(['name', 'http-method', 'fields'])
         
     | 
| 
      
 153 
     | 
    
         
            +
                      expect(apimap_sorted['included'][2]['attributes'].keys).to eq(['name'])
         
     | 
| 
      
 154 
     | 
    
         
            +
                      expect(apimap_sorted['included'][3]['attributes'].keys).to eq(['name'])
         
     | 
| 
      
 155 
     | 
    
         
            +
                    end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                    it 'should sort the included action attributes fields by name' do
         
     | 
| 
      
 158 
     | 
    
         
            +
                      expect(apimap_sorted['included'][1]['attributes']['fields'].map { |field| field['field'] }).to eq(['File', 'Save'])
         
     | 
| 
      
 159 
     | 
    
         
            +
                    end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                    it 'should sort the included action fields values' do
         
     | 
| 
      
 162 
     | 
    
         
            +
                      expect(apimap_sorted['included'][1]['attributes']['fields'][1].keys).to eq(['field', 'type', 'defaultValue', 'description', 'isRequired'])
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                    it 'should sort the meta values' do
         
     | 
| 
      
 166 
     | 
    
         
            +
                      expect(apimap_sorted['meta'].keys).to eq(
         
     | 
| 
      
 167 
     | 
    
         
            +
                        ['database_type', 'liana', 'liana_version', 'orm_version'])
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
                  end
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,203 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module ForestLiana
         
     | 
| 
      
 2 
     | 
    
         
            +
              describe IpWhitelistChecker do
         
     | 
| 
      
 3 
     | 
    
         
            +
                describe 'Check is_ip_matches_rule function' do
         
     | 
| 
      
 4 
     | 
    
         
            +
                  describe 'with IP "90.88.0.1" and "90.88.0.2"' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                    it 'should return false' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 7 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 8 
     | 
    
         
            +
                        'ip' => '90.88.0.1',
         
     | 
| 
      
 9 
     | 
    
         
            +
                      }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.2', rule)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                      expect(is_matching).to eq(false)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  describe 'with IP "::1" and "aaaa"' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    it 'should raise an "ArgumentError" exception with "Unknown IP Address aaaa" message' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 20 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 21 
     | 
    
         
            +
                        'ip' => '::1',
         
     | 
| 
      
 22 
     | 
    
         
            +
                      }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      expect {
         
     | 
| 
      
 25 
     | 
    
         
            +
                        IpWhitelistChecker.is_ip_matches_rule('aaaa', rule)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      }.to raise_error(ArgumentError, 'Unknown IP Address aaaa')
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  describe 'with IP "90.88.0.1" and "::1"' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    it 'should return false' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 33 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 34 
     | 
    
         
            +
                        'ip' => '90.88.0.1',
         
     | 
| 
      
 35 
     | 
    
         
            +
                      }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                      expect(is_matching).to eq(false)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  describe 'with IP "::1" and "::1"' do
         
     | 
| 
      
 44 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 46 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 47 
     | 
    
         
            +
                        'ip' => '::1',
         
     | 
| 
      
 48 
     | 
    
         
            +
                      }
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  describe 'with IP "90.88.0.1" and "90.88.0.1"' do
         
     | 
| 
      
 57 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 59 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 60 
     | 
    
         
            +
                        'ip' => '90.88.0.1',
         
     | 
| 
      
 61 
     | 
    
         
            +
                      }
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.1', rule)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  describe 'with IP "90.88.0.0" and "90.88.0.0"' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 71 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 72 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 73 
     | 
    
         
            +
                        'ip' => '90.88.0.0',
         
     | 
| 
      
 74 
     | 
    
         
            +
                      }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.0', rule)
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  describe 'with IP "127.0.0.1" and "::1"' do
         
     | 
| 
      
 83 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 84 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 85 
     | 
    
         
            +
                        'type' => 0,
         
     | 
| 
      
 86 
     | 
    
         
            +
                        'ip' => '127.0.0.1',
         
     | 
| 
      
 87 
     | 
    
         
            +
                      }
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  describe 'with range "90.88.0.0 - 90.88.255.255' do
         
     | 
| 
      
 96 
     | 
    
         
            +
                    rule = {
         
     | 
| 
      
 97 
     | 
    
         
            +
                      'type' => 1,
         
     | 
| 
      
 98 
     | 
    
         
            +
                      'ip_minimum' => '90.88.0.0',
         
     | 
| 
      
 99 
     | 
    
         
            +
                      'ip_maximum' => '90.88.255.255',
         
     | 
| 
      
 100 
     | 
    
         
            +
                    }
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    describe 'with IP "90.89.0.1"' do
         
     | 
| 
      
 103 
     | 
    
         
            +
                      it 'should return false' do
         
     | 
| 
      
 104 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.89.0.1', rule)
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                        expect(is_matching).to eq(false)
         
     | 
| 
      
 107 
     | 
    
         
            +
                      end
         
     | 
| 
      
 108 
     | 
    
         
            +
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    describe 'with IP "::ffff:90.89.0.1"' do
         
     | 
| 
      
 111 
     | 
    
         
            +
                      it 'should return false' do
         
     | 
| 
      
 112 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('::ffff:90.89.0.1', rule)
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                        expect(is_matching).to eq(false)
         
     | 
| 
      
 115 
     | 
    
         
            +
                      end
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    describe 'with IP "90.88.118.79"' do
         
     | 
| 
      
 119 
     | 
    
         
            +
                      it 'should return false' do
         
     | 
| 
      
 120 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                        expect(is_matching).to eq(true)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      end
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                  describe 'with range "90.88.0.1 - 90.88.255.255" and IP "90.88.118.79"' do
         
     | 
| 
      
 128 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 129 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 130 
     | 
    
         
            +
                        'type' => 1,
         
     | 
| 
      
 131 
     | 
    
         
            +
                        'ip_minimum' => '90.88.0.1',
         
     | 
| 
      
 132 
     | 
    
         
            +
                        'ip_maximum' => '90.88.255.255',
         
     | 
| 
      
 133 
     | 
    
         
            +
                      }
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  describe 'with range "90.88.0.1 - 90.88.254.254" and IP "90.88.118.79"' do
         
     | 
| 
      
 142 
     | 
    
         
            +
                    it 'should return true' do
         
     | 
| 
      
 143 
     | 
    
         
            +
                      rule = {
         
     | 
| 
      
 144 
     | 
    
         
            +
                        'type' => 1,
         
     | 
| 
      
 145 
     | 
    
         
            +
                        'ip_minimum' => '90.88.0.1',
         
     | 
| 
      
 146 
     | 
    
         
            +
                        'ip_maximum' => '90.88.254.254',
         
     | 
| 
      
 147 
     | 
    
         
            +
                      }
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                      expect(is_matching).to eq(true)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                  describe 'with subnet "90.88.0.0/24"' do
         
     | 
| 
      
 156 
     | 
    
         
            +
                    rule = {
         
     | 
| 
      
 157 
     | 
    
         
            +
                      'type' => 2,
         
     | 
| 
      
 158 
     | 
    
         
            +
                      'range' => '90.88.0.0/24',
         
     | 
| 
      
 159 
     | 
    
         
            +
                    }
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                    describe 'with IP "90.88.0.1"' do
         
     | 
| 
      
 162 
     | 
    
         
            +
                      it 'should return true' do
         
     | 
| 
      
 163 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.1', rule)
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                        expect(is_matching).to eq(true)
         
     | 
| 
      
 166 
     | 
    
         
            +
                      end
         
     | 
| 
      
 167 
     | 
    
         
            +
                    end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                    describe 'with IP "90.88.0.0"' do
         
     | 
| 
      
 170 
     | 
    
         
            +
                      it 'should return true' do
         
     | 
| 
      
 171 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.0', rule)
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                        expect(is_matching).to eq(true)
         
     | 
| 
      
 174 
     | 
    
         
            +
                      end
         
     | 
| 
      
 175 
     | 
    
         
            +
                    end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                    describe 'with IP "90.88.0.254"' do
         
     | 
| 
      
 178 
     | 
    
         
            +
                      it 'should return true' do
         
     | 
| 
      
 179 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.254', rule)
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                        expect(is_matching).to eq(true)
         
     | 
| 
      
 182 
     | 
    
         
            +
                      end
         
     | 
| 
      
 183 
     | 
    
         
            +
                    end
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                    describe 'with IP "90.88.1.1"' do
         
     | 
| 
      
 186 
     | 
    
         
            +
                      it 'should return true' do
         
     | 
| 
      
 187 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.1.1', rule)
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                        expect(is_matching).to eq(false)
         
     | 
| 
      
 190 
     | 
    
         
            +
                      end
         
     | 
| 
      
 191 
     | 
    
         
            +
                    end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                    describe 'with IP "::1"' do
         
     | 
| 
      
 194 
     | 
    
         
            +
                      it 'should return true' do
         
     | 
| 
      
 195 
     | 
    
         
            +
                        is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                        expect(is_matching).to eq(false)
         
     | 
| 
      
 198 
     | 
    
         
            +
                      end
         
     | 
| 
      
 199 
     | 
    
         
            +
                    end
         
     | 
| 
      
 200 
     | 
    
         
            +
                  end
         
     | 
| 
      
 201 
     | 
    
         
            +
                end
         
     | 
| 
      
 202 
     | 
    
         
            +
              end
         
     | 
| 
      
 203 
     | 
    
         
            +
            end
         
     |