From 2f2ebf419ca727f4d1e9ff4b076a9f4ccf739028 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 29 Oct 2015 16:47:56 +1100 Subject: [PATCH] Fixing customer info security for packing reports --- lib/open_food_network/packing_report.rb | 28 +++-- .../open_food_network/packing_report_spec.rb | 110 ++++++++++-------- 2 files changed, 81 insertions(+), 57 deletions(-) diff --git a/lib/open_food_network/packing_report.rb b/lib/open_food_network/packing_report.rb index 5b069fffdb..4f2c54da9e 100644 --- a/lib/open_food_network/packing_report.rb +++ b/lib/open_food_network/packing_report.rb @@ -15,19 +15,27 @@ module OpenFoodNetwork end def search - Spree::Order.complete.not_state(:canceled).managed_by(@user).search(params[:q]) - end - - def orders - search.result + Spree::Order.complete.not_state(:canceled).search(params[:q]) end def table_items - @line_items = orders.map do |o| - lis = o.line_items.managed_by(@user) - lis = lis.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? - lis - end.flatten + permissions = OpenFoodNetwork::Permissions.new(@user) + orders = permissions.visible_orders.merge(search.result) + + line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders)) + line_items = line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? + + line_items_with_hidden_details = + permissions.editable_line_items.empty? ? line_items : line_items.where('"spree_line_items"."id" NOT IN (?)', permissions.editable_line_items) + + line_items.select{ |li| line_items_with_hidden_details.include? li }.each do |line_item| + # TODO We should really be hiding customer code here too, but until we + # have an actual association between order and customer, it's a bit tricky + line_item.order.bill_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.ship_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.assign_attributes(email: "HIDDEN") + end + line_items end def rules diff --git a/spec/lib/open_food_network/packing_report_spec.rb b/spec/lib/open_food_network/packing_report_spec.rb index 40e3d44c9e..6b02a26fed 100644 --- a/spec/lib/open_food_network/packing_report_spec.rb +++ b/spec/lib/open_food_network/packing_report_spec.rb @@ -4,76 +4,92 @@ include AuthenticationWorkflow module OpenFoodNetwork describe PackingReport do - context "as a site admin" do - let(:user) do - user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!("admin") - user - end - subject { PackingReport.new user } + describe "fetching orders" do + let(:d1) { create(:distributor_enterprise) } + let(:oc1) { create(:simple_order_cycle) } + let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } + let(:li1) { build(:line_item) } + + before { o1.line_items << li1 } + + context "as a site admin" do + let(:user) { create(:admin_user) } + subject { PackingReport.new user } - describe "fetching orders" do it "fetches completed orders" do - o1 = create(:order) - o2 = create(:order, completed_at: 1.day.ago) - subject.orders.should == [o2] + o2 = create(:order) + o2.line_items << build(:line_item) + subject.table_items.should == [li1] end it "does not show cancelled orders" do - o1 = create(:order, state: "canceled", completed_at: 1.day.ago) - o2 = create(:order, completed_at: 1.day.ago) - subject.orders.should == [o2] + o2 = create(:order, state: "canceled", completed_at: 1.day.ago) + o2.line_items << build(:line_item) + subject.table_items.should == [li1] end end - end - context "as an enterprise user" do - let!(:user) { create_enterprise_user } + context "as a manager of a supplier" do + let!(:user) { create(:user) } + subject { PackingReport.new user } - subject { PackingReport.new user } + let(:s1) { create(:supplier_enterprise) } - describe "fetching orders" do - let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier: supplier) } - let(:d1) { create(:distributor_enterprise) } - let(:oc1) { create(:simple_order_cycle) } - let(:order) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } + before do + s1.enterprise_roles.create!(user: user) + end + + context "that has granted P-OC to the distributor" do + let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } + let(:li2) { build(:line_item, product: create(:simple_product, supplier: s1)) } + + before do + o2.line_items << li2 + create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:add_to_order_cycle]) + end + + it "shows line items supplied by my producers, with names hidden" do + subject.table_items.should == [li2] + subject.table_items.first.order.bill_address.firstname.should == "HIDDEN" + end + end + + context "that has not granted P-OC to the distributor" do + let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } + let(:li2) { build(:line_item, product: create(:simple_product, supplier: s1)) } + + before do + o2.line_items << li2 + end + + it "shows line items supplied by my producers, with names hidden" do + subject.table_items.should == [] + end + end + end + + context "as a manager of a distributor" do + let!(:user) { create(:user) } + subject { PackingReport.new user } before do d1.enterprise_roles.create!(user: user) end - it "only shows orders managed by the current user" do + it "only shows line items distributed by enterprises managed by the current user" do d2 = create(:distributor_enterprise) d2.enterprise_roles.create!(user: create(:user)) o2 = create(:order, distributor: d2, completed_at: 1.day.ago) - - subject.orders.should == [order] + o2.line_items << build(:line_item) + subject.table_items.should == [li1] end it "only shows the selected order cycle" do oc2 = create(:simple_order_cycle) - order2 = create(:order, order_cycle: oc2) + o2 = create(:order, distributor: d1, order_cycle: oc2) + o2.line_items << build(:line_item) subject.stub(:params).and_return(order_cycle_id_in: oc1.id) - subject.orders.should == [order] - end - - it "only shows product line items that I am supplying" do - d2 = create(:distributor_enterprise) - create(:enterprise_relationship, parent: supplier, child: d1, permissions_list: [:add_to_order_cycle]) - d2.enterprise_roles.create!(user: create(:user)) - - s2 = create(:supplier_enterprise) - p2 = create(:simple_product, supplier: s2) - - li1 = create(:line_item, product: product) - li2 = create(:line_item, product: p2) - o1 = create(:order, distributor: d1, completed_at: 1.day.ago) - o1.line_items << li1 - o2 = create(:order, distributor: d2, completed_at: 1.day.ago) - o2.line_items << li2 - subject.orders.map{ |o| o.line_items}.flatten.should include li1 - subject.orders.map{ |o| o.line_items}.flatten.should_not include li2 + subject.table_items.should == [li1] end end end