diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0f6126367c..0d31130c6e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,6 +3,8 @@ require 'open_food_network/referer_parser' class ApplicationController < ActionController::Base protect_from_forgery + prepend_before_filter :restrict_iframes + include EnterprisesHelper helper CssSplitter::ApplicationHelper @@ -20,6 +22,21 @@ class ApplicationController < ActionController::Base private + def restrict_iframes + response.headers['X-Frame-Options'] = 'DENY' + response.headers['Content-Security-Policy'] = "frame-ancestors 'none'" + end + + def enable_embedded_shopfront + return unless Spree::Config[:enable_embedded_shopfronts] + + @session_data = session + + whitelist = Spree::Config[:embedded_shopfronts_whitelist] || "'none'" + response.headers.delete 'X-Frame-Options' + response.headers['Content-Security-Policy'] = "frame-ancestors #{whitelist}" + end + def action params[:action].to_sym end diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 58c0c62eac..e002a7c723 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -9,6 +9,7 @@ class CheckoutController < Spree::CheckoutController prepend_before_filter :require_distributor_chosen skip_before_filter :check_registration + before_filter :enable_embedded_shopfront include OrderCyclesHelper include EnterprisesHelper diff --git a/app/controllers/enterprises_controller.rb b/app/controllers/enterprises_controller.rb index 6c38cfe83a..126e2bdeed 100644 --- a/app/controllers/enterprises_controller.rb +++ b/app/controllers/enterprises_controller.rb @@ -10,6 +10,7 @@ class EnterprisesController < BaseController before_filter :check_stock_levels, only: :shop before_filter :clean_permalink, only: :check_permalink + before_filter :enable_embedded_shopfront respond_to :js, only: :permalink_checker diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index fbf1819277..55b6b827e1 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,6 +1,8 @@ class HomeController < BaseController layout 'darkswarm' + before_filter :enable_embedded_shopfront + def index if ContentConfig.home_show_stats @num_distributors = Enterprise.is_distributor.activated.visible.count diff --git a/app/controllers/producers_controller.rb b/app/controllers/producers_controller.rb index 42d1d401e5..21861b6fb8 100644 --- a/app/controllers/producers_controller.rb +++ b/app/controllers/producers_controller.rb @@ -1,6 +1,8 @@ class ProducersController < BaseController layout 'darkswarm' + before_filter :enable_embedded_shopfront + def index end end diff --git a/app/controllers/shop_controller.rb b/app/controllers/shop_controller.rb index 6ad6f56e56..13d56f917e 100644 --- a/app/controllers/shop_controller.rb +++ b/app/controllers/shop_controller.rb @@ -4,6 +4,7 @@ class ShopController < BaseController layout "darkswarm" before_filter :require_distributor_chosen before_filter :set_order_cycles + before_filter :enable_embedded_shopfront def show redirect_to main_app.enterprise_shop_path(current_distributor) diff --git a/app/controllers/shops_controller.rb b/app/controllers/shops_controller.rb index 3305811e07..439e8fde06 100644 --- a/app/controllers/shops_controller.rb +++ b/app/controllers/shops_controller.rb @@ -1,6 +1,9 @@ class ShopsController < BaseController layout 'darkswarm' + before_filter :enable_embedded_shopfront + def index + #@embeddable = "test" end end diff --git a/app/controllers/spree/checkout_controller_decorator.rb b/app/controllers/spree/checkout_controller_decorator.rb index 641e15f640..7841c86c36 100644 --- a/app/controllers/spree/checkout_controller_decorator.rb +++ b/app/controllers/spree/checkout_controller_decorator.rb @@ -4,6 +4,8 @@ Spree::CheckoutController.class_eval do include CheckoutHelper + before_filter :enable_embedded_shopfront + def edit flash.keep redirect_to main_app.checkout_path diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index dde08273ad..47425bcbf2 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -4,6 +4,7 @@ Spree::OrdersController.class_eval do after_filter :populate_variant_attributes, only: :populate before_filter :update_distribution, only: :update before_filter :filter_order_params, only: :update + before_filter :enable_embedded_shopfront prepend_before_filter :require_order_cycle, only: :edit prepend_before_filter :require_distributor_chosen, only: :edit diff --git a/app/controllers/spree/paypal_controller_decorator.rb b/app/controllers/spree/paypal_controller_decorator.rb index fce09cfe0b..74da22557f 100644 --- a/app/controllers/spree/paypal_controller_decorator.rb +++ b/app/controllers/spree/paypal_controller_decorator.rb @@ -2,6 +2,7 @@ Spree::PaypalController.class_eval do include CheckoutHelper after_filter :reset_order_when_complete, only: :confirm + before_filter :enable_embedded_shopfront def cancel flash[:notice] = t('flash.cancel', :scope => 'paypal') diff --git a/app/controllers/spree/users_controller_decorator.rb b/app/controllers/spree/users_controller_decorator.rb index 5f0eaa9759..a56c59d6fa 100644 --- a/app/controllers/spree/users_controller_decorator.rb +++ b/app/controllers/spree/users_controller_decorator.rb @@ -1,3 +1,5 @@ Spree::UsersController.class_eval do layout 'darkswarm' + + before_filter :enable_embedded_shopfront end diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 4f8a80bf96..925106f3db 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -4,6 +4,10 @@ Spree::AppConfiguration.class_eval do # we can allow to be modified in the UI by adding appropriate form # elements to existing or new configuration pages. + # Embedded Shopfronts + preference :enable_embedded_shopfronts, :boolean, default: false + preference :embedded_shopfronts_whitelist, :text, default: nil + # Terms of Service Preferences preference :enterprises_require_tos, :boolean, default: false diff --git a/app/overrides/spree/admin/general_settings/edit/embedded_shopfront_settings.html.haml.deface b/app/overrides/spree/admin/general_settings/edit/embedded_shopfront_settings.html.haml.deface new file mode 100644 index 0000000000..980a97a268 --- /dev/null +++ b/app/overrides/spree/admin/general_settings/edit/embedded_shopfront_settings.html.haml.deface @@ -0,0 +1,11 @@ +/ insert_after "fieldset.security" + +%fieldset.embedded_shopfronts.no-border-bottom + %legend{:align => "center"}= t('admin.shopfront_settings.embedded_shopfront_settings') + .field + = preference_field_tag(:enable_embedded_shopfronts, Spree::Config[:enable_embedded_shopfronts], type: Spree::Config.preference_type(:enable_embedded_shopfronts)) + = label_tag(:enable_embedded_shopfronts, t('admin.shopfront_settings.enable_embedded_shopfronts')) + tag(:br) + .field + = label_tag(:embedded_shopfronts_whitelist, t('admin.shopfront_settings.embedded_shopfronts_whitelist')) + tag(:br) + = preference_field_tag(:embedded_shopfronts_whitelist, Spree::Config[:embedded_shopfronts_whitelist], type: Spree::Config.preference_type(:embedded_shopfronts_whitelist)) + diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index acd6a88835..221a7b05e3 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -97,6 +97,10 @@ en-GB: update_user_invoice_explained: "Use this button to immediately update invoices for the month to date for each enterprise user in the system. This task can be set up to run automatically every night." auto_finalise_invoices: "Auto-finalise invoices monthly on the 2nd at 1:30am" auto_update_invoices: "Auto-update invoices nightly at 1:00am" + shopfront_settings: + embedded_shopfront_settings: Embedded Shopfront Settings + enable_embedded_shopfronts: Enable Embedded Shopfronts + embedded_shopfronts_whitelist: External Domains Whitelist business_model_configuration: edit: business_model_configuration: "Business Model" diff --git a/config/locales/en.yml b/config/locales/en.yml index 3346930377..70ff9c536e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -229,6 +229,11 @@ en: default_payment_method: must be set if you wish to create invoices for enterprise users. default_shipping_method: must be set if you wish to create invoices for enterprise users. + shopfront_settings: + embedded_shopfront_settings: Embedded Shopfront Settings + enable_embedded_shopfronts: Enable Embedded Shopfronts + embedded_shopfronts_whitelist: External Domains Whitelist + business_model_configuration: edit: business_model_configuration: "Business Model" diff --git a/spec/dummy/iframe_test.html b/spec/dummy/iframe_test.html new file mode 100644 index 0000000000..552cf8e8dc --- /dev/null +++ b/spec/dummy/iframe_test.html @@ -0,0 +1,10 @@ + +
+ + +Iframe Test
+ + + + + \ No newline at end of file diff --git a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb new file mode 100644 index 0000000000..fd216c2a2b --- /dev/null +++ b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +feature "Using embedded shopfront functionality", js: true do + include AuthenticationWorkflow + include WebHelper + + describe "enabling embedded shopfronts" do + before do + Spree::Config[:enable_embedded_shopfronts] = false + end + + it "disables iframes by default" do + visit shops_path + expect(page.response_headers['X-Frame-Options']).to eq 'DENY' + expect(page.response_headers['Content-Security-Policy']).to eq "frame-ancestors 'none'" + end + + it "allows iframes on certain pages when enabled in configuration" do + quick_login_as_admin + + visit spree.edit_admin_general_settings_path + + check 'enable_embedded_shopfronts' + fill_in 'embedded_shopfronts_whitelist', with: "test.com" + + click_button 'Update' + + visit shops_path + expect(page.response_headers['X-Frame-Options']).to be_nil + expect(page.response_headers['Content-Security-Policy']).to eq "frame-ancestors test.com" + end + end + + describe "using iframes", js: true do + before do + Spree::Config[:enable_embedded_shopfronts] = true + end + + after do + Spree::Config[:enable_embedded_shopfronts] = false + end + + pending "displays iframe content" do + Capybara.current_session.driver.visit('spec/dummy/iframe_test.html') + + expect(page).to have_text 'Iframe Test' + expect(page).to have_selector 'iframe#test_iframe' + + within_frame 'test_iframe' do + sleep 1 + expect(page).to have_content "OFN" # currently fails... + end + end + end +end