From a16dc4d7208943311137558f0d8e97f9be6e0bbc Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:28:58 +0100 Subject: [PATCH 01/17] Move ability decorator specs to specific file --- spec/models/spree/{ability_spec.rb => ability_decorator_spec.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/models/spree/{ability_spec.rb => ability_decorator_spec.rb} (100%) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_decorator_spec.rb similarity index 100% rename from spec/models/spree/ability_spec.rb rename to spec/models/spree/ability_decorator_spec.rb From c00c03737edde766dafd96ad15270a448dbd91ba Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:29:49 +0100 Subject: [PATCH 02/17] Bring user and ability related files from spree_core --- app/models/spree/ability.rb | 73 ++++++++ spec/models/spree/ability_spec.rb | 265 ++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 app/models/spree/ability.rb create mode 100644 spec/models/spree/ability_spec.rb diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb new file mode 100644 index 0000000000..f29dea39e1 --- /dev/null +++ b/app/models/spree/ability.rb @@ -0,0 +1,73 @@ +# Implementation class for Cancan gem. Instead of overriding this class, consider adding new permissions +# using the special +register_ability+ method which allows extensions to add their own abilities. +# +# See http://github.com/ryanb/cancan for more details on cancan. +require 'cancan' + +module Spree + class Ability + include CanCan::Ability + + class_attribute :abilities + self.abilities = Set.new + + # Allows us to go beyond the standard cancan initialize method which makes it difficult for engines to + # modify the default +Ability+ of an application. The +ability+ argument must be a class that includes + # the +CanCan::Ability+ module. The registered ability should behave properly as a stand-alone class + # and therefore should be easy to test in isolation. + def self.register_ability(ability) + self.abilities.add(ability) + end + + def self.remove_ability(ability) + self.abilities.delete(ability) + end + + def initialize(user) + self.clear_aliased_actions + + # override cancan default aliasing (we don't want to differentiate between read and index) + alias_action :delete, to: :destroy + alias_action :edit, to: :update + alias_action :new, to: :create + alias_action :new_action, to: :create + alias_action :show, to: :read + + user ||= Spree.user_class.new + + if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin') + can :manage, :all + else + can [:index, :read], Country + can [:index, :read], OptionType + can [:index, :read], OptionValue + can :create, Order + can :read, Order do |order, token| + order.user == user || order.token && token == order.token + end + can :update, Order do |order, token| + order.user == user || order.token && token == order.token + end + can [:index, :read], Product + can [:index, :read], ProductProperty + can [:index, :read], Property + can :create, Spree.user_class + can [:read, :update, :destroy], Spree.user_class, id: user.id + can [:index, :read], State + can [:index, :read], StockItem + can [:index, :read], StockLocation + can [:index, :read], StockMovement + can [:index, :read], Taxon + can [:index, :read], Taxonomy + can [:index, :read], Variant + can [:index, :read], Zone + end + + # Include any abilities registered by extensions, etc. + Ability.abilities.each do |clazz| + ability = clazz.send(:new, user) + @rules = rules + ability.send(:rules) + end + end + end +end diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb new file mode 100644 index 0000000000..2ee7e0d613 --- /dev/null +++ b/spec/models/spree/ability_spec.rb @@ -0,0 +1,265 @@ +require 'spec_helper' +require 'cancan/matchers' +require 'spree/testing_support/ability_helpers' +require 'spree/testing_support/bar_ability' + +# Fake ability for testing registration of additional abilities +class FooAbility + include CanCan::Ability + + def initialize(user) + # allow anyone to perform index on Order + can :index, Spree::Order + # allow anyone to update an Order with id of 1 + can :update, Spree::Order do |order| + order.id == 1 + end + end +end + +describe Spree::Ability do + let(:user) { create(:user) } + let(:ability) { Spree::Ability.new(user) } + let(:token) { nil } + + before do + user.spree_roles.clear + end + + TOKEN = 'token123' + + after(:each) { + Spree::Ability.abilities = Set.new + user.spree_roles = [] + } + + context 'register_ability' do + it 'should add the ability to the list of abilties' do + Spree::Ability.register_ability(FooAbility) + Spree::Ability.new(user).abilities.should_not be_empty + end + + it 'should apply the registered abilities permissions' do + Spree::Ability.register_ability(FooAbility) + Spree::Ability.new(user).can?(:update, mock_model(Spree::Order, :id => 1)).should be_true + end + end + + context 'for general resource' do + let(:resource) { Object.new } + + context 'with admin user' do + before(:each) { user.stub(:has_spree_role?).and_return(true) } + it_should_behave_like 'access granted' + it_should_behave_like 'index allowed' + end + + context 'with customer' do + it_should_behave_like 'access denied' + it_should_behave_like 'no index allowed' + end + end + + context 'for admin protected resources' do + let(:resource) { Object.new } + let(:resource_shipment) { Spree::Shipment.new } + let(:resource_product) { Spree::Product.new } + let(:resource_user) { Spree.user_class.new } + let(:resource_order) { Spree::Order.new } + let(:fakedispatch_user) { Spree.user_class.new } + let(:fakedispatch_ability) { Spree::Ability.new(fakedispatch_user) } + + context 'with admin user' do + it 'should be able to admin' do + user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') + ability.should be_able_to :admin, resource + ability.should be_able_to :index, resource_order + ability.should be_able_to :show, resource_product + ability.should be_able_to :create, resource_user + end + end + + context 'with fakedispatch user' do + it 'should be able to admin on the order and shipment pages' do + user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') + + Spree::Ability.register_ability(BarAbility) + + ability.should_not be_able_to :admin, resource + + ability.should be_able_to :admin, resource_order + ability.should be_able_to :index, resource_order + ability.should_not be_able_to :update, resource_order + # ability.should_not be_able_to :create, resource_order # Fails + + ability.should be_able_to :admin, resource_shipment + ability.should be_able_to :index, resource_shipment + ability.should be_able_to :create, resource_shipment + + ability.should_not be_able_to :admin, resource_product + ability.should_not be_able_to :update, resource_product + # ability.should_not be_able_to :show, resource_product # Fails + + ability.should_not be_able_to :admin, resource_user + ability.should_not be_able_to :update, resource_user + ability.should be_able_to :update, user + # ability.should_not be_able_to :create, resource_user # Fails + # It can create new users if is has access to the :admin, User!! + + # TODO change the Ability class so only users and customers get the extra premissions? + + Spree::Ability.remove_ability(BarAbility) + end + end + + context 'with customer' do + it 'should not be able to admin' do + ability.should_not be_able_to :admin, resource + ability.should_not be_able_to :admin, resource_order + ability.should_not be_able_to :admin, resource_product + ability.should_not be_able_to :admin, resource_user + end + end + end + + context 'as Guest User' do + + context 'for Country' do + let(:resource) { Spree::Country.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for OptionType' do + let(:resource) { Spree::OptionType.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for OptionValue' do + let(:resource) { Spree::OptionType.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for Order' do + let(:resource) { Spree::Order.new } + + context 'requested by same user' do + before(:each) { resource.user = user } + it_should_behave_like 'access granted' + it_should_behave_like 'no index allowed' + end + + context 'requested by other user' do + before(:each) { resource.user = Spree.user_class.new } + it_should_behave_like 'create only' + end + + context 'requested with proper token' do + let(:token) { 'TOKEN123' } + before(:each) { resource.stub :token => 'TOKEN123' } + it_should_behave_like 'access granted' + it_should_behave_like 'no index allowed' + end + + context 'requested with inproper token' do + let(:token) { 'FAIL' } + before(:each) { resource.stub :token => 'TOKEN123' } + it_should_behave_like 'create only' + end + end + + context 'for Product' do + let(:resource) { Spree::Product.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for ProductProperty' do + let(:resource) { Spree::Product.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for Property' do + let(:resource) { Spree::Product.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for State' do + let(:resource) { Spree::State.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for StockItem' do + let(:resource) { Spree::StockItem.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for StockLocation' do + let(:resource) { Spree::StockLocation.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for StockMovement' do + let(:resource) { Spree::StockMovement.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for Taxons' do + let(:resource) { Spree::Taxon.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for Taxonomy' do + let(:resource) { Spree::Taxonomy.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for User' do + context 'requested by same user' do + let(:resource) { user } + it_should_behave_like 'access granted' + it_should_behave_like 'no index allowed' + end + context 'requested by other user' do + let(:resource) { Spree.user_class.new } + it_should_behave_like 'create only' + end + end + + context 'for Variant' do + let(:resource) { Spree::Variant.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + + context 'for Zone' do + let(:resource) { Spree::Zone.new } + context 'requested by any user' do + it_should_behave_like 'read only' + end + end + end +end From 051ee0fd140c579719263201d9c554580f4978b7 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:30:59 +0100 Subject: [PATCH 03/17] Run rubocop -a --- app/models/spree/ability.rb | 8 +++++--- spec/models/spree/ability_spec.rb | 11 +++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index f29dea39e1..0cf919176c 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Implementation class for Cancan gem. Instead of overriding this class, consider adding new permissions # using the special +register_ability+ method which allows extensions to add their own abilities. # @@ -16,15 +18,15 @@ module Spree # the +CanCan::Ability+ module. The registered ability should behave properly as a stand-alone class # and therefore should be easy to test in isolation. def self.register_ability(ability) - self.abilities.add(ability) + abilities.add(ability) end def self.remove_ability(ability) - self.abilities.delete(ability) + abilities.delete(ability) end def initialize(user) - self.clear_aliased_actions + clear_aliased_actions # override cancan default aliasing (we don't want to differentiate between read and index) alias_action :delete, to: :destroy diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 2ee7e0d613..1bd8e71aaa 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -7,7 +7,7 @@ require 'spree/testing_support/bar_ability' class FooAbility include CanCan::Ability - def initialize(user) + def initialize(_user) # allow anyone to perform index on Order can :index, Spree::Order # allow anyone to update an Order with id of 1 @@ -26,7 +26,7 @@ describe Spree::Ability do user.spree_roles.clear end - TOKEN = 'token123' + TOKEN = 'token123'.freeze after(:each) { Spree::Ability.abilities = Set.new @@ -41,7 +41,7 @@ describe Spree::Ability do it 'should apply the registered abilities permissions' do Spree::Ability.register_ability(FooAbility) - Spree::Ability.new(user).can?(:update, mock_model(Spree::Order, :id => 1)).should be_true + Spree::Ability.new(user).can?(:update, mock_model(Spree::Order, id: 1)).should be_true end end @@ -123,7 +123,6 @@ describe Spree::Ability do end context 'as Guest User' do - context 'for Country' do let(:resource) { Spree::Country.new } context 'requested by any user' do @@ -161,14 +160,14 @@ describe Spree::Ability do context 'requested with proper token' do let(:token) { 'TOKEN123' } - before(:each) { resource.stub :token => 'TOKEN123' } + before(:each) { resource.stub token: 'TOKEN123' } it_should_behave_like 'access granted' it_should_behave_like 'no index allowed' end context 'requested with inproper token' do let(:token) { 'FAIL' } - before(:each) { resource.stub :token => 'TOKEN123' } + before(:each) { resource.stub token: 'TOKEN123' } it_should_behave_like 'create only' end end From 37c7d254e10926f1ab593073396fd8c15eeae3df Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:33:30 +0100 Subject: [PATCH 04/17] Fix rubocop issues --- app/models/spree/ability.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index 0cf919176c..25aee521fd 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true -# Implementation class for Cancan gem. Instead of overriding this class, consider adding new permissions +# Implementation class for Cancan gem. +# Instead of overriding this class, consider adding new permissions # using the special +register_ability+ method which allows extensions to add their own abilities. # # See http://github.com/ryanb/cancan for more details on cancan. @@ -13,10 +14,11 @@ module Spree class_attribute :abilities self.abilities = Set.new - # Allows us to go beyond the standard cancan initialize method which makes it difficult for engines to - # modify the default +Ability+ of an application. The +ability+ argument must be a class that includes - # the +CanCan::Ability+ module. The registered ability should behave properly as a stand-alone class - # and therefore should be easy to test in isolation. + # Allows us to go beyond the standard cancan initialize method + # which makes it difficult for engines to modify the default +Ability+ of an application. + # The +ability+ argument must be a class that includes the +CanCan::Ability+ module. + # The registered ability should behave properly as a stand-alone class + # and therefore should be easy to test in isolation. def self.register_ability(ability) abilities.add(ability) end @@ -67,8 +69,8 @@ module Spree # Include any abilities registered by extensions, etc. Ability.abilities.each do |clazz| - ability = clazz.send(:new, user) - @rules = rules + ability.send(:rules) + ability = clazz.__send__(:new, user) + @rules = rules + ability.__send__(:rules) end end end From 895ab62ba9513662c13db3692b44c20bfe944125 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:41:10 +0100 Subject: [PATCH 05/17] Bring ability helpers from spree_core and fix ability_spec --- spec/models/spree/ability_spec.rb | 50 +++++++------- spec/support/ability_helpers.rb | 107 ++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 spec/support/ability_helpers.rb diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 1bd8e71aaa..67bb647b17 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' require 'cancan/matchers' -require 'spree/testing_support/ability_helpers' +require 'support/ability_helpers' require 'spree/testing_support/bar_ability' # Fake ability for testing registration of additional abilities @@ -36,12 +36,12 @@ describe Spree::Ability do context 'register_ability' do it 'should add the ability to the list of abilties' do Spree::Ability.register_ability(FooAbility) - Spree::Ability.new(user).abilities.should_not be_empty + expect(Spree::Ability.new(user).abilities).to_not be_empty end it 'should apply the registered abilities permissions' do Spree::Ability.register_ability(FooAbility) - Spree::Ability.new(user).can?(:update, mock_model(Spree::Order, id: 1)).should be_true + expect(Spree::Ability.new(user).can?(:update, build(:order, id: 1))).to be_truthy end end @@ -72,10 +72,10 @@ describe Spree::Ability do context 'with admin user' do it 'should be able to admin' do user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') - ability.should be_able_to :admin, resource - ability.should be_able_to :index, resource_order - ability.should be_able_to :show, resource_product - ability.should be_able_to :create, resource_user + expect(ability).to be_able_to :admin, resource + expect(ability).to be_able_to :index, resource_order + expect(ability).to be_able_to :show, resource_product + expect(ability).to be_able_to :create, resource_user end end @@ -85,25 +85,23 @@ describe Spree::Ability do Spree::Ability.register_ability(BarAbility) - ability.should_not be_able_to :admin, resource + expect(ability).to_not be_able_to :admin, resource - ability.should be_able_to :admin, resource_order - ability.should be_able_to :index, resource_order - ability.should_not be_able_to :update, resource_order - # ability.should_not be_able_to :create, resource_order # Fails + expect(ability).to be_able_to :admin, resource_order + expect(ability).to be_able_to :index, resource_order + expect(ability).to_not be_able_to :update, resource_order - ability.should be_able_to :admin, resource_shipment - ability.should be_able_to :index, resource_shipment - ability.should be_able_to :create, resource_shipment + expect(ability).to be_able_to :admin, resource_shipment + expect(ability).to be_able_to :index, resource_shipment + expect(ability).to be_able_to :create, resource_shipment - ability.should_not be_able_to :admin, resource_product - ability.should_not be_able_to :update, resource_product - # ability.should_not be_able_to :show, resource_product # Fails + expect(ability).to_not be_able_to :admin, resource_product + expect(ability).to_not be_able_to :update, resource_product + + expect(ability).to_not be_able_to :admin, resource_user + expect(ability).to_not be_able_to :update, resource_user + expect(ability).to be_able_to :update, user - ability.should_not be_able_to :admin, resource_user - ability.should_not be_able_to :update, resource_user - ability.should be_able_to :update, user - # ability.should_not be_able_to :create, resource_user # Fails # It can create new users if is has access to the :admin, User!! # TODO change the Ability class so only users and customers get the extra premissions? @@ -114,10 +112,10 @@ describe Spree::Ability do context 'with customer' do it 'should not be able to admin' do - ability.should_not be_able_to :admin, resource - ability.should_not be_able_to :admin, resource_order - ability.should_not be_able_to :admin, resource_product - ability.should_not be_able_to :admin, resource_user + expect(ability).to_not be_able_to :admin, resource + expect(ability).to_not be_able_to :admin, resource_order + expect(ability).to_not be_able_to :admin, resource_product + expect(ability).to_not be_able_to :admin, resource_user end end end diff --git a/spec/support/ability_helpers.rb b/spec/support/ability_helpers.rb new file mode 100644 index 0000000000..0d42bbf7c2 --- /dev/null +++ b/spec/support/ability_helpers.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +shared_examples_for 'access granted' do + it 'should allow read' do + expect(ability).to be_able_to(:read, resource, token) if token + expect(ability).to be_able_to(:read, resource) unless token + end + + it 'should allow create' do + expect(ability).to be_able_to(:create, resource, token) if token + expect(ability).to be_able_to(:create, resource) unless token + end + + it 'should allow update' do + expect(ability).to be_able_to(:update, resource, token) if token + expect(ability).to be_able_to(:update, resource) unless token + end +end + +shared_examples_for 'access denied' do + it 'should not allow read' do + expect(ability).to_not be_able_to(:read, resource) + end + + it 'should not allow create' do + expect(ability).to_not be_able_to(:create, resource) + end + + it 'should not allow update' do + expect(ability).to_not be_able_to(:update, resource) + end +end + +shared_examples_for 'admin granted' do + it 'should allow admin' do + expect(ability).to be_able_to(:admin, resource, token) if token + expect(ability).to be_able_to(:admin, resource) unless token + end +end + +shared_examples_for 'admin denied' do + it 'should not allow admin' do + expect(ability).to_not be_able_to(:admin, resource) + end +end + +shared_examples_for 'index allowed' do + it 'should allow index' do + expect(ability).to be_able_to(:index, resource) + end +end + +shared_examples_for 'no index allowed' do + it 'should not allow index' do + expect(ability).to_not be_able_to(:index, resource) + end +end + +shared_examples_for 'create only' do + it 'should allow create' do + expect(ability).to be_able_to(:create, resource) + end + + it 'should not allow read' do + expect(ability).to_not be_able_to(:read, resource) + end + + it 'should not allow update' do + expect(ability).to_not be_able_to(:update, resource) + end + + it 'should not allow index' do + expect(ability).to_not be_able_to(:index, resource) + end +end + +shared_examples_for 'read only' do + it 'should not allow create' do + expect(ability).to_not be_able_to(:create, resource) + end + + it 'should not allow update' do + expect(ability).to_not be_able_to(:update, resource) + end + + it 'should allow index' do + expect(ability).to be_able_to(:index, resource) + end +end + +shared_examples_for 'update only' do + it 'should not allow create' do + expect(ability).to_not be_able_to(:create, resource) + end + + it 'should not allow read' do + expect(ability).to_not be_able_to(:read, resource) + end + + it 'should allow update' do + expect(ability).to be_able_to(:update, resource) + end + + it 'should not allow index' do + expect(ability).to_not be_able_to(:index, resource) + end +end From 32649cb25a63cf4a6795c875b2ee889de0542d37 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 19 Aug 2020 04:43:11 +0100 Subject: [PATCH 06/17] Transpec ability_spec --- spec/models/spree/ability_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 67bb647b17..97a695cd1b 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -49,7 +49,7 @@ describe Spree::Ability do let(:resource) { Object.new } context 'with admin user' do - before(:each) { user.stub(:has_spree_role?).and_return(true) } + before(:each) { allow(user).to receive(:has_spree_role?).and_return(true) } it_should_behave_like 'access granted' it_should_behave_like 'index allowed' end @@ -158,14 +158,14 @@ describe Spree::Ability do context 'requested with proper token' do let(:token) { 'TOKEN123' } - before(:each) { resource.stub token: 'TOKEN123' } + before(:each) { allow(resource).to receive_messages token: 'TOKEN123' } it_should_behave_like 'access granted' it_should_behave_like 'no index allowed' end context 'requested with inproper token' do let(:token) { 'FAIL' } - before(:each) { resource.stub token: 'TOKEN123' } + before(:each) { allow(resource).to receive_messages token: 'TOKEN123' } it_should_behave_like 'create only' end end From 22eac6200c8e35abdb3c1d69e850742f0bfc1415 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Tue, 1 Sep 2020 21:48:05 +0100 Subject: [PATCH 07/17] Add needed fake ability --- spec/models/spree/ability_spec.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 97a695cd1b..5b64660e95 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' require 'cancan/matchers' require 'support/ability_helpers' -require 'spree/testing_support/bar_ability' # Fake ability for testing registration of additional abilities class FooAbility @@ -80,6 +79,17 @@ describe Spree::Ability do end context 'with fakedispatch user' do + class BarAbility + include CanCan::Ability + + def initialize(user) + user ||= Spree::User.new + return unless user.has_spree_role?('bar') + + can [:admin, :index, :show], Spree::Order + end + end + it 'should be able to admin on the order and shipment pages' do user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') From 405b31772613f1bd7c4ba1506245d596d5216fc3 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 4 Sep 2020 10:28:28 +0100 Subject: [PATCH 08/17] Merge ability and ability decorator --- app/models/spree/ability.rb | 327 +++++++++- app/models/spree/ability_decorator.rb | 313 --------- spec/models/spree/ability_decorator_spec.rb | 607 ----------------- spec/models/spree/ability_spec.rb | 685 +++++++++++++++++--- spec/support/ability_helpers.rb | 50 +- 5 files changed, 934 insertions(+), 1048 deletions(-) delete mode 100644 app/models/spree/ability_decorator.rb delete mode 100644 spec/models/spree/ability_decorator_spec.rb diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index 25aee521fd..4b9bd1d057 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -1,32 +1,11 @@ # frozen_string_literal: true -# Implementation class for Cancan gem. -# Instead of overriding this class, consider adding new permissions -# using the special +register_ability+ method which allows extensions to add their own abilities. -# -# See http://github.com/ryanb/cancan for more details on cancan. require 'cancan' module Spree class Ability include CanCan::Ability - class_attribute :abilities - self.abilities = Set.new - - # Allows us to go beyond the standard cancan initialize method - # which makes it difficult for engines to modify the default +Ability+ of an application. - # The +ability+ argument must be a class that includes the +CanCan::Ability+ module. - # The registered ability should behave properly as a stand-alone class - # and therefore should be easy to test in isolation. - def self.register_ability(ability) - abilities.add(ability) - end - - def self.remove_ability(ability) - abilities.delete(ability) - end - def initialize(user) clear_aliased_actions @@ -67,11 +46,309 @@ module Spree can [:index, :read], Zone end - # Include any abilities registered by extensions, etc. - Ability.abilities.each do |clazz| - ability = clazz.__send__(:new, user) - @rules = rules + ability.__send__(:rules) + add_shopping_abilities user + add_base_abilities user if is_new_user? user + add_enterprise_management_abilities user if can_manage_enterprises? user + add_group_management_abilities user if can_manage_groups? user + add_product_management_abilities user if can_manage_products? user + add_order_cycle_management_abilities user if can_manage_order_cycles? user + add_order_management_abilities user if can_manage_orders? user + add_relationship_management_abilities user if can_manage_relationships? user + end + + # New users have no enterprises. + def is_new_user?(user) + user.enterprises.blank? + end + + # Users can manage an enterprise if they have one. + def can_manage_enterprises?(user) + user.enterprises.present? + end + + # Users can manage a group if they have one. + def can_manage_groups?(user) + user.owned_groups.present? + end + + # Users can manage products if they have an enterprise that is not a profile. + def can_manage_products?(user) + can_manage_enterprises?(user) && + user.enterprises.any? { |e| e.category != :hub_profile && e.producer_profile_only != true } + end + + # Users can manage order cycles if they manage a sells own/any enterprise + # OR if they manage a producer which is included in any order cycles + def can_manage_order_cycles?(user) + can_manage_orders?(user) || + OrderCycle.visible_by(user).any? + end + + # Users can manage orders if they have a sells own/any enterprise. + def can_manage_orders?(user) + ( user.enterprises.map(&:sells) & %w(own any) ).any? + end + + def can_manage_relationships?(user) + can_manage_enterprises? user + end + + def add_shopping_abilities(user) + can [:destroy], Spree::LineItem do |item| + user == item.order.user && + item.order.changes_allowed? + end + + can [:cancel], Spree::Order do |order| + order.user == user + end + + can [:update, :destroy], Spree::CreditCard do |credit_card| + credit_card.user == user + end + + can [:update], Customer do |customer| + customer.user == user end end + + # New users can create an enterprise, and gain other permissions from doing this. + def add_base_abilities(_user) + can [:create], Enterprise + end + + def add_group_management_abilities(user) + can [:admin, :index], :overview + can [:admin, :index], EnterpriseGroup + can [:read, :edit, :update], EnterpriseGroup do |group| + user.owned_groups.include? group + end + end + + def add_enterprise_management_abilities(user) + # Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil) + # when searching for variants to add to the order + can [:create, :search], nil + + can [:admin, :index], :overview + + can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty + + can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule| + user.enterprises.include? tag_rule.enterprise + end + + can [:admin, :index, :create], Enterprise + can [:read, :edit, :update, + :remove_logo, :remove_promo_image, :remove_terms_and_conditions, + :bulk_update, :resend_confirmation], Enterprise do |enterprise| + OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise + end + can [:welcome, :register], Enterprise do |enterprise| + enterprise.owner == user + end + can [:manage_payment_methods, :manage_shipping_methods, :manage_enterprise_fees], Enterprise do |enterprise| + user.enterprises.include? enterprise + end + + # All enterprises can have fees, though possibly suppliers don't need them? + can [:index, :create], EnterpriseFee + can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee| + user.enterprises.include? enterprise_fee.enterprise + end + + can [:admin, :known_users, :customers], :search + + can [:admin, :show], :account + + # For printing own account invoice orders + can [:print], Spree::Order do |order| + order.user == user + end + + can [:admin, :bulk_update], ColumnPreference do |column_preference| + column_preference.user == user + end + + can [:admin, :connect, :status, :destroy], StripeAccount do |stripe_account| + user.enterprises.include? stripe_account.enterprise + end + + can [:admin, :create], :manager_invitation + end + + def add_product_management_abilities(user) + # Enterprise User can only access products that they are a supplier for + can [:create], Spree::Product + can [:admin, :read, :index, :update, + :seo, :group_buy_options, + :bulk_update, :clone, :delete, + :destroy], Spree::Product do |product| + OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier + end + + can [:create], Spree::Variant + can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant| + OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier + end + + can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo| + next false unless vo.hub.present? && vo.variant.andand.product.andand.supplier.present? + + hub_auth = OpenFoodNetwork::Permissions.new(user). + variant_override_hubs. + include? vo.hub + + producer_auth = OpenFoodNetwork::Permissions.new(user). + variant_override_producers. + include? vo.variant.product.supplier + + hub_auth && producer_auth + end + + can [:admin, :create, :update], InventoryItem do |ii| + next false unless ii.enterprise.present? && ii.variant.andand.product.andand.supplier.present? + + hub_auth = OpenFoodNetwork::Permissions.new(user). + variant_override_hubs. + include? ii.enterprise + + producer_auth = OpenFoodNetwork::Permissions.new(user). + variant_override_producers. + include? ii.variant.product.supplier + + hub_auth && producer_auth + end + + can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], Spree::ProductProperty + can [:admin, :index, :read, :create, :edit, :update, :destroy], Spree::Image + + can [:admin, :index, :read, :search], Spree::Taxon + can [:admin, :index, :read, :create, :edit], Spree::Classification + + can [:admin, :index, :guide, :import, :save, :save_data, :validate_data, :reset_absent_products], ProductImport::ProductImporter + + # Reports page + can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :payments, + :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :packing], + Spree::Admin::ReportsController + add_bulk_coop_abilities + add_enterprise_fee_summary_abilities + end + + def add_order_cycle_management_abilities(user) + can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle| + OrderCycle.visible_by(user).include? order_cycle + end + can [:admin, :index, :create], Schedule + can [:admin, :update, :destroy], Schedule do |schedule| + OpenFoodNetwork::Permissions.new(user).editable_schedules.include? schedule + end + can [:bulk_update, :clone, :destroy, :notify_producers], OrderCycle do |order_cycle| + user.enterprises.include? order_cycle.coordinator + end + can [:for_order_cycle], Enterprise + can [:for_order_cycle], EnterpriseFee + end + + def add_order_management_abilities(user) + can [:index, :create], Spree::Order + can [:read, :update, :fire, :resend, :invoice, :print, :print_ticket], Spree::Order do |order| + # We allow editing orders with a nil distributor as this state occurs + # during the order creation process from the admin backend + order.distributor.nil? || + # Enterprise User can access orders that they are a distributor for + user.enterprises.include?(order.distributor) || + # Enterprise User can access orders that are placed inside a OC they coordinate + order.order_cycle.andand.coordinated_by?(user) + end + can [:admin, :bulk_management, :managed], Spree::Order do + user.admin? || user.enterprises.any?(&:is_distributor) + end + can [:admin, :create, :show, :poll], :invoice + can [:admin, :visible], Enterprise + can [:admin, :index, :create, :update, :destroy], :line_item + can [:admin, :index, :create], Spree::LineItem + can [:destroy, :update], Spree::LineItem do |item| + order = item.order + user.admin? || user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + end + + can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment + can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment + can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment + can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization + can [:destroy], Spree::Adjustment do |adjustment| + # Sharing code with destroying a line item. This should be unified and probably applied for other actions as well. + if user.admin? + true + elsif adjustment.adjustable.instance_of? Spree::Order + order = adjustment.adjustable + user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + elsif adjustment.adjustable.instance_of? Spree::LineItem + order = adjustment.adjustable.order + user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + end + end + + can [:create], OrderCycle + + can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant + can [:admin, :index, :read, :create, :edit, :update], Exchange + can [:admin, :index, :read, :create, :edit, :update], ExchangeFee + + # Enterprise user can only access payment and shipping methods for their distributors + can [:index, :create], Spree::PaymentMethod + can [:admin, :read, :update, :fire, :resend, :destroy, :show_provider_preferences], Spree::PaymentMethod do |payment_method| + (user.enterprises & payment_method.distributors).any? + end + + can [:index, :create], Spree::ShippingMethod + can [:admin, :read, :update, :destroy], Spree::ShippingMethod do |shipping_method| + (user.enterprises & shipping_method.distributors).any? + end + + # Reports page + can [:admin, :index, :customers, :group_buys, :sales_tax, :payments, + :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, + :order_cycle_management, :xero_invoices], Spree::Admin::ReportsController + add_bulk_coop_abilities + add_enterprise_fee_summary_abilities + + can [:create], Customer + can [:admin, :index, :update, :destroy, :show], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id) + can [:admin, :new, :index], Subscription + can [:create, :edit, :update, :cancel, :pause, :unpause], Subscription do |subscription| + user.enterprises.include?(subscription.shop) + end + can [:admin, :build], SubscriptionLineItem + can [:destroy], SubscriptionLineItem do |subscription_line_item| + user.enterprises.include?(subscription_line_item.subscription.shop) + end + can [:admin, :edit, :cancel, :resume], ProxyOrder do |proxy_order| + user.enterprises.include?(proxy_order.subscription.shop) + end + end + + def add_relationship_management_abilities(user) + can [:admin, :index, :create], EnterpriseRelationship + can [:destroy], EnterpriseRelationship do |enterprise_relationship| + user.enterprises.include? enterprise_relationship.parent + end + end + + def add_bulk_coop_abilities + # Reveal the report link in spree/admin/reports#index + can [:bulk_coop], Spree::Admin::ReportsController + # Allow direct access to the report resource + can [:admin, :new, :create], :bulk_coop + end + + def add_enterprise_fee_summary_abilities + # Reveal the report link in spree/admin/reports#index + can [:enterprise_fee_summary], Spree::Admin::ReportsController + # Allow direct access to the report resource + can [:admin, :new, :create], :enterprise_fee_summary + end end end diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb deleted file mode 100644 index 325d93839a..0000000000 --- a/app/models/spree/ability_decorator.rb +++ /dev/null @@ -1,313 +0,0 @@ -class AbilityDecorator - include CanCan::Ability - - # All abilites are allocated from this initialiser. - # Spree also defines other abilities. - def initialize(user) - add_shopping_abilities user - add_base_abilities user if is_new_user? user - add_enterprise_management_abilities user if can_manage_enterprises? user - add_group_management_abilities user if can_manage_groups? user - add_product_management_abilities user if can_manage_products? user - add_order_cycle_management_abilities user if can_manage_order_cycles? user - add_order_management_abilities user if can_manage_orders? user - add_relationship_management_abilities user if can_manage_relationships? user - end - - # New users have no enterprises. - def is_new_user?(user) - user.enterprises.blank? - end - - # Users can manage an enterprise if they have one. - def can_manage_enterprises?(user) - user.enterprises.present? - end - - # Users can manage a group if they have one. - def can_manage_groups?(user) - user.owned_groups.present? - end - - # Users can manage products if they have an enterprise that is not a profile. - def can_manage_products?(user) - can_manage_enterprises?(user) && - user.enterprises.any? { |e| e.category != :hub_profile && e.producer_profile_only != true } - end - - # Users can manage order cycles if they manage a sells own/any enterprise - # OR if they manage a producer which is included in any order cycles - def can_manage_order_cycles?(user) - can_manage_orders?(user) || - OrderCycle.visible_by(user).any? - end - - # Users can manage orders if they have a sells own/any enterprise. - def can_manage_orders?(user) - ( user.enterprises.map(&:sells) & %w(own any) ).any? - end - - def can_manage_relationships?(user) - can_manage_enterprises? user - end - - def add_shopping_abilities(user) - can [:destroy], Spree::LineItem do |item| - user == item.order.user && - item.order.changes_allowed? - end - - can [:cancel], Spree::Order do |order| - order.user == user - end - - can [:update, :destroy], Spree::CreditCard do |credit_card| - credit_card.user == user - end - - can [:update], Customer do |customer| - customer.user == user - end - end - - # New users can create an enterprise, and gain other permissions from doing this. - def add_base_abilities(_user) - can [:create], Enterprise - end - - def add_group_management_abilities(user) - can [:admin, :index], :overview - can [:admin, :index], EnterpriseGroup - can [:read, :edit, :update], EnterpriseGroup do |group| - user.owned_groups.include? group - end - end - - def add_enterprise_management_abilities(user) - # Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil) - # when searching for variants to add to the order - can [:create, :search], nil - - can [:admin, :index], :overview - - can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty - - can [:admin, :map_by_tag, :destroy], TagRule do |tag_rule| - user.enterprises.include? tag_rule.enterprise - end - - can [:admin, :index, :create], Enterprise - can [:read, :edit, :update, - :remove_logo, :remove_promo_image, :remove_terms_and_conditions, - :bulk_update, :resend_confirmation], Enterprise do |enterprise| - OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise - end - can [:welcome, :register], Enterprise do |enterprise| - enterprise.owner == user - end - can [:manage_payment_methods, :manage_shipping_methods, :manage_enterprise_fees], Enterprise do |enterprise| - user.enterprises.include? enterprise - end - - # All enterprises can have fees, though possibly suppliers don't need them? - can [:index, :create], EnterpriseFee - can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee| - user.enterprises.include? enterprise_fee.enterprise - end - - can [:admin, :known_users, :customers], :search - - can [:admin, :show], :account - - # For printing own account invoice orders - can [:print], Spree::Order do |order| - order.user == user - end - - can [:admin, :bulk_update], ColumnPreference do |column_preference| - column_preference.user == user - end - - can [:admin, :connect, :status, :destroy], StripeAccount do |stripe_account| - user.enterprises.include? stripe_account.enterprise - end - - can [:admin, :create], :manager_invitation - end - - def add_product_management_abilities(user) - # Enterprise User can only access products that they are a supplier for - can [:create], Spree::Product - can [:admin, :read, :index, :update, - :seo, :group_buy_options, - :bulk_update, :clone, :delete, - :destroy], Spree::Product do |product| - OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier - end - - can [:create], Spree::Variant - can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant| - OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier - end - - can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo| - next false unless vo.hub.present? && vo.variant.andand.product.andand.supplier.present? - - hub_auth = OpenFoodNetwork::Permissions.new(user). - variant_override_hubs. - include? vo.hub - - producer_auth = OpenFoodNetwork::Permissions.new(user). - variant_override_producers. - include? vo.variant.product.supplier - - hub_auth && producer_auth - end - - can [:admin, :create, :update], InventoryItem do |ii| - next false unless ii.enterprise.present? && ii.variant.andand.product.andand.supplier.present? - - hub_auth = OpenFoodNetwork::Permissions.new(user). - variant_override_hubs. - include? ii.enterprise - - producer_auth = OpenFoodNetwork::Permissions.new(user). - variant_override_producers. - include? ii.variant.product.supplier - - hub_auth && producer_auth - end - - can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], Spree::ProductProperty - can [:admin, :index, :read, :create, :edit, :update, :destroy], Spree::Image - - can [:admin, :index, :read, :search], Spree::Taxon - can [:admin, :index, :read, :create, :edit], Spree::Classification - - can [:admin, :index, :guide, :import, :save, :save_data, :validate_data, :reset_absent_products], ProductImport::ProductImporter - - # Reports page - can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :payments, - :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :packing], - Spree::Admin::ReportsController - add_bulk_coop_abilities - add_enterprise_fee_summary_abilities - end - - def add_order_cycle_management_abilities(user) - can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle| - OrderCycle.visible_by(user).include? order_cycle - end - can [:admin, :index, :create], Schedule - can [:admin, :update, :destroy], Schedule do |schedule| - OpenFoodNetwork::Permissions.new(user).editable_schedules.include? schedule - end - can [:bulk_update, :clone, :destroy, :notify_producers], OrderCycle do |order_cycle| - user.enterprises.include? order_cycle.coordinator - end - can [:for_order_cycle], Enterprise - can [:for_order_cycle], EnterpriseFee - end - - def add_order_management_abilities(user) - can [:index, :create], Spree::Order - can [:read, :update, :fire, :resend, :invoice, :print, :print_ticket], Spree::Order do |order| - # We allow editing orders with a nil distributor as this state occurs - # during the order creation process from the admin backend - order.distributor.nil? || - # Enterprise User can access orders that they are a distributor for - user.enterprises.include?(order.distributor) || - # Enterprise User can access orders that are placed inside a OC they coordinate - order.order_cycle.andand.coordinated_by?(user) - end - can [:admin, :bulk_management, :managed], Spree::Order do - user.admin? || user.enterprises.any?(&:is_distributor) - end - can [:admin, :create, :show, :poll], :invoice - can [:admin, :visible], Enterprise - can [:admin, :index, :create, :update, :destroy], :line_item - can [:admin, :index, :create], Spree::LineItem - can [:destroy, :update], Spree::LineItem do |item| - order = item.order - user.admin? || user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) - end - - can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment - can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment - can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment - can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization - can [:destroy], Spree::Adjustment do |adjustment| - # Sharing code with destroying a line item. This should be unified and probably applied for other actions as well. - if user.admin? - true - elsif adjustment.adjustable.instance_of? Spree::Order - order = adjustment.adjustable - user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) - elsif adjustment.adjustable.instance_of? Spree::LineItem - order = adjustment.adjustable.order - user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) - end - end - - can [:create], OrderCycle - - can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant - can [:admin, :index, :read, :create, :edit, :update], Exchange - can [:admin, :index, :read, :create, :edit, :update], ExchangeFee - - # Enterprise user can only access payment and shipping methods for their distributors - can [:index, :create], Spree::PaymentMethod - can [:admin, :read, :update, :fire, :resend, :destroy, :show_provider_preferences], Spree::PaymentMethod do |payment_method| - (user.enterprises & payment_method.distributors).any? - end - - can [:index, :create], Spree::ShippingMethod - can [:admin, :read, :update, :destroy], Spree::ShippingMethod do |shipping_method| - (user.enterprises & shipping_method.distributors).any? - end - - # Reports page - can [:admin, :index, :customers, :group_buys, :sales_tax, :payments, - :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, - :order_cycle_management, :xero_invoices], Spree::Admin::ReportsController - add_bulk_coop_abilities - add_enterprise_fee_summary_abilities - - can [:create], Customer - can [:admin, :index, :update, :destroy, :show], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id) - can [:admin, :new, :index], Subscription - can [:create, :edit, :update, :cancel, :pause, :unpause], Subscription do |subscription| - user.enterprises.include?(subscription.shop) - end - can [:admin, :build], SubscriptionLineItem - can [:destroy], SubscriptionLineItem do |subscription_line_item| - user.enterprises.include?(subscription_line_item.subscription.shop) - end - can [:admin, :edit, :cancel, :resume], ProxyOrder do |proxy_order| - user.enterprises.include?(proxy_order.subscription.shop) - end - end - - def add_relationship_management_abilities(user) - can [:admin, :index, :create], EnterpriseRelationship - can [:destroy], EnterpriseRelationship do |enterprise_relationship| - user.enterprises.include? enterprise_relationship.parent - end - end - - def add_bulk_coop_abilities - # Reveal the report link in spree/admin/reports#index - can [:bulk_coop], Spree::Admin::ReportsController - # Allow direct access to the report resource - can [:admin, :new, :create], :bulk_coop - end - - def add_enterprise_fee_summary_abilities - # Reveal the report link in spree/admin/reports#index - can [:enterprise_fee_summary], Spree::Admin::ReportsController - # Allow direct access to the report resource - can [:admin, :new, :create], :enterprise_fee_summary - end -end - -Spree::Ability.register_ability(AbilityDecorator) diff --git a/spec/models/spree/ability_decorator_spec.rb b/spec/models/spree/ability_decorator_spec.rb deleted file mode 100644 index 355c5d2935..0000000000 --- a/spec/models/spree/ability_decorator_spec.rb +++ /dev/null @@ -1,607 +0,0 @@ -require 'spec_helper' -require "cancan/matchers" -require 'support/cancan_helper' - -module Spree - describe User do - describe "broad permissions" do - subject { AbilityDecorator.new(user) } - - include ::AbilityHelper - - let(:user) { create(:user) } - let(:enterprise_any) { create(:enterprise, sells: 'any') } - let(:enterprise_own) { create(:enterprise, sells: 'own') } - let(:enterprise_none) { create(:enterprise, sells: 'none') } - let(:enterprise_any_producer) { create(:enterprise, sells: 'any', is_primary_producer: true) } - let(:enterprise_own_producer) { create(:enterprise, sells: 'own', is_primary_producer: true) } - let(:enterprise_none_producer) { create(:enterprise, sells: 'none', is_primary_producer: true) } - - context "as manager of an enterprise who sells 'any'" do - before do - user.enterprise_roles.create! enterprise: enterprise_any - end - - it { expect(subject.can_manage_products?(user)).to be true } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be true } - it { expect(subject.can_manage_order_cycles?(user)).to be true } - end - - context "as manager of an enterprise who sell 'own'" do - before do - user.enterprise_roles.create! enterprise: enterprise_own - end - - it { expect(subject.can_manage_products?(user)).to be true } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be true } - it { expect(subject.can_manage_order_cycles?(user)).to be true } - end - - context "as manager of an enterprise who sells 'none'" do - before do - user.enterprise_roles.create! enterprise: enterprise_none - end - - it { expect(subject.can_manage_products?(user)).to be false } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be false } - it { expect(subject.can_manage_order_cycles?(user)).to be false } - end - - context "as manager of a producer enterprise who sells 'any'" do - before do - user.enterprise_roles.create! enterprise: enterprise_any_producer - end - - it { expect(subject.can_manage_products?(user)).to be true } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be true } - it { expect(subject.can_manage_order_cycles?(user)).to be true } - end - - context "as manager of a producer enterprise who sell 'own'" do - before do - user.enterprise_roles.create! enterprise: enterprise_own_producer - end - - it { expect(subject.can_manage_products?(user)).to be true } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be true } - it { expect(subject.can_manage_order_cycles?(user)).to be true } - end - - context "as manager of a producer enterprise who sells 'none'" do - before do - user.enterprise_roles.create! enterprise: enterprise_none_producer - end - - context "as a non profile" do - before do - enterprise_none_producer.is_primary_producer = true - enterprise_none_producer.producer_profile_only = false - enterprise_none_producer.save! - end - - it { expect(subject.can_manage_products?(user)).to be true } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be false } - it { expect(subject.can_manage_order_cycles?(user)).to be false } - end - - context "as a profile" do - before do - enterprise_none_producer.is_primary_producer = true - enterprise_none_producer.producer_profile_only = true - enterprise_none_producer.save! - end - - it { expect(subject.can_manage_products?(user)).to be false } - it { expect(subject.can_manage_enterprises?(user)).to be true } - it { expect(subject.can_manage_orders?(user)).to be false } - it { expect(subject.can_manage_order_cycles?(user)).to be false } - end - end - - context "as a new user with no enterprises" do - it { expect(subject.can_manage_products?(user)).to be false } - it { expect(subject.can_manage_enterprises?(user)).to be false } - it { expect(subject.can_manage_orders?(user)).to be false } - it { expect(subject.can_manage_order_cycles?(user)).to be false } - - it "can create enterprises straight off the bat" do - expect(subject.is_new_user?(user)).to be true - expect(user).to have_ability :create, for: Enterprise - end - end - end - - describe 'Roles' do - # create enterprises - let(:s1) { create(:supplier_enterprise) } - let(:s2) { create(:supplier_enterprise) } - let(:s_related) { create(:supplier_enterprise) } - let(:d1) { create(:distributor_enterprise) } - let(:d2) { create(:distributor_enterprise) } - - let(:p1) { create(:product, supplier: s1) } - let(:p2) { create(:product, supplier: s2) } - let(:p_related) { create(:product, supplier: s_related) } - - let(:er1) { create(:enterprise_relationship, parent: s1, child: d1) } - let(:er2) { create(:enterprise_relationship, parent: d1, child: s1) } - let(:er_ps) { create(:enterprise_relationship, parent: s_related, child: s1, permissions_list: [:manage_products]) } - - subject { user } - let(:user) { nil } - - context "when is a supplier enterprise user" do - # create supplier_enterprise1 user without full admin access - let(:user) do - user = create(:user) - user.spree_roles = [] - s1.enterprise_roles.build(user: user).save - user - end - - let(:order) { create(:order) } - - it "should be able to read/write their enterprises' products and variants" do - is_expected.to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p1) - is_expected.to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p1.master) - end - - it "should be able to read/write related enterprises' products and variants with manage_products permission" do - er_ps - is_expected.to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p_related) - is_expected.to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p_related.master) - end - - it "should not be able to read/write other enterprises' products and variants" do - is_expected.not_to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p2) - is_expected.not_to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p2.master) - end - - it "should not be able to access admin actions on orders" do - is_expected.not_to have_ability([:admin], for: Spree::Order) - end - - it "should be able to create a new product" do - is_expected.to have_ability(:create, for: Spree::Product) - end - - it "should be able to read/write their enterprises' product variants" do - is_expected.to have_ability([:create], for: Spree::Variant) - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy, :delete], for: p1.master) - end - - it "should not be able to read/write other enterprises' product variants" do - is_expected.not_to have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy], for: p2.master) - end - - it "should be able to read/write their enterprises' product properties" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update_positions, :destroy], for: Spree::ProductProperty) - end - - it "should be able to read/write their enterprises' product images" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :destroy], for: Spree::Image) - end - - it "should be able to read Taxons (in order to create classifications)" do - is_expected.to have_ability([:admin, :index, :read, :search], for: Spree::Taxon) - end - - it "should be able to read/write Classifications on a product" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit], for: Spree::Classification) - end - - it "should be able to read/write their enterprises' producer properties" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update_positions, :destroy], for: ProducerProperty) - end - - it "should be able to read and create enterprise relationships" do - is_expected.to have_ability([:admin, :index, :create], for: EnterpriseRelationship) - end - - it "should be able to destroy enterprise relationships for its enterprises" do - is_expected.to have_ability(:destroy, for: er1) - end - - it "should not be able to destroy enterprise relationships for other enterprises" do - is_expected.not_to have_ability(:destroy, for: er2) - end - - it "should be able to read some reports" do - is_expected.to have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management], for: Spree::Admin::ReportsController) - end - - include_examples "allows access to Enterprise Fee Summary" - - it "should not be able to read other reports" do - is_expected.not_to have_ability([:group_buys, :payments, :orders_and_distributors, :users_and_enterprises, :xero_invoices], for: Spree::Admin::ReportsController) - end - - it "should not be able to access customer actions" do - is_expected.not_to have_ability([:admin, :index, :update], for: Customer) - end - - describe "order_cycles abilities" do - context "where the enterprise is not in an order_cycle" do - let!(:order_cycle) { create(:simple_order_cycle) } - - it "should not be able to access read/update order_cycle actions" do - is_expected.not_to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) - end - - it "should not be able to access bulk_update, clone order cycle actions" do - is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) - end - - it "cannot request permitted enterprises for an order cycle" do - is_expected.not_to have_ability([:for_order_cycle], for: Enterprise) - end - - it "cannot request permitted enterprise fees for an order cycle" do - is_expected.not_to have_ability([:for_order_cycle], for: EnterpriseFee) - end - end - - context "where the enterprise is in an order_cycle" do - let!(:order_cycle) { create(:simple_order_cycle) } - let!(:exchange){ create(:exchange, incoming: true, order_cycle: order_cycle, receiver: order_cycle.coordinator, sender: s1) } - - it "should be able to access read/update order cycle actions" do - is_expected.to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) - end - - it "should not be able to access bulk/update, clone order cycle actions" do - is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) - end - - it "can request permitted enterprises for an order cycle" do - is_expected.to have_ability([:for_order_cycle], for: Enterprise) - end - - it "can request permitted enterprise fees for an order cycle" do - is_expected.to have_ability([:for_order_cycle], for: EnterpriseFee) - end - end - end - end - - context "when is a distributor enterprise user" do - # create distributor_enterprise1 user without full admin access - let(:user) do - user = create(:user) - user.spree_roles = [] - d1.enterprise_roles.build(user: user).save - user - end - # create order for each enterprise - let(:o1) do - o = create(:order, distributor: d1, bill_address: create(:address)) - create(:line_item, order: o, product: p1) - o - end - let(:o2) do - o = create(:order, distributor: d2, bill_address: create(:address)) - create(:line_item, order: o, product: p1) - o - end - let(:o3) do - o = create(:order, distributor: nil, bill_address: create(:address)) - create(:line_item, order: o, product: p1) - o - end - - describe "editing enterprises" do - let!(:d_related) { create(:distributor_enterprise) } - let!(:er_pd) { create(:enterprise_relationship, parent: d_related, child: d1, permissions_list: [:edit_profile]) } - - it "should be able to edit enterprises it manages" do - is_expected.to have_ability([:read, :edit, :update, :remove_logo, :remove_promo_image, :remove_terms_and_conditions, :bulk_update, :resend_confirmation], for: d1) - end - - it "should be able to edit enterprises it has permission to" do - is_expected.to have_ability([:read, :edit, :update, :remove_logo, :remove_promo_image, :remove_terms_and_conditions, :bulk_update, :resend_confirmation], for: d_related) - end - - it "should be able to manage shipping methods, payment methods and enterprise fees for enterprises it manages" do - is_expected.to have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d1) - end - - it "should not be able to manage shipping methods, payment methods and enterprise fees for enterprises it has edit profile permission to" do - is_expected.not_to have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d_related) - end - end - - describe "variant overrides" do - let(:vo1) { create(:variant_override, hub: d1, variant: p1.master) } - let(:vo2) { create(:variant_override, hub: d1, variant: p2.master) } - let(:vo3) { create(:variant_override, hub: d2, variant: p1.master) } - let(:vo4) { create(:variant_override, hub: d2, variant: p2.master) } - - let!(:er1) { create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:create_variant_overrides]) } - - it "should be able to access variant overrides page" do - is_expected.to have_ability([:admin, :index, :bulk_update, :bulk_reset], for: VariantOverride) - end - - it "should be able to read/write their own variant overrides" do - is_expected.to have_ability([:admin, :index, :read, :update], for: vo1) - end - - it "should not be able to read/write variant overrides when producer of product hasn't granted permission" do - is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo2) - end - - it "should not be able to read/write variant overrides when we can't add hub to order cycle" do - is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo3) - end - - it "should not be able to read/write other enterprises' variant overrides" do - is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo4) - end - end - - it "should be able to read/write their enterprises' orders" do - is_expected.to have_ability([:admin, :index, :read, :edit], for: o1) - end - - it "should not be able to read/write other enterprises' orders" do - is_expected.not_to have_ability([:admin, :index, :read, :edit], for: o2) - end - - it "should be able to read/write orders that are in the process of being created" do - is_expected.to have_ability([:admin, :index, :read, :edit], for: o3) - end - - it "should be able to create and search on nil (required for creating an order)" do - is_expected.to have_ability([:create, :search], for: nil) - end - - it "should be able to create a new order" do - is_expected.to have_ability([:admin, :index, :read, :create, :update], for: Spree::Order) - end - - it "should be able to create a new line item" do - is_expected.to have_ability([:admin, :create], for: Spree::LineItem) - end - - it "should be able to read/write Payments on a product" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Payment) - end - - it "should be able to read/write Shipments on a product" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Shipment) - end - - it "should be able to read/write Adjustments on a product" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Adjustment) - end - - it "should be able to read/write ReturnAuthorizations on a product" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::ReturnAuthorization) - end - - it "should be able to read/write PaymentMethods" do - is_expected.to have_ability([:admin, :index, :create, :update, :destroy], for: Spree::PaymentMethod) - end - - it "should be able to read/write ShippingMethods" do - is_expected.to have_ability([:admin, :index, :create, :update, :destroy], for: Spree::ShippingMethod) - end - - it "should be able to read and create enterprise relationships" do - is_expected.to have_ability([:admin, :index, :create], for: EnterpriseRelationship) - end - - it "should be able to destroy enterprise relationships for its enterprises" do - is_expected.to have_ability(:destroy, for: er2) - end - - it "should not be able to destroy enterprise relationships for other enterprises" do - is_expected.not_to have_ability(:destroy, for: er1) - end - - it "should be able to read some reports" do - is_expected.to have_ability([:admin, :index, :customers, :sales_tax, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :xero_invoices], for: Spree::Admin::ReportsController) - end - - include_examples "allows access to Enterprise Fee Summary" - - it "should not be able to read other reports" do - is_expected.not_to have_ability([:users_and_enterprises], for: Spree::Admin::ReportsController) - end - - it "should be able to access customer actions" do - is_expected.to have_ability([:admin, :index, :update], for: Customer) - end - - context "for a given order_cycle" do - let!(:order_cycle) { create(:simple_order_cycle) } - let!(:exchange){ create(:exchange, incoming: false, order_cycle: order_cycle, receiver: d1, sender: order_cycle.coordinator) } - - it "should be able to access read and update order cycle actions" do - is_expected.to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) - end - - it "should not be able to access bulk_update, clone order cycle actions" do - is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) - end - end - - it "can request permitted enterprises for an order cycle" do - is_expected.to have_ability([:for_order_cycle], for: Enterprise) - end - - it "can request permitted enterprise fees for an order cycle" do - is_expected.to have_ability([:for_order_cycle], for: EnterpriseFee) - end - end - - context 'Order Cycle co-ordinator, distributor enterprise manager' do - let(:user) do - user = create(:user) - user.spree_roles = [] - d1.enterprise_roles.build(user: user).save - user - end - - let(:oc1) { create(:simple_order_cycle, coordinator: d1) } - let(:oc2) { create(:simple_order_cycle) } - - it "should be able to read/write OrderCycles they are the co-ordinator of" do - is_expected.to have_ability([:admin, :index, :read, :edit, :update, :bulk_update, :clone, :destroy], for: oc1) - end - - it "should not be able to read/write OrderCycles they are not the co-ordinator of" do - should_not have_ability([:admin, :index, :read, :create, :edit, :update, :bulk_update, :clone, :destroy], for: oc2) - end - - it "should be able to create OrderCycles" do - is_expected.to have_ability([:create], for: OrderCycle) - end - - it "should be able to read/write EnterpriseFees" do - is_expected.to have_ability([:admin, :index, :read, :create, :edit, :bulk_update, :destroy, :for_order_cycle], for: EnterpriseFee) - end - - it "should be able to add enterprises to order cycles" do - is_expected.to have_ability([:admin, :index, :for_order_cycle, :create], for: Enterprise) - end - end - - context 'enterprise manager' do - let(:user) do - user = create(:user) - user.spree_roles = [] - s1.enterprise_roles.build(user: user).save - user - end - - it 'should have the ability to view the admin account page' do - is_expected.to have_ability([:admin, :show], for: :account) - end - - it 'should have the ability to read and edit enterprises that I manage' do - is_expected.to have_ability([:read, :edit, :update, :bulk_update], for: s1) - end - - it 'should not have the ability to read and edit enterprises that I do not manage' do - is_expected.not_to have_ability([:read, :edit, :update, :bulk_update], for: s2) - end - - it 'should not have the ability to welcome and register enterprises that I do not own' do - is_expected.not_to have_ability([:welcome, :register], for: s1) - end - - it 'should have the ability administrate and create enterpises' do - is_expected.to have_ability([:admin, :index, :create], for: Enterprise) - end - - it "should have the ability to search for users which share management of its enterprises" do - is_expected.to have_ability([:admin, :known_users, :customers], for: :search) - is_expected.not_to have_ability([:users], for: :search) - end - end - - context 'enterprise owner' do - let(:user) { s1.owner } - - it 'should have the ability to welcome and register enterprises that I own' do - is_expected.to have_ability([:welcome, :register], for: s1) - end - - it 'should have the ability to view the admin account page' do - is_expected.to have_ability([:admin, :show], for: :account) - end - end - end - - describe "permissions for variant overrides" do - let!(:distributor) { create(:distributor_enterprise) } - let!(:producer) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier: producer) } - let!(:variant) { create(:variant, product: product) } - let!(:variant_override) { create(:variant_override, hub: distributor, variant: variant) } - - subject { user } - - let(:manage_actions) { [:admin, :index, :read, :update, :bulk_update, :bulk_reset] } - - describe "when admin" do - let(:user) { create(:admin_user) } - - it "should have permission" do - is_expected.to have_ability(manage_actions, for: variant_override) - end - end - - describe "when user of the producer" do - let(:user) { producer.owner } - - it "should not have permission" do - is_expected.not_to have_ability(manage_actions, for: variant_override) - end - end - - describe "when user of the distributor" do - let(:user) { distributor.owner } - - it "should not have permission" do - is_expected.not_to have_ability(manage_actions, for: variant_override) - end - end - - describe "when user of the distributor which is also the producer" do - let(:user) { distributor.owner } - let!(:distributor) { create(:distributor_enterprise, is_primary_producer: true, sells: "any") } - let!(:producer) { distributor } - - it "should have permission" do - is_expected.to have_ability(manage_actions, for: variant_override) - end - end - - describe "when owner of the distributor with add_to_order_cycle permission to the producer" do - let!(:unauthorized_enterprise) do - create(:enterprise, sells: "any").tap do |record| - create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:add_to_order_cycle]) - end - end - let(:user) { unauthorized_enterprise.owner } - - it "should not have permission" do - is_expected.not_to have_ability(manage_actions, for: variant_override) - end - end - - describe "when owner of the enterprise with create_variant_overrides permission to the producer" do - let!(:authorized_enterprise) do - create(:enterprise, sells: "any").tap do |record| - create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:create_variant_overrides]) - end - end - let(:user) { authorized_enterprise.owner } - - it "should not have permission" do - is_expected.not_to have_ability(manage_actions, for: variant_override) - end - - describe "when the enterprise is not a distributor" do - let!(:authorized_enterprise) do - create(:enterprise, sells: "none").tap do |record| - create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:create_variant_overrides]) - end - end - - it "should not have permission" do - is_expected.not_to have_ability(manage_actions, for: variant_override) - end - end - end - end - end -end diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 5b64660e95..00850efdb8 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -2,23 +2,11 @@ require 'spec_helper' require 'cancan/matchers' require 'support/ability_helpers' -# Fake ability for testing registration of additional abilities -class FooAbility - include CanCan::Ability - - def initialize(_user) - # allow anyone to perform index on Order - can :index, Spree::Order - # allow anyone to update an Order with id of 1 - can :update, Spree::Order do |order| - order.id == 1 - end - end -end - describe Spree::Ability do + include ::AbilityHelper + let(:user) { create(:user) } - let(:ability) { Spree::Ability.new(user) } + let(:subject) { Spree::Ability.new(user) } let(:token) { nil } before do @@ -28,22 +16,9 @@ describe Spree::Ability do TOKEN = 'token123'.freeze after(:each) { - Spree::Ability.abilities = Set.new user.spree_roles = [] } - context 'register_ability' do - it 'should add the ability to the list of abilties' do - Spree::Ability.register_ability(FooAbility) - expect(Spree::Ability.new(user).abilities).to_not be_empty - end - - it 'should apply the registered abilities permissions' do - Spree::Ability.register_ability(FooAbility) - expect(Spree::Ability.new(user).can?(:update, build(:order, id: 1))).to be_truthy - end - end - context 'for general resource' do let(:resource) { Object.new } @@ -71,61 +46,19 @@ describe Spree::Ability do context 'with admin user' do it 'should be able to admin' do user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') - expect(ability).to be_able_to :admin, resource - expect(ability).to be_able_to :index, resource_order - expect(ability).to be_able_to :show, resource_product - expect(ability).to be_able_to :create, resource_user - end - end - - context 'with fakedispatch user' do - class BarAbility - include CanCan::Ability - - def initialize(user) - user ||= Spree::User.new - return unless user.has_spree_role?('bar') - - can [:admin, :index, :show], Spree::Order - end - end - - it 'should be able to admin on the order and shipment pages' do - user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') - - Spree::Ability.register_ability(BarAbility) - - expect(ability).to_not be_able_to :admin, resource - - expect(ability).to be_able_to :admin, resource_order - expect(ability).to be_able_to :index, resource_order - expect(ability).to_not be_able_to :update, resource_order - - expect(ability).to be_able_to :admin, resource_shipment - expect(ability).to be_able_to :index, resource_shipment - expect(ability).to be_able_to :create, resource_shipment - - expect(ability).to_not be_able_to :admin, resource_product - expect(ability).to_not be_able_to :update, resource_product - - expect(ability).to_not be_able_to :admin, resource_user - expect(ability).to_not be_able_to :update, resource_user - expect(ability).to be_able_to :update, user - - # It can create new users if is has access to the :admin, User!! - - # TODO change the Ability class so only users and customers get the extra premissions? - - Spree::Ability.remove_ability(BarAbility) + expect(subject).to be_able_to :admin, resource + expect(subject).to be_able_to :index, resource_order + expect(subject).to be_able_to :show, resource_product + expect(subject).to be_able_to :create, resource_user end end context 'with customer' do it 'should not be able to admin' do - expect(ability).to_not be_able_to :admin, resource - expect(ability).to_not be_able_to :admin, resource_order - expect(ability).to_not be_able_to :admin, resource_product - expect(ability).to_not be_able_to :admin, resource_user + expect(subject).to_not be_able_to :admin, resource + expect(subject).to_not be_able_to :admin, resource_order + expect(subject).to_not be_able_to :admin, resource_product + expect(subject).to_not be_able_to :admin, resource_user end end end @@ -269,4 +202,600 @@ describe Spree::Ability do end end end + + describe "broad permissions" do + let(:user) { create(:user) } + let(:enterprise_any) { create(:enterprise, sells: 'any') } + let(:enterprise_own) { create(:enterprise, sells: 'own') } + let(:enterprise_none) { create(:enterprise, sells: 'none') } + let(:enterprise_any_producer) { create(:enterprise, sells: 'any', is_primary_producer: true) } + let(:enterprise_own_producer) { create(:enterprise, sells: 'own', is_primary_producer: true) } + let(:enterprise_none_producer) { create(:enterprise, sells: 'none', is_primary_producer: true) } + + context "as manager of an enterprise who sells 'any'" do + before do + user.enterprise_roles.create! enterprise: enterprise_any + end + + it { expect(subject.can_manage_products?(user)).to be true } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be true } + it { expect(subject.can_manage_order_cycles?(user)).to be true } + end + + context "as manager of an enterprise who sell 'own'" do + before do + user.enterprise_roles.create! enterprise: enterprise_own + end + + it { expect(subject.can_manage_products?(user)).to be true } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be true } + it { expect(subject.can_manage_order_cycles?(user)).to be true } + end + + context "as manager of an enterprise who sells 'none'" do + before do + user.enterprise_roles.create! enterprise: enterprise_none + end + + it { expect(subject.can_manage_products?(user)).to be false } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be false } + it { expect(subject.can_manage_order_cycles?(user)).to be false } + end + + context "as manager of a producer enterprise who sells 'any'" do + before do + user.enterprise_roles.create! enterprise: enterprise_any_producer + end + + it { expect(subject.can_manage_products?(user)).to be true } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be true } + it { expect(subject.can_manage_order_cycles?(user)).to be true } + end + + context "as manager of a producer enterprise who sell 'own'" do + before do + user.enterprise_roles.create! enterprise: enterprise_own_producer + end + + it { expect(subject.can_manage_products?(user)).to be true } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be true } + it { expect(subject.can_manage_order_cycles?(user)).to be true } + end + + context "as manager of a producer enterprise who sells 'none'" do + before do + user.enterprise_roles.create! enterprise: enterprise_none_producer + end + + context "as a non profile" do + before do + enterprise_none_producer.is_primary_producer = true + enterprise_none_producer.producer_profile_only = false + enterprise_none_producer.save! + end + + it { expect(subject.can_manage_products?(user)).to be true } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be false } + it { expect(subject.can_manage_order_cycles?(user)).to be false } + end + + context "as a profile" do + before do + enterprise_none_producer.is_primary_producer = true + enterprise_none_producer.producer_profile_only = true + enterprise_none_producer.save! + end + + it { expect(subject.can_manage_products?(user)).to be false } + it { expect(subject.can_manage_enterprises?(user)).to be true } + it { expect(subject.can_manage_orders?(user)).to be false } + it { expect(subject.can_manage_order_cycles?(user)).to be false } + end + end + + context "as a new user with no enterprises" do + it { expect(subject.can_manage_products?(user)).to be false } + it { expect(subject.can_manage_enterprises?(user)).to be false } + it { expect(subject.can_manage_orders?(user)).to be false } + it { expect(subject.can_manage_order_cycles?(user)).to be false } + + it "can create enterprises straight off the bat" do + expect(subject.is_new_user?(user)).to be true + expect(user).to have_ability :create, for: Enterprise + end + end + end + + describe 'Roles' do + # create enterprises + let(:s1) { create(:supplier_enterprise) } + let(:s2) { create(:supplier_enterprise) } + let(:s_related) { create(:supplier_enterprise) } + let(:d1) { create(:distributor_enterprise) } + let(:d2) { create(:distributor_enterprise) } + + let(:p1) { create(:product, supplier: s1) } + let(:p2) { create(:product, supplier: s2) } + let(:p_related) { create(:product, supplier: s_related) } + + let(:er1) { create(:enterprise_relationship, parent: s1, child: d1) } + let(:er2) { create(:enterprise_relationship, parent: d1, child: s1) } + let(:er_ps) { create(:enterprise_relationship, parent: s_related, child: s1, permissions_list: [:manage_products]) } + + subject { user } + let(:user) { nil } + + context "when is a supplier enterprise user" do + # create supplier_enterprise1 user without full admin access + let(:user) do + user = create(:user) + user.spree_roles = [] + s1.enterprise_roles.build(user: user).save + user + end + + let(:order) { create(:order) } + + it "should be able to read/write their enterprises' products and variants" do + is_expected.to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p1) + is_expected.to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p1.master) + end + + it "should be able to read/write related enterprises' products and variants with manage_products permission" do + er_ps + is_expected.to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p_related) + is_expected.to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p_related.master) + end + + it "should not be able to read/write other enterprises' products and variants" do + is_expected.not_to have_ability([:admin, :read, :update, :bulk_update, :clone, :destroy], for: p2) + is_expected.not_to have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p2.master) + end + + it "should not be able to access admin actions on orders" do + is_expected.not_to have_ability([:admin], for: Spree::Order) + end + + it "should be able to create a new product" do + is_expected.to have_ability(:create, for: Spree::Product) + end + + it "should be able to read/write their enterprises' product variants" do + is_expected.to have_ability([:create], for: Spree::Variant) + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy, :delete], for: p1.master) + end + + it "should not be able to read/write other enterprises' product variants" do + is_expected.not_to have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy], for: p2.master) + end + + it "should be able to read/write their enterprises' product properties" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update_positions, :destroy], for: Spree::ProductProperty) + end + + it "should be able to read/write their enterprises' product images" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :destroy], for: Spree::Image) + end + + it "should be able to read Taxons (in order to create classifications)" do + is_expected.to have_ability([:admin, :index, :read, :search], for: Spree::Taxon) + end + + it "should be able to read/write Classifications on a product" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit], for: Spree::Classification) + end + + it "should be able to read/write their enterprises' producer properties" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update_positions, :destroy], for: ProducerProperty) + end + + it "should be able to read and create enterprise relationships" do + is_expected.to have_ability([:admin, :index, :create], for: EnterpriseRelationship) + end + + it "should be able to destroy enterprise relationships for its enterprises" do + is_expected.to have_ability(:destroy, for: er1) + end + + it "should not be able to destroy enterprise relationships for other enterprises" do + is_expected.not_to have_ability(:destroy, for: er2) + end + + it "should be able to read some reports" do + is_expected.to have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management], for: Spree::Admin::ReportsController) + end + + include_examples "allows access to Enterprise Fee Summary" + + it "should not be able to read other reports" do + is_expected.not_to have_ability([:group_buys, :payments, :orders_and_distributors, :users_and_enterprises, :xero_invoices], for: Spree::Admin::ReportsController) + end + + it "should not be able to access customer actions" do + is_expected.not_to have_ability([:admin, :index, :update], for: Customer) + end + + describe "order_cycles abilities" do + context "where the enterprise is not in an order_cycle" do + let!(:order_cycle) { create(:simple_order_cycle) } + + it "should not be able to access read/update order_cycle actions" do + is_expected.not_to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) + end + + it "should not be able to access bulk_update, clone order cycle actions" do + is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) + end + + it "cannot request permitted enterprises for an order cycle" do + is_expected.not_to have_ability([:for_order_cycle], for: Enterprise) + end + + it "cannot request permitted enterprise fees for an order cycle" do + is_expected.not_to have_ability([:for_order_cycle], for: EnterpriseFee) + end + end + + context "where the enterprise is in an order_cycle" do + let!(:order_cycle) { create(:simple_order_cycle) } + let!(:exchange){ create(:exchange, incoming: true, order_cycle: order_cycle, receiver: order_cycle.coordinator, sender: s1) } + + it "should be able to access read/update order cycle actions" do + is_expected.to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) + end + + it "should not be able to access bulk/update, clone order cycle actions" do + is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) + end + + it "can request permitted enterprises for an order cycle" do + is_expected.to have_ability([:for_order_cycle], for: Enterprise) + end + + it "can request permitted enterprise fees for an order cycle" do + is_expected.to have_ability([:for_order_cycle], for: EnterpriseFee) + end + end + end + end + + context "when is a distributor enterprise user" do + # create distributor_enterprise1 user without full admin access + let(:user) do + user = create(:user) + user.spree_roles = [] + d1.enterprise_roles.build(user: user).save + user + end + # create order for each enterprise + let(:o1) do + o = create(:order, distributor: d1, bill_address: create(:address)) + create(:line_item, order: o, product: p1) + o + end + let(:o2) do + o = create(:order, distributor: d2, bill_address: create(:address)) + create(:line_item, order: o, product: p1) + o + end + let(:o3) do + o = create(:order, distributor: nil, bill_address: create(:address)) + create(:line_item, order: o, product: p1) + o + end + + describe "editing enterprises" do + let!(:d_related) { create(:distributor_enterprise) } + let!(:er_pd) { create(:enterprise_relationship, parent: d_related, child: d1, permissions_list: [:edit_profile]) } + + it "should be able to edit enterprises it manages" do + is_expected.to have_ability([:read, :edit, :update, :remove_logo, :remove_promo_image, :remove_terms_and_conditions, :bulk_update, :resend_confirmation], for: d1) + end + + it "should be able to edit enterprises it has permission to" do + is_expected.to have_ability([:read, :edit, :update, :remove_logo, :remove_promo_image, :remove_terms_and_conditions, :bulk_update, :resend_confirmation], for: d_related) + end + + it "should be able to manage shipping methods, payment methods and enterprise fees for enterprises it manages" do + is_expected.to have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d1) + end + + it "should not be able to manage shipping methods, payment methods and enterprise fees for enterprises it has edit profile permission to" do + is_expected.not_to have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d_related) + end + end + + describe "variant overrides" do + let(:vo1) { create(:variant_override, hub: d1, variant: p1.master) } + let(:vo2) { create(:variant_override, hub: d1, variant: p2.master) } + let(:vo3) { create(:variant_override, hub: d2, variant: p1.master) } + let(:vo4) { create(:variant_override, hub: d2, variant: p2.master) } + + let!(:er1) { create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:create_variant_overrides]) } + + it "should be able to access variant overrides page" do + is_expected.to have_ability([:admin, :index, :bulk_update, :bulk_reset], for: VariantOverride) + end + + it "should be able to read/write their own variant overrides" do + is_expected.to have_ability([:admin, :index, :read, :update], for: vo1) + end + + it "should not be able to read/write variant overrides when producer of product hasn't granted permission" do + is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo2) + end + + it "should not be able to read/write variant overrides when we can't add hub to order cycle" do + is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo3) + end + + it "should not be able to read/write other enterprises' variant overrides" do + is_expected.not_to have_ability([:admin, :index, :read, :update], for: vo4) + end + end + + it "should be able to read/write their enterprises' orders" do + is_expected.to have_ability([:admin, :index, :read, :edit], for: o1) + end + + it "should not be able to read/write other enterprises' orders" do + is_expected.not_to have_ability([:admin, :index, :read, :edit], for: o2) + end + + it "should be able to read/write orders that are in the process of being created" do + is_expected.to have_ability([:admin, :index, :read, :edit], for: o3) + end + + it "should be able to create and search on nil (required for creating an order)" do + is_expected.to have_ability([:create, :search], for: nil) + end + + it "should be able to create a new order" do + is_expected.to have_ability([:admin, :index, :read, :create, :update], for: Spree::Order) + end + + it "should be able to create a new line item" do + is_expected.to have_ability([:admin, :create], for: Spree::LineItem) + end + + it "should be able to read/write Payments on a product" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Payment) + end + + it "should be able to read/write Shipments on a product" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Shipment) + end + + it "should be able to read/write Adjustments on a product" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::Adjustment) + end + + it "should be able to read/write ReturnAuthorizations on a product" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :update, :fire], for: Spree::ReturnAuthorization) + end + + it "should be able to read/write PaymentMethods" do + is_expected.to have_ability([:admin, :index, :create, :update, :destroy], for: Spree::PaymentMethod) + end + + it "should be able to read/write ShippingMethods" do + is_expected.to have_ability([:admin, :index, :create, :update, :destroy], for: Spree::ShippingMethod) + end + + it "should be able to read and create enterprise relationships" do + is_expected.to have_ability([:admin, :index, :create], for: EnterpriseRelationship) + end + + it "should be able to destroy enterprise relationships for its enterprises" do + is_expected.to have_ability(:destroy, for: er2) + end + + it "should not be able to destroy enterprise relationships for other enterprises" do + is_expected.not_to have_ability(:destroy, for: er1) + end + + it "should be able to read some reports" do + is_expected.to have_ability([:admin, :index, :customers, :sales_tax, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :xero_invoices], for: Spree::Admin::ReportsController) + end + + include_examples "allows access to Enterprise Fee Summary" + + it "should not be able to read other reports" do + is_expected.not_to have_ability([:users_and_enterprises], for: Spree::Admin::ReportsController) + end + + it "should be able to access customer actions" do + is_expected.to have_ability([:admin, :index, :update], for: Customer) + end + + context "for a given order_cycle" do + let!(:order_cycle) { create(:simple_order_cycle) } + let!(:exchange){ create(:exchange, incoming: false, order_cycle: order_cycle, receiver: d1, sender: order_cycle.coordinator) } + + it "should be able to access read and update order cycle actions" do + is_expected.to have_ability([:admin, :index, :read, :edit, :update], for: order_cycle) + end + + it "should not be able to access bulk_update, clone order cycle actions" do + is_expected.not_to have_ability([:bulk_update, :clone], for: order_cycle) + end + end + + it "can request permitted enterprises for an order cycle" do + is_expected.to have_ability([:for_order_cycle], for: Enterprise) + end + + it "can request permitted enterprise fees for an order cycle" do + is_expected.to have_ability([:for_order_cycle], for: EnterpriseFee) + end + end + + context 'Order Cycle co-ordinator, distributor enterprise manager' do + let(:user) do + user = create(:user) + user.spree_roles = [] + d1.enterprise_roles.build(user: user).save + user + end + + let(:oc1) { create(:simple_order_cycle, coordinator: d1) } + let(:oc2) { create(:simple_order_cycle) } + + it "should be able to read/write OrderCycles they are the co-ordinator of" do + is_expected.to have_ability([:admin, :index, :read, :edit, :update, :bulk_update, :clone, :destroy], for: oc1) + end + + it "should not be able to read/write OrderCycles they are not the co-ordinator of" do + should_not have_ability([:admin, :index, :read, :create, :edit, :update, :bulk_update, :clone, :destroy], for: oc2) + end + + it "should be able to create OrderCycles" do + is_expected.to have_ability([:create], for: OrderCycle) + end + + it "should be able to read/write EnterpriseFees" do + is_expected.to have_ability([:admin, :index, :read, :create, :edit, :bulk_update, :destroy, :for_order_cycle], for: EnterpriseFee) + end + + it "should be able to add enterprises to order cycles" do + is_expected.to have_ability([:admin, :index, :for_order_cycle, :create], for: Enterprise) + end + end + + context 'enterprise manager' do + let(:user) do + user = create(:user) + user.spree_roles = [] + s1.enterprise_roles.build(user: user).save + user + end + + it 'should have the ability to view the admin account page' do + is_expected.to have_ability([:admin, :show], for: :account) + end + + it 'should have the ability to read and edit enterprises that I manage' do + is_expected.to have_ability([:read, :edit, :update, :bulk_update], for: s1) + end + + it 'should not have the ability to read and edit enterprises that I do not manage' do + is_expected.not_to have_ability([:read, :edit, :update, :bulk_update], for: s2) + end + + it 'should not have the ability to welcome and register enterprises that I do not own' do + is_expected.not_to have_ability([:welcome, :register], for: s1) + end + + it 'should have the ability administrate and create enterpises' do + is_expected.to have_ability([:admin, :index, :create], for: Enterprise) + end + + it "should have the ability to search for users which share management of its enterprises" do + is_expected.to have_ability([:admin, :known_users, :customers], for: :search) + is_expected.not_to have_ability([:users], for: :search) + end + end + + context 'enterprise owner' do + let(:user) { s1.owner } + + it 'should have the ability to welcome and register enterprises that I own' do + is_expected.to have_ability([:welcome, :register], for: s1) + end + + it 'should have the ability to view the admin account page' do + is_expected.to have_ability([:admin, :show], for: :account) + end + end + end + + describe "permissions for variant overrides" do + let!(:distributor) { create(:distributor_enterprise) } + let!(:producer) { create(:supplier_enterprise) } + let!(:product) { create(:product, supplier: producer) } + let!(:variant) { create(:variant, product: product) } + let!(:variant_override) { create(:variant_override, hub: distributor, variant: variant) } + + subject { user } + + let(:manage_actions) { [:admin, :index, :read, :update, :bulk_update, :bulk_reset] } + + describe "when admin" do + let(:user) { create(:admin_user) } + + it "should have permission" do + is_expected.to have_ability(manage_actions, for: variant_override) + end + end + + describe "when user of the producer" do + let(:user) { producer.owner } + + it "should not have permission" do + is_expected.not_to have_ability(manage_actions, for: variant_override) + end + end + + describe "when user of the distributor" do + let(:user) { distributor.owner } + + it "should not have permission" do + is_expected.not_to have_ability(manage_actions, for: variant_override) + end + end + + describe "when user of the distributor which is also the producer" do + let(:user) { distributor.owner } + let!(:distributor) { create(:distributor_enterprise, is_primary_producer: true, sells: "any") } + let!(:producer) { distributor } + + it "should have permission" do + is_expected.to have_ability(manage_actions, for: variant_override) + end + end + + describe "when owner of the distributor with add_to_order_cycle permission to the producer" do + let!(:unauthorized_enterprise) do + create(:enterprise, sells: "any").tap do |record| + create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:add_to_order_cycle]) + end + end + let(:user) { unauthorized_enterprise.owner } + + it "should not have permission" do + is_expected.not_to have_ability(manage_actions, for: variant_override) + end + end + + describe "when owner of the enterprise with create_variant_overrides permission to the producer" do + let!(:authorized_enterprise) do + create(:enterprise, sells: "any").tap do |record| + create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:create_variant_overrides]) + end + end + let(:user) { authorized_enterprise.owner } + + it "should not have permission" do + is_expected.not_to have_ability(manage_actions, for: variant_override) + end + + describe "when the enterprise is not a distributor" do + let!(:authorized_enterprise) do + create(:enterprise, sells: "none").tap do |record| + create(:enterprise_relationship, parent: producer, child: record, permissions_list: [:create_variant_overrides]) + end + end + + it "should not have permission" do + is_expected.not_to have_ability(manage_actions, for: variant_override) + end + end + end + end end diff --git a/spec/support/ability_helpers.rb b/spec/support/ability_helpers.rb index 0d42bbf7c2..4dcb840fe7 100644 --- a/spec/support/ability_helpers.rb +++ b/spec/support/ability_helpers.rb @@ -2,106 +2,106 @@ shared_examples_for 'access granted' do it 'should allow read' do - expect(ability).to be_able_to(:read, resource, token) if token - expect(ability).to be_able_to(:read, resource) unless token + expect(subject).to be_able_to(:read, resource, token) if token + expect(subject).to be_able_to(:read, resource) unless token end it 'should allow create' do - expect(ability).to be_able_to(:create, resource, token) if token - expect(ability).to be_able_to(:create, resource) unless token + expect(subject).to be_able_to(:create, resource, token) if token + expect(subject).to be_able_to(:create, resource) unless token end it 'should allow update' do - expect(ability).to be_able_to(:update, resource, token) if token - expect(ability).to be_able_to(:update, resource) unless token + expect(subject).to be_able_to(:update, resource, token) if token + expect(subject).to be_able_to(:update, resource) unless token end end shared_examples_for 'access denied' do it 'should not allow read' do - expect(ability).to_not be_able_to(:read, resource) + expect(subject).to_not be_able_to(:read, resource) end it 'should not allow create' do - expect(ability).to_not be_able_to(:create, resource) + expect(subject).to_not be_able_to(:create, resource) end it 'should not allow update' do - expect(ability).to_not be_able_to(:update, resource) + expect(subject).to_not be_able_to(:update, resource) end end shared_examples_for 'admin granted' do it 'should allow admin' do - expect(ability).to be_able_to(:admin, resource, token) if token - expect(ability).to be_able_to(:admin, resource) unless token + expect(subject).to be_able_to(:admin, resource, token) if token + expect(subject).to be_able_to(:admin, resource) unless token end end shared_examples_for 'admin denied' do it 'should not allow admin' do - expect(ability).to_not be_able_to(:admin, resource) + expect(subject).to_not be_able_to(:admin, resource) end end shared_examples_for 'index allowed' do it 'should allow index' do - expect(ability).to be_able_to(:index, resource) + expect(subject).to be_able_to(:index, resource) end end shared_examples_for 'no index allowed' do it 'should not allow index' do - expect(ability).to_not be_able_to(:index, resource) + expect(subject).to_not be_able_to(:index, resource) end end shared_examples_for 'create only' do it 'should allow create' do - expect(ability).to be_able_to(:create, resource) + expect(subject).to be_able_to(:create, resource) end it 'should not allow read' do - expect(ability).to_not be_able_to(:read, resource) + expect(subject).to_not be_able_to(:read, resource) end it 'should not allow update' do - expect(ability).to_not be_able_to(:update, resource) + expect(subject).to_not be_able_to(:update, resource) end it 'should not allow index' do - expect(ability).to_not be_able_to(:index, resource) + expect(subject).to_not be_able_to(:index, resource) end end shared_examples_for 'read only' do it 'should not allow create' do - expect(ability).to_not be_able_to(:create, resource) + expect(subject).to_not be_able_to(:create, resource) end it 'should not allow update' do - expect(ability).to_not be_able_to(:update, resource) + expect(subject).to_not be_able_to(:update, resource) end it 'should allow index' do - expect(ability).to be_able_to(:index, resource) + expect(subject).to be_able_to(:index, resource) end end shared_examples_for 'update only' do it 'should not allow create' do - expect(ability).to_not be_able_to(:create, resource) + expect(subject).to_not be_able_to(:create, resource) end it 'should not allow read' do - expect(ability).to_not be_able_to(:read, resource) + expect(subject).to_not be_able_to(:read, resource) end it 'should allow update' do - expect(ability).to be_able_to(:update, resource) + expect(subject).to be_able_to(:update, resource) end it 'should not allow index' do - expect(ability).to_not be_able_to(:index, resource) + expect(subject).to_not be_able_to(:index, resource) end end From 60ef32300b32fa8dcce78e1e9c2a5d3b90284937 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 4 Sep 2020 13:56:16 +0100 Subject: [PATCH 09/17] No need to test code with different ability setup, this was a good spec for spree, in ofn we use and test the static auth config in Ability --- .../spree/admin/users_controller_spec.rb | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/spec/controllers/spree/admin/users_controller_spec.rb b/spec/controllers/spree/admin/users_controller_spec.rb index f67417e1fe..2a67433db3 100644 --- a/spec/controllers/spree/admin/users_controller_spec.rb +++ b/spec/controllers/spree/admin/users_controller_spec.rb @@ -33,33 +33,6 @@ describe Spree::Admin::UsersController do expect(response).to redirect_to(spree.edit_admin_user_path(test_user)) end - describe "with BarAbility" do - class BarAbility - include CanCan::Ability - - def initialize(user) - user ||= Spree::User.new - return unless user.has_spree_role?('bar') - - can [:admin, :index, :show], Spree::Order - end - end - - it 'should deny access to users with an bar role' do - user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') - Spree::Ability.register_ability(BarAbility) - spree_post :index - expect(response).to redirect_to('/unauthorized') - end - - it 'should deny access to users with an bar role' do - user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') - Spree::Ability.register_ability(BarAbility) - spree_post :update, id: '9' - expect(response).to redirect_to('/unauthorized') - end - end - it 'should deny access to users without an admin role' do allow(user).to receive_messages has_spree_role?: false spree_post :index From 8234ad09065d2ba223694079cf37c150a5d78a33 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 4 Sep 2020 14:06:06 +0100 Subject: [PATCH 10/17] Ensure test order cycle coordinator is really an enterprise not managed by the user instead of relying on the factory logic --- spec/models/spree/ability_spec.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 00850efdb8..7534871faf 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -466,7 +466,6 @@ describe Spree::Ability do end context "when is a distributor enterprise user" do - # create distributor_enterprise1 user without full admin access let(:user) do user = create(:user) user.spree_roles = [] @@ -615,7 +614,7 @@ describe Spree::Ability do end context "for a given order_cycle" do - let!(:order_cycle) { create(:simple_order_cycle) } + let!(:order_cycle) { create(:simple_order_cycle, coordinator: d2) } let!(:exchange){ create(:exchange, incoming: false, order_cycle: order_cycle, receiver: d1, sender: order_cycle.coordinator) } it "should be able to access read and update order cycle actions" do @@ -645,7 +644,7 @@ describe Spree::Ability do end let(:oc1) { create(:simple_order_cycle, coordinator: d1) } - let(:oc2) { create(:simple_order_cycle) } + let(:oc2) { create(:simple_order_cycle, coordinator: d2) } it "should be able to read/write OrderCycles they are the co-ordinator of" do is_expected.to have_ability([:admin, :index, :read, :edit, :update, :bulk_update, :clone, :destroy], for: oc1) From ecdba1fa4e91562a78e9e581e46dadb0da5aee62 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 4 Sep 2020 14:19:50 +0100 Subject: [PATCH 11/17] For some reason the factory create(:admin_user) is not working here, this new version works --- spec/models/spree/ability_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 7534871faf..c20fda569c 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -726,7 +726,7 @@ describe Spree::Ability do let(:manage_actions) { [:admin, :index, :read, :update, :bulk_update, :bulk_reset] } describe "when admin" do - let(:user) { create(:admin_user) } + before { user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') } it "should have permission" do is_expected.to have_ability(manage_actions, for: variant_override) From 455111093d8ebfc9720386d2d051693c8ae6db1a Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 4 Sep 2020 14:27:25 +0100 Subject: [PATCH 12/17] Fix easy rubocop issues --- app/models/spree/ability.rb | 46 +++++++++++++++++++------------ spec/models/spree/ability_spec.rb | 2 +- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index 4b9bd1d057..a7d12ce2b6 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -47,7 +47,7 @@ module Spree end add_shopping_abilities user - add_base_abilities user if is_new_user? user + add_base_abilities user if new_user? user add_enterprise_management_abilities user if can_manage_enterprises? user add_group_management_abilities user if can_manage_groups? user add_product_management_abilities user if can_manage_products? user @@ -57,7 +57,7 @@ module Spree end # New users have no enterprises. - def is_new_user?(user) + def new_user?(user) user.enterprises.blank? end @@ -126,8 +126,8 @@ module Spree end def add_enterprise_management_abilities(user) - # Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil) - # when searching for variants to add to the order + # We perform authorize! on (:create, nil) when creating a new order from admin, + # and also (:search, nil) when searching for variants to add to the order can [:create, :search], nil can [:admin, :index], :overview @@ -147,7 +147,9 @@ module Spree can [:welcome, :register], Enterprise do |enterprise| enterprise.owner == user end - can [:manage_payment_methods, :manage_shipping_methods, :manage_enterprise_fees], Enterprise do |enterprise| + can [:manage_payment_methods, + :manage_shipping_methods, + :manage_enterprise_fees], Enterprise do |enterprise| user.enterprises.include? enterprise end @@ -188,8 +190,10 @@ module Spree end can [:create], Spree::Variant - can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant| - OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier + can [:admin, :index, :read, :edit, + :update, :search, :delete, :destroy], Spree::Variant do |variant| + OpenFoodNetwork::Permissions.new(user). + managed_product_enterprises.include? variant.product.supplier end can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo| @@ -207,7 +211,8 @@ module Spree end can [:admin, :create, :update], InventoryItem do |ii| - next false unless ii.enterprise.present? && ii.variant.andand.product.andand.supplier.present? + next false unless ii.enterprise.present? && + ii.variant.andand.product.andand.supplier.present? hub_auth = OpenFoodNetwork::Permissions.new(user). variant_override_hubs. @@ -220,13 +225,15 @@ module Spree hub_auth && producer_auth end - can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], Spree::ProductProperty + can [:admin, :index, :read, :create, + :edit, :update_positions, :destroy], Spree::ProductProperty can [:admin, :index, :read, :create, :edit, :update, :destroy], Spree::Image can [:admin, :index, :read, :search], Spree::Taxon can [:admin, :index, :read, :create, :edit], Spree::Classification - can [:admin, :index, :guide, :import, :save, :save_data, :validate_data, :reset_absent_products], ProductImport::ProductImporter + can [:admin, :index, :guide, :import, :save, :save_data, + :validate_data, :reset_absent_products], ProductImport::ProductImporter # Reports page can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :payments, @@ -271,7 +278,9 @@ module Spree can [:admin, :index, :create], Spree::LineItem can [:destroy, :update], Spree::LineItem do |item| order = item.order - user.admin? || user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + user.admin? || + user.enterprises.include?(order.distributor) || + order.order_cycle.andand.coordinated_by?(user) end can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment @@ -279,15 +288,16 @@ module Spree can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization can [:destroy], Spree::Adjustment do |adjustment| - # Sharing code with destroying a line item. This should be unified and probably applied for other actions as well. if user.admin? true elsif adjustment.adjustable.instance_of? Spree::Order order = adjustment.adjustable - user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + user.enterprises.include?(order.distributor) || + order.order_cycle.andand.coordinated_by?(user) elsif adjustment.adjustable.instance_of? Spree::LineItem order = adjustment.adjustable.order - user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user) + user.enterprises.include?(order.distributor) || + order.order_cycle.andand.coordinated_by?(user) end end @@ -299,7 +309,8 @@ module Spree # Enterprise user can only access payment and shipping methods for their distributors can [:index, :create], Spree::PaymentMethod - can [:admin, :read, :update, :fire, :resend, :destroy, :show_provider_preferences], Spree::PaymentMethod do |payment_method| + can [:admin, :read, :update, :fire, :resend, + :destroy, :show_provider_preferences], Spree::PaymentMethod do |payment_method| (user.enterprises & payment_method.distributors).any? end @@ -316,7 +327,8 @@ module Spree add_enterprise_fee_summary_abilities can [:create], Customer - can [:admin, :index, :update, :destroy, :show], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id) + can [:admin, :index, :update, + :destroy, :show], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id) can [:admin, :new, :index], Subscription can [:create, :edit, :update, :cancel, :pause, :unpause], Subscription do |subscription| user.enterprises.include?(subscription.shop) @@ -349,6 +361,6 @@ module Spree can [:enterprise_fee_summary], Spree::Admin::ReportsController # Allow direct access to the report resource can [:admin, :new, :create], :enterprise_fee_summary - end + end end end diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index c20fda569c..7838b0093d 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -306,7 +306,7 @@ describe Spree::Ability do it { expect(subject.can_manage_order_cycles?(user)).to be false } it "can create enterprises straight off the bat" do - expect(subject.is_new_user?(user)).to be true + expect(subject.new_user?(user)).to be true expect(user).to have_ability :create, for: Enterprise end end From a8726679126a6b9fb5c35f9e1c8164507ffcce8c Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 18 Sep 2020 15:28:43 +0100 Subject: [PATCH 13/17] Add yarn.lock after yarn was added in ofn-install and installed in all servers, every ofn deploy will run yarn install now --- yarn.lock | 1804 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1804 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..6b3a7a9d05 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1804 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca" + integrity sha1-w8p0NJOGSMPg2cHjKN1otiLChMo= + dependencies: + mime-types "~2.1.11" + negotiator "0.6.1" + +after@0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arraybuffer.slice@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz#f33b2159f0532a3f3107a272c0ccfbd1ad2979ca" + integrity sha1-8zshWfBTKj8xB6JywMz70a0peco= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + +base64id@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" + integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" + integrity sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ= + +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + dependencies: + callsite "1.0.0" + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +blob@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" + integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE= + +bluebird@^2.9.27: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + integrity sha1-U0uQM8AiyVecVro7Plpcqvu2UOE= + +body-parser@^1.12.4: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^0.1.2: + version "0.1.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" + integrity sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY= + dependencies: + expand-range "^0.1.0" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + +chokidar@^1.4.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +coffee-script@~1: + version "1.12.7" + resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" + integrity sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +colors@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + +component-emitter@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.1.2.tgz#296594f2753daa63996d2af08d15a95116c9aec3" + integrity sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM= + +component-emitter@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +connect@^3.3.5: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js@^2.1.0: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= + dependencies: + ms "0.7.1" + +debug@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.3.3.tgz#40c453e67e6e13c901ddec317af8986cda9eff8c" + integrity sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w= + dependencies: + ms "0.7.2" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= + +dom-serialize@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +engine.io-client@~1.8.4: + version "1.8.5" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.5.tgz#fe7fb60cb0dcf2fa2859489329cb5968dedeb11f" + integrity sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg== + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "2.3.3" + engine.io-parser "1.3.2" + has-cors "1.1.0" + indexof "0.0.1" + parsejson "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~1.1.5" + xmlhttprequest-ssl "1.5.3" + yeast "0.1.2" + +engine.io-parser@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-1.3.2.tgz#937b079f0007d0893ec56d46cb220b8cb435220a" + integrity sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo= + dependencies: + after "0.8.2" + arraybuffer.slice "0.0.6" + base64-arraybuffer "0.1.5" + blob "0.0.4" + has-binary "0.1.7" + wtf-8 "1.0.0" + +engine.io@~1.8.4: + version "1.8.5" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-1.8.5.tgz#4ebe5e75c6dc123dee4afdce6e5fdced21eb93f6" + integrity sha512-j1DWIcktw4hRwrv6nWx++5nFH2X64x16MAG2P0Lmi5Dvdfi3I+Jhc7JKJIdAmDJa+5aZ/imHV7dWRPy2Cqjh3A== + dependencies: + accepts "1.3.3" + base64id "1.0.0" + cookie "0.3.1" + debug "2.3.3" + engine.io-parser "1.3.2" + ws "~1.1.5" + +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +expand-braces@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" + integrity sha1-SIsdHSRRyz06axks/AMPRMWFX+o= + dependencies: + array-slice "^0.2.3" + array-unique "^0.2.1" + braces "^0.1.2" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" + integrity sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ= + dependencies: + is-number "^0.1.1" + repeat-string "^0.2.2" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +follow-redirects@^1.0.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fs-access@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" + integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o= + dependencies: + null-check "^1.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.0.0: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + +glob@^7.0.0, glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +has-binary@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-binary/-/has-binary-0.1.7.tgz#68e61eb16210c9545a0a5cce06a873912fe1e68c" + integrity sha1-aOYesWIQyVRaClzOBqhzkS/h5ow= + dependencies: + isarray "0.0.1" + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-proxy@^1.13.0: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + +is-number@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" + integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY= + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isbinaryfile@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" + integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== + dependencies: + buffer-alloc "^1.2.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +jasmine-core@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.4.1.tgz#6f83ab3a0f16951722ce07d206c773d57cc838be" + integrity sha1-b4OrOg8WlRcizgfSBsdz1XzIOL4= + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + +karma-chrome-launcher@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf" + integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w== + dependencies: + fs-access "^1.0.0" + which "^1.2.1" + +karma-coffee-preprocessor@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/karma-coffee-preprocessor/-/karma-coffee-preprocessor-0.3.0.tgz#a4d8dc2b145bfef458a203d308b63bc03c9b4259" + integrity sha1-pNjcKxRb/vRYogPTCLY7wDybQlk= + dependencies: + coffee-script "~1" + +karma-jasmine@~0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-0.3.8.tgz#5b6457791ad9b89aa173f079e3ebe1b8c805236c" + integrity sha1-W2RXeRrZuJqhc/B54+vhuMgFI2w= + +karma@~0.13.22: + version "0.13.22" + resolved "https://registry.yarnpkg.com/karma/-/karma-0.13.22.tgz#07750b1bd063d7e7e7b91bcd2e6354d8f2aa8744" + integrity sha1-B3ULG9Bj1+fnuRvNLmNU2PKqh0Q= + dependencies: + batch "^0.5.3" + bluebird "^2.9.27" + body-parser "^1.12.4" + chokidar "^1.4.1" + colors "^1.1.0" + connect "^3.3.5" + core-js "^2.1.0" + di "^0.0.1" + dom-serialize "^2.2.0" + expand-braces "^0.1.1" + glob "^7.0.0" + graceful-fs "^4.1.2" + http-proxy "^1.13.0" + isbinaryfile "^3.0.0" + lodash "^3.8.0" + log4js "^0.6.31" + mime "^1.3.4" + minimatch "^3.0.0" + optimist "^0.6.1" + rimraf "^2.3.3" + socket.io "^1.4.5" + source-map "^0.5.3" + useragent "^2.1.6" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +lodash@^3.8.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= + +log4js@^0.6.31: + version "0.6.38" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" + integrity sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0= + dependencies: + readable-stream "~1.0.2" + semver "~4.3.3" + +lru-cache@4.1.x: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-types@~2.1.11, mime-types@~2.1.24: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + dependencies: + mime-db "1.44.0" + +mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +minimatch@^3.0.0, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + integrity sha1-riXPJRKziFodldfwN4aNhDESR2U= + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +nan@^2.12.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +null-check@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" + integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + integrity sha1-ejs9DpgGPUP0wD8uiubNUahog6A= + +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parsejson@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" + integrity sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs= + dependencies: + better-assert "~1.0.0" + +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + dependencies: + better-assert "~1.0.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.2: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.0.2: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" + integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4= + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.3.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@~4.3.3: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socket.io-adapter@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" + integrity sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s= + dependencies: + debug "2.3.3" + socket.io-parser "2.3.1" + +socket.io-client@1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-1.7.4.tgz#ec9f820356ed99ef6d357f0756d648717bdd4281" + integrity sha1-7J+CA1btme9tNX8HVtZIcXvdQoE= + dependencies: + backo2 "1.0.2" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "2.3.3" + engine.io-client "~1.8.4" + has-binary "0.1.7" + indexof "0.0.1" + object-component "0.0.3" + parseuri "0.0.5" + socket.io-parser "2.3.1" + to-array "0.1.4" + +socket.io-parser@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-2.3.1.tgz#dd532025103ce429697326befd64005fcfe5b4a0" + integrity sha1-3VMgJRA85Clpcya+/WQAX8/ltKA= + dependencies: + component-emitter "1.1.2" + debug "2.2.0" + isarray "0.0.1" + json3 "3.3.2" + +socket.io@^1.4.5: + version "1.7.4" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-1.7.4.tgz#2f7ecedc3391bf2d5c73e291fe233e6e34d4dd00" + integrity sha1-L37O3DORvy1cc+KR/iM+bjTU3QA= + dependencies: + debug "2.3.3" + engine.io "~1.8.4" + has-binary "0.1.7" + object-assign "4.1.0" + socket.io-adapter "0.5.0" + socket.io-client "1.7.4" + socket.io-parser "2.3.1" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.3, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +tmp@0.0.x: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +type-is@~1.6.17: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +useragent@^2.1.6: + version "2.3.0" + resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972" + integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw== + dependencies: + lru-cache "4.1.x" + tmp "0.0.x" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + +which@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@~1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + integrity sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w== + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +wtf-8@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" + integrity sha1-OS2LotDxw00e4tYw8V0O+2jhBIo= + +xmlhttprequest-ssl@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d" + integrity sha1-GFqIjATspGw+QHDZn3tJ3jUomS0= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= From 5b3f700fb4f66750cc1b9ee96f24f63137022d10 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 18 Sep 2020 15:29:38 +0100 Subject: [PATCH 14/17] Move momentjs from a Gemfile dependeny to a package.jons dependency and upgrade it from 2.20.1 to 2.28.0 --- Gemfile | 1 - Gemfile.lock | 3 --- package.json | 11 +++++++---- yarn.lock | 5 +++++ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index 682b445502..bc40aaa865 100644 --- a/Gemfile +++ b/Gemfile @@ -117,7 +117,6 @@ gem 'uglifier', '>= 1.0.3' gem 'angular-rails-templates', '~> 0.3.0' gem 'foundation-icons-sass-rails' -gem 'momentjs-rails' gem 'foundation-rails', '= 5.5.2.1' diff --git a/Gemfile.lock b/Gemfile.lock index b83aa83858..e283cfc2b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -462,8 +462,6 @@ GEM mini_racer (0.2.15) libv8 (> 7.3) minitest (4.7.5) - momentjs-rails (2.20.1) - railties (>= 3.1) money (5.1.1) i18n (~> 0.6.0) msgpack (1.3.3) @@ -768,7 +766,6 @@ DEPENDENCIES knapsack letter_opener (>= 1.4.1) mini_racer (= 0.2.15) - momentjs-rails money (= 5.1.1) newrelic_rpm (~> 3.0) oauth2 (~> 1.4.4) diff --git a/package.json b/package.json index 53c751067d..2bc846b667 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,14 @@ "url": "https://github.com/openfoodfoundation/openfoodnetwork" }, "devDependencies": { + "jasmine-core": "~2.4.1", "karma": "~0.13.22", "karma-chrome-launcher": "~2.2.0", - "karma-jasmine": "~0.3.8", - "jasmine-core": "~2.4.1", - "karma-coffee-preprocessor": "~0.3.0" + "karma-coffee-preprocessor": "~0.3.0", + "karma-jasmine": "~0.3.8" }, - "license": "AGPL-1.0" + "license": "AGPL-1.0", + "dependencies": { + "moment": "^2.28.0" + } } diff --git a/yarn.lock b/yarn.lock index 6b3a7a9d05..fcf257f4ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1173,6 +1173,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +moment@^2.28.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.28.0.tgz#cdfe73ce01327cee6537b0fafac2e0f21a237d75" + integrity sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw== + ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" From d4c4bcaa50b1da9533ebb3a04f030f226c23eacd Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 18 Sep 2020 15:53:34 +0100 Subject: [PATCH 15/17] Make node_modules available for code in app/assets --- app/assets/javascripts/admin/all.js | 2 +- app/assets/javascripts/darkswarm/all.js.coffee | 2 +- config/initializers/assets.rb | 1 + spec/javascripts/application_spec.js | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 config/initializers/assets.rb diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index c43f365cb6..47d5487631 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -71,7 +71,7 @@ //= require textAngular.min.js //= require i18n/translations //= require darkswarm/i18n.translate.js -//= require moment +//= require moment/min/moment.min.js //= require moment/de.js //= require moment/en-gb.js //= require moment/es.js diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index 51209fadd6..41f4c5147c 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -28,7 +28,7 @@ #= require angular-backstretch.js #= require angular-flash.min.js # -#= require moment +#= require moment/min/moment.min.js #= require moment/de.js #= require moment/en-gb.js #= require moment/es.js diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000000..2e9af484ab --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1 @@ +Rails.application.config.assets.paths << Rails.root.join('node_modules') diff --git a/spec/javascripts/application_spec.js b/spec/javascripts/application_spec.js index 47368298f8..24c76ce9d7 100644 --- a/spec/javascripts/application_spec.js +++ b/spec/javascripts/application_spec.js @@ -12,7 +12,7 @@ //= require textAngular-rangy.min.js //= require textAngular-sanitize.min.js //= require textAngular.min.js -//= require moment +//= require moment/min/moment.min.js //= require i18n angular.module('templates', []) From 2fae7e0df3e688fc43dc356a8092a50bf8371edb Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Fri, 18 Sep 2020 16:18:24 +0100 Subject: [PATCH 16/17] Use moment js min and locale files from node_modules In this commit fil and nl-be are also added We could use moment/min/locales.min.js but that would add all locales available in moment which would be a move in size from current 30k in moment locales to 300k --- app/assets/javascripts/admin/all.js | 28 ++++++++++--------- .../javascripts/darkswarm/all.js.coffee | 28 ++++++++++--------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 47d5487631..cc11bafd58 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -72,19 +72,21 @@ //= require i18n/translations //= require darkswarm/i18n.translate.js //= require moment/min/moment.min.js -//= require moment/de.js -//= require moment/en-gb.js -//= require moment/es.js -//= require moment/fr.js -//= require moment/it.js -//= require moment/nb.js -//= require moment/pt-br.js -//= require moment/pt.js -//= require moment/ru.js -//= require moment/sv.js -//= require moment/ca.js -//= require moment/ar.js -//= require moment/tr.js +//= require moment/locale/ar.js +//= require moment/locale/ca.js +//= require moment/locale/de.js +//= require moment/locale/en-gb.js +//= require moment/locale/es.js +//= require moment/locale/fil.js +//= require moment/locale/fr.js +//= require moment/locale/it.js +//= require moment/locale/nb.js +//= require moment/locale/nl-be.js +//= require moment/locale/pt-br.js +//= require moment/locale/pt.js +//= require moment/locale/ru.js +//= require moment/locale/sv.js +//= require moment/locale/tr.js // foundation //= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index 41f4c5147c..fe4564fc97 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -29,19 +29,21 @@ #= require angular-flash.min.js # #= require moment/min/moment.min.js -#= require moment/de.js -#= require moment/en-gb.js -#= require moment/es.js -#= require moment/fr.js -#= require moment/it.js -#= require moment/nb.js -#= require moment/pt-br.js -#= require moment/pt.js -#= require moment/ru.js -#= require moment/sv.js -#= require moment/ca.js -#= require moment/ar.js -#= require moment/tr.js +#= require moment/locale/ar.js +#= require moment/locale/ca.js +#= require moment/locale/de.js +#= require moment/locale/en-gb.js +#= require moment/locale/es.js +#= require moment/locale/fil.js +#= require moment/locale/fr.js +#= require moment/locale/it.js +#= require moment/locale/nb.js +#= require moment/locale/nl-be.js +#= require moment/locale/pt-br.js +#= require moment/locale/pt.js +#= require moment/locale/ru.js +#= require moment/locale/sv.js +#= require moment/locale/tr.js # #= require modernizr # From fe7d7b54d10258da884775ac12475e09572090ea Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Thu, 9 Apr 2020 23:22:40 +0100 Subject: [PATCH 17/17] Make version number 1.0.0 as we dont want to mantain the app version here and update AGPL to v3 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2bc846b667..da0b3da45c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openfoodnetwork", - "version": "1.7.1", + "version": "1.0.0", "repository": { "type": "git", "url": "https://github.com/openfoodfoundation/openfoodnetwork" @@ -12,7 +12,7 @@ "karma-coffee-preprocessor": "~0.3.0", "karma-jasmine": "~0.3.8" }, - "license": "AGPL-1.0", + "license": "AGPL-3.0", "dependencies": { "moment": "^2.28.0" }