From 674b8db56e626978bc4feb57b06dde9655d5d239 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 2 Jun 2020 18:04:54 +0300 Subject: [PATCH 1/5] magento/security-package#224: Recaptcha badge is not shown on checkout login form if 'Invisible Badge Position' is 'Bottom Left/Right' Merge pull request #5738 from magento-honey-badgers/2.4-develop-241-sync [honey] MC-33700: TransportBuilder unable to send emails of Content-Type "text/plain" --- .../web/js/nonInlineReCaptchaRenderer.js | 46 +++++++++++++++++++ .../view/frontend/web/js/reCaptcha.js | 7 ++- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js new file mode 100644 index 00000000..66f54404 --- /dev/null +++ b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js @@ -0,0 +1,46 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery' +], function ($) { + 'use strict'; + + var reCaptchaEntities = [], + initialized = false, + rendererRecaptchaId = 'recaptcha-invisible', + rendererReCaptcha = null; + + return { + add: function (reCaptchaEntity, parameters) { + if (parameters.size === 'invisible' && parameters.badge !== 'inline') { + if (!initialized) { + this._init(); + grecaptcha.render(rendererRecaptchaId, parameters); + setInterval(this._resolveVisibility, 100); + initialized = true; + } + + reCaptchaEntities.push(reCaptchaEntity); + } + }, + + _resolveVisibility: function () { + reCaptchaEntities.some( + (entity) => { + return entity.is(":visible") + // 900 is some magic z-index value of modal popups. + && (entity.closest("[data-role='modal']").length == 0 || entity.zIndex() > 900) + }) ? rendererReCaptcha.show() : rendererReCaptcha.hide(); + }, + + _init: function () { + rendererReCaptcha = $('
', { + 'id': rendererRecaptchaId + }); + $('body').append(rendererReCaptcha); + } + }; +}); diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js index 63688881..14835df9 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js @@ -11,9 +11,10 @@ define( 'jquery', 'ko', 'Magento_ReCaptchaFrontendUi/js/registry', - 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader' + 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader', + 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer', ], - function (Component, $, ko, registry, reCaptchaLoader, undefined) { + function (Component, $, ko, registry, reCaptchaLoader,nonInlineReCaptchaRenderer, undefined) { 'use strict'; return Component.extend({ @@ -117,6 +118,8 @@ define( this.settings.rendering ); + nonInlineReCaptchaRenderer.add($reCaptcha, parameters); + // eslint-disable-next-line no-undef widgetId = grecaptcha.render(this.getReCaptchaId(), parameters); this.initParentForm($parentForm, widgetId); From 4ff78d97621810e17bbd6ee1c3eb843b8974e1cc Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Tue, 16 Jun 2020 20:08:40 +0300 Subject: [PATCH 2/5] magento/security-package#224: Recaptcha badge is not shown on checkout login form if 'Invisible Badge Position' is 'Bottom Left/Right' --- .../web/js/nonInlineReCaptchaRenderer.js | 34 +++++++++++------- .../view/frontend/web/js/reCaptcha.js | 36 +++++++++---------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js index 66f54404..a0926a96 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js @@ -14,29 +14,39 @@ define([ rendererReCaptcha = null; return { + /** + * Add reCaptcha entity to checklist. + * + * @param {jQuery} reCaptchaEntity + * @param {Object} parameters + */ add: function (reCaptchaEntity, parameters) { - if (parameters.size === 'invisible' && parameters.badge !== 'inline') { - if (!initialized) { - this._init(); - grecaptcha.render(rendererRecaptchaId, parameters); - setInterval(this._resolveVisibility, 100); - initialized = true; - } - - reCaptchaEntities.push(reCaptchaEntity); + if (!initialized) { + this.init(); + grecaptcha.render(rendererRecaptchaId, parameters); + setInterval(this.resolveVisibility, 100); + initialized = true; } + + reCaptchaEntities.push(reCaptchaEntity); }, - _resolveVisibility: function () { + /** + * Show additional reCaptcha instance if any other should be visible, otherwise hide it. + */ + resolveVisibility: function () { reCaptchaEntities.some( (entity) => { return entity.is(":visible") // 900 is some magic z-index value of modal popups. - && (entity.closest("[data-role='modal']").length == 0 || entity.zIndex() > 900) + && (entity.closest("[data-role='modal']").length === 0 || entity.zIndex() > 900) }) ? rendererReCaptcha.show() : rendererReCaptcha.hide(); }, - _init: function () { + /** + * Initialize additional reCaptcha instance. + */ + init: function () { rendererReCaptcha = $('
', { 'id': rendererRecaptchaId }); diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js index 14835df9..e17b91eb 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js @@ -14,7 +14,7 @@ define( 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader', 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer', ], - function (Component, $, ko, registry, reCaptchaLoader,nonInlineReCaptchaRenderer, undefined) { + function (Component, $, ko, registry, reCaptchaLoader,nonInlineReCaptchaRenderer) { 'use strict'; return Component.extend({ @@ -23,7 +23,6 @@ define( template: 'Magento_ReCaptchaFrontendUi/reCaptcha', reCaptchaId: 'recaptcha' }, - _isApiRegistered: undefined, initialize: function () { this._super(); @@ -76,8 +75,7 @@ define( * Initialize reCAPTCHA after first rendering */ initCaptcha: function () { - var me = this, - $parentForm, + var $parentForm, $wrapper, $reCaptcha, widgetId, @@ -103,22 +101,23 @@ define( $reCaptcha.attr('id', this.getReCaptchaId()); $parentForm = $wrapper.parents('form'); - me = this; parameters = _.extend( { 'callback': function (token) { // jscs:ignore jsDoc - me.reCaptchaCallback(token); - me.validateReCaptcha(true); - }, + this.reCaptchaCallback(token); + this.validateReCaptcha(true); + }.bind(this), 'expired-callback': function () { - me.validateReCaptcha(false); - } + this.validateReCaptcha(false); + }.bind(this) }, this.settings.rendering ); - nonInlineReCaptchaRenderer.add($reCaptcha, parameters); + if (parameters.size === 'invisible' && parameters.badge !== 'inline') { + nonInlineReCaptchaRenderer.add($reCaptcha, parameters) + } // eslint-disable-next-line no-undef widgetId = grecaptcha.render(this.getReCaptchaId(), parameters); @@ -137,18 +136,17 @@ define( * @param {String} widgetId */ initParentForm: function (parentForm, widgetId) { - var me = this, - listeners; + var listeners; if (this.getIsInvisibleRecaptcha() && parentForm.length > 0) { parentForm.submit(function (event) { - if (!me.tokenField.value) { + if (!this.tokenField.value) { // eslint-disable-next-line no-undef grecaptcha.execute(widgetId); event.preventDefault(event); event.stopImmediatePropagation(); } - }); + }.bind(this)); // Move our (last) handler topmost. We need this to avoid submit bindings with ko. listeners = $._data(parentForm[0], 'events').submit; @@ -173,14 +171,12 @@ define( * Render reCAPTCHA */ renderReCaptcha: function () { - var me = this; - if (window.grecaptcha && window.grecaptcha.render) { // Check if reCAPTCHA is already loaded - me.initCaptcha(); + this.initCaptcha(); } else { // Wait for reCAPTCHA to be loaded $(window).on('recaptchaapiready', function () { - me.initCaptcha(); - }); + this.initCaptcha(); + }.bind(this)); } }, From 2c2008b35b89b173c57b6b36638a0547c496672e Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Fri, 12 Jun 2020 12:38:21 +0300 Subject: [PATCH 3/5] magento/security-package#242: ReCAPTCHA v2 ("I am not a robot") for Newsletter Subscription displays with error. --- ReCaptchaNewsletter/etc/adminhtml/system.xml | 2 +- .../view/frontend/layout/default.xml | 7 ------- .../view/frontend/web/css/source/_module.less | 16 ++++++++++++++++ 3 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 ReCaptchaNewsletter/view/frontend/web/css/source/_module.less diff --git a/ReCaptchaNewsletter/etc/adminhtml/system.xml b/ReCaptchaNewsletter/etc/adminhtml/system.xml index f70a2969..ca0109b6 100644 --- a/ReCaptchaNewsletter/etc/adminhtml/system.xml +++ b/ReCaptchaNewsletter/etc/adminhtml/system.xml @@ -12,7 +12,7 @@ - + If enabled, a badge will be displayed in every page. Magento\ReCaptchaAdminUi\Model\OptionSource\Type diff --git a/ReCaptchaNewsletter/view/frontend/layout/default.xml b/ReCaptchaNewsletter/view/frontend/layout/default.xml index 82c684a2..992d56d7 100644 --- a/ReCaptchaNewsletter/view/frontend/layout/default.xml +++ b/ReCaptchaNewsletter/view/frontend/layout/default.xml @@ -17,13 +17,6 @@ ifconfig="recaptcha_frontend/type_for/newsletter"> newsletter - - true - - bottomright - invisible - - diff --git a/ReCaptchaNewsletter/view/frontend/web/css/source/_module.less b/ReCaptchaNewsletter/view/frontend/web/css/source/_module.less new file mode 100644 index 00000000..563319cd --- /dev/null +++ b/ReCaptchaNewsletter/view/frontend/web/css/source/_module.less @@ -0,0 +1,16 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +.block.newsletter { + .field-recaptcha { + .field { + .control { + &:before { + content: none; + } + } + } + } +} From a31d7014c16c15a6697d094681b35d23f92e7d7b Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 17 Jun 2020 00:10:57 +0300 Subject: [PATCH 4/5] Static tests fix. --- .../web/js/nonInlineReCaptchaRenderer.js | 16 +++++++++++++--- .../view/frontend/web/js/reCaptcha.js | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js index a0926a96..10a77456 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js @@ -33,18 +33,28 @@ define([ /** * Show additional reCaptcha instance if any other should be visible, otherwise hide it. + * + * @private */ resolveVisibility: function () { reCaptchaEntities.some( - (entity) => { - return entity.is(":visible") + /** + * Check if reCaptcha instance is visible. + * + * @param {jQuery} entity + * @returns {Boolean} + */ + function (entity) { + return entity.is(':visible') && // 900 is some magic z-index value of modal popups. - && (entity.closest("[data-role='modal']").length === 0 || entity.zIndex() > 900) + (entity.closest('[data-role=\'modal\']').length === 0 || entity.zIndex() > 900) }) ? rendererReCaptcha.show() : rendererReCaptcha.hide(); }, /** * Initialize additional reCaptcha instance. + * + * @private */ init: function () { rendererReCaptcha = $('
', { diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js index e17b91eb..2c951331 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js @@ -12,9 +12,9 @@ define( 'ko', 'Magento_ReCaptchaFrontendUi/js/registry', 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader', - 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer', + 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer' ], - function (Component, $, ko, registry, reCaptchaLoader,nonInlineReCaptchaRenderer) { + function (Component, $, ko, registry, reCaptchaLoader, nonInlineReCaptchaRenderer) { 'use strict'; return Component.extend({ From bd4465a26488c35d64f860b484a90262f7b2387a Mon Sep 17 00:00:00 2001 From: Lena Orobei Date: Tue, 16 Jun 2020 16:27:08 -0500 Subject: [PATCH 5/5] Fix JS code styles --- .../web/js/nonInlineReCaptchaRenderer.js | 12 +++++----- .../view/frontend/web/js/reCaptcha.js | 22 ++++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js index a0926a96..ab622f45 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/nonInlineReCaptchaRenderer.js @@ -3,6 +3,7 @@ * See COPYING.txt for license details. */ +/* global grecaptcha */ define([ 'jquery' ], function ($) { @@ -35,12 +36,11 @@ define([ * Show additional reCaptcha instance if any other should be visible, otherwise hide it. */ resolveVisibility: function () { - reCaptchaEntities.some( - (entity) => { - return entity.is(":visible") - // 900 is some magic z-index value of modal popups. - && (entity.closest("[data-role='modal']").length === 0 || entity.zIndex() > 900) - }) ? rendererReCaptcha.show() : rendererReCaptcha.hide(); + reCaptchaEntities.some(function (entity) { + return entity.is(':visible') && + // 900 is some magic z-index value of modal popups. + (entity.closest('[data-role=\'modal\']').length === 0 || entity.zIndex() > 900); + }) ? rendererReCaptcha.show() : rendererReCaptcha.hide(); }, /** diff --git a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js index e17b91eb..ddd627f2 100644 --- a/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js +++ b/ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js @@ -3,18 +3,17 @@ * See COPYING.txt for license details. */ -/* eslint-disable no-undef */ -// jscs:disable jsDoc +/* global grecaptcha */ define( [ 'uiComponent', 'jquery', 'ko', + 'underscore', 'Magento_ReCaptchaFrontendUi/js/registry', 'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader', - 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer', - ], - function (Component, $, ko, registry, reCaptchaLoader,nonInlineReCaptchaRenderer) { + 'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer' + ], function (Component, $, ko, _, registry, reCaptchaLoader, nonInlineReCaptchaRenderer) { 'use strict'; return Component.extend({ @@ -24,6 +23,9 @@ define( reCaptchaId: 'recaptcha' }, + /** + * @inheritdoc + */ initialize: function () { this._super(); this._loadApi(); @@ -116,7 +118,7 @@ define( ); if (parameters.size === 'invisible' && parameters.badge !== 'inline') { - nonInlineReCaptchaRenderer.add($reCaptcha, parameters) + nonInlineReCaptchaRenderer.add($reCaptcha, parameters); } // eslint-disable-next-line no-undef @@ -161,6 +163,11 @@ define( } }, + /** + * Validates reCAPTCHA + * @param {*} state + * @returns {jQuery} + */ validateReCaptcha: function (state) { if (!this.getIsInvisibleRecaptcha()) { return $(document).find('input[type=checkbox].required-captcha').prop('checked', state); @@ -188,5 +195,4 @@ define( return this.reCaptchaId; } }); - } -); + });