diff --git a/app/controllers/concerns/bizible_csp.rb b/app/controllers/concerns/bizible_csp.rb new file mode 100644 index 0000000000000000000000000000000000000000..521f312775949391b2412f06f9298be8f3260688 --- /dev/null +++ b/app/controllers/concerns/bizible_csp.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module BizibleCSP + extend ActiveSupport::Concern + + included do + content_security_policy do |policy| + next unless helpers.bizible_enabled? || policy.directives.present? + + default_script_src = policy.directives['script-src'] || policy.directives['default-src'] + script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.bizible.com/scripts/bizible.js'] + policy.script_src(*script_src_values) + end + end +end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 7b688c0ccc28e88ddbb957341008607fa813003d..057c451ace21b115b64aa21d0832d2b06ba76268 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -6,6 +6,7 @@ class RegistrationsController < Devise::RegistrationsController include RecaptchaHelper include InvisibleCaptchaOnSignup include OneTrustCSP + include BizibleCSP layout 'devise' diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 7e8e3ea878928b0c81bb221e76a887d29f7b6dec..e907e291eeb2cb1a8eefeb40056785b88358722d 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -10,6 +10,7 @@ class SessionsController < Devise::SessionsController include KnownSignIn include Gitlab::Utils::StrongMemoize include OneTrustCSP + include BizibleCSP skip_before_action :check_two_factor_requirement, only: [:destroy] skip_before_action :check_password_expiration, only: [:destroy] diff --git a/app/helpers/bizible_helper.rb b/app/helpers/bizible_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..970cc6558da9f6166521880484e04afa6e2c4ecc --- /dev/null +++ b/app/helpers/bizible_helper.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module BizibleHelper + def bizible_enabled? + Feature.enabled?(:ecomm_instrumentation, type: :ops) && + Gitlab.config.extra.has_key?('bizible') && + Gitlab.config.extra.bizible.present? && + Gitlab.config.extra.bizible == true + end +end diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml index 1d46a43e5bdd60ef1c922d329476e1e957b7ec8c..ef19ac33a155c7f053c704050b4eb7942e657346 100644 --- a/app/views/devise/confirmations/almost_there.haml +++ b/app/views/devise/confirmations/almost_there.haml @@ -4,6 +4,7 @@ - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" + = render "layouts/bizible" = render "layouts/google_tag_manager_body" .well-confirmation.gl-text-center.gl-mb-6 diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 87108c8ea78cfb68e74979c7014047a52af3e852..60c3df718a15b1b11082740681eaa2dfcd29a9d5 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -3,6 +3,7 @@ - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" + = render "layouts/bizible" = render "layouts/google_tag_manager_body" .signup-page diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 175b45dbbfaef01f97295303a57167ff5f9e0d45..c669f3efec6314903c0e895d6082fc91ebb29f72 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,6 +1,7 @@ - page_title _("Sign in") - content_for :page_specific_javascripts do = render "layouts/one_trust" + = render "layouts/bizible" #signin-container - if any_form_based_providers_enabled? diff --git a/app/views/layouts/_bizible.html.haml b/app/views/layouts/_bizible.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..a2b28c138e58044d41beca70ba4db2bb7d5fdc4c --- /dev/null +++ b/app/views/layouts/_bizible.html.haml @@ -0,0 +1,14 @@ +- if bizible_enabled? + + = javascript_include_tag "https://cdn.bizible.com/scripts/bizible.js" + = javascript_tag nonce: content_security_policy_nonce do + :plain + const bizibleScript = document.createElement('script'); + bizibleScript.src = 'https://cdn.bizible.com/scripts/bizible.js'; + bizibleScript.nonce = '#{content_security_policy_nonce}' + bizibleScript.charset = 'UTF-8'; + bizibleScript.defer = true; + document.head.appendChild(bizibleScript); + + function OptanonWrapper() { } + diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml index ca2f225a2d8d98776b0e6642cbfdefa0790147cd..44dffdbf70aef24ad4affb452befbf6da1993ee4 100644 --- a/app/views/registrations/welcome/show.html.haml +++ b/app/views/registrations/welcome/show.html.haml @@ -5,6 +5,7 @@ - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" + = render "layouts/bizible" = render "layouts/google_tag_manager_body" .row.gl-flex-grow-1 diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml index c461250fc9b9a3339fc037fe46ec1bd1c149767f..afe257c2fc2c64278196d60ad8abd0475f1de6ce 100644 --- a/app/views/users/terms/index.html.haml +++ b/app/views/users/terms/index.html.haml @@ -1,6 +1,7 @@ - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" + = render "layouts/bizible" = render "layouts/google_tag_manager_body" #js-terms-of-service{ data: { terms_data: terms_data(@term, @redirect) } } diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index bcb34548f8175ad9aebafd6f1d376c60221bd568..6758afc91c4660754f72474a603932d44bd5f777 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -1332,6 +1332,9 @@ production: &base ## OneTrust # one_trust_id: '_your_one_trust_id' + ## Bizible. + # bizible: true + ## Matomo analytics. # matomo_url: '_your_matomo_url' # matomo_site_id: '_your_matomo_site_id' diff --git a/ee/app/controllers/trial_registrations_controller.rb b/ee/app/controllers/trial_registrations_controller.rb index 56a49ab6e706938ab8e17a3e52d4450821ebbc99..e83291a111247ccdc4b37cc8df0bb5a64c4ad67b 100644 --- a/ee/app/controllers/trial_registrations_controller.rb +++ b/ee/app/controllers/trial_registrations_controller.rb @@ -4,6 +4,7 @@ # TODO: namespace https://gitlab.com/gitlab-org/gitlab/-/issues/338394 class TrialRegistrationsController < RegistrationsController include OneTrustCSP + include BizibleCSP layout 'minimal' diff --git a/ee/app/views/trial_registrations/new.html.haml b/ee/app/views/trial_registrations/new.html.haml index 7aa1abfad5dd8c7b5077971fe6b401e016ccd08a..39800da3800547e0daa23fe92ee0ac7e5601a19d 100644 --- a/ee/app/views/trial_registrations/new.html.haml +++ b/ee/app/views/trial_registrations/new.html.haml @@ -3,6 +3,8 @@ - content_for :page_specific_javascripts do = render "layouts/google_tag_manager_head" = render "layouts/one_trust" + = render "layouts/bizible" + = render "layouts/google_tag_manager_body" .row diff --git a/spec/features/users/bizible_csp_spec.rb b/spec/features/users/bizible_csp_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..af0b42050b3fd2088d354dda5732a4708db3694f --- /dev/null +++ b/spec/features/users/bizible_csp_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Bizible content security policy' do + before do + stub_config(extra: { one_trust_id: SecureRandom.uuid }) + end + + it 'has proper Content Security Policy headers' do + visit root_path + + expect(response_headers['Content-Security-Policy']).to include('https://cdn.bizible.com/scripts/bizible.js') + end +end diff --git a/spec/helpers/bizible_helper_spec.rb b/spec/helpers/bizible_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b82211d51ec305e4daf70e8fd2623549622d8473 --- /dev/null +++ b/spec/helpers/bizible_helper_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe BizibleHelper do + describe '#bizible_enabled?' do + before do + stub_config(extra: { bizible: SecureRandom.uuid }) + end + + context 'when bizible is disabled' do + before do + allow(helper).to receive(:bizible_enabled?).and_return(false) + end + + it { is_expected.to be_falsey } + end + + context 'when bizible is enabled' do + before do + allow(helper).to receive(:bizible_enabled?).and_return(true) + end + + it { is_expected.to be_truthy } + end + + subject(:bizible_enabled?) { helper.bizible_enabled? } + + context 'with ecomm_instrumentation feature flag disabled' do + before do + stub_feature_flags(ecomm_instrumentation: false) + end + + it { is_expected.to be_falsey } + end + + context 'with ecomm_instrumentation feature flag enabled' do + context 'when no id is set' do + before do + stub_config(extra: {}) + end + + it { is_expected.to be_falsey } + end + end + end +end