Skip to content

Commit 337a1d8

Browse files
committed
Merge branch 'AC-9196' of https://github.com/magento-gl/security-package into AC-9196
2 parents 4bf69cd + ef3bb0c commit 337a1d8

File tree

7 files changed

+173
-18
lines changed

7 files changed

+173
-18
lines changed

.github/CONTRIBUTING.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ For more detailed information on contribution please read our [beginners guide](
1919
2. Pull requests (PRs) must be accompanied by a meaningful description of their purpose. Comprehensive descriptions increase the chances of a pull request being merged quickly and without additional clarification requests.
2020
3. Commits must be accompanied by meaningful commit messages. Please see the [Magento Pull Request Template](https://github.com/magento/magento2/blob/2.3-develop/.github/PULL_REQUEST_TEMPLATE.md) for more information.
2121
4. PRs which include bug fixes must be accompanied with a step-by-step description of how to reproduce the bug.
22-
3. PRs which include new logic or new features must be submitted along with:
23-
* Unit/integration test coverage
24-
* Proposed [documentation](https://devdocs.magento.com) updates. Documentation contributions can be submitted via the [devdocs GitHub](https://github.com/magento/devdocs).
25-
4. For larger features or changes, please [open an issue](https://github.com/magento/magento2/issues) to discuss the proposed changes prior to development. This may prevent duplicate or unnecessary effort and allow other contributors to provide input.
26-
5. All automated tests must pass (all builds on [Travis CI](https://travis-ci.org/magento/magento2) must be green).
22+
5. PRs which include new logic or new features must be submitted along with:
23+
* Unit/integration test coverage
24+
* Proposed [documentation](https://developer.adobe.com/commerce) updates. Use feedback buttons __Edit in GitHub__ and __Log an issue__ at the top of a relevant topic.
25+
6. For larger features or changes, please [open an issue](https://github.com/magento/magento2/issues) to discuss the proposed changes prior to development. This may prevent duplicate or unnecessary effort and allow other contributors to provide input.
26+
7. All automated tests must pass (all builds on [Travis CI](https://travis-ci.org/magento/magento2) must be green).
2727

2828
## Contribution process
2929

ReCaptchaFrontendUi/view/frontend/web/js/reCaptcha.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,14 @@ define(
7373
* @param {String} token
7474
*/
7575
reCaptchaCallback: function (token) {
76+
var submitButton;
77+
7678
if (this.getIsInvisibleRecaptcha()) {
7779
this.tokenField.value = token;
80+
submitButton = this.$parentForm.find('button:not([type]), [type=submit]');
81+
if (submitButton.length) { //eslint-disable-line max-depth
82+
submitButton.attr('disabled', false);
83+
}
7884
this.$parentForm.submit();
7985
}
8086
},
@@ -155,18 +161,17 @@ define(
155161

156162
if (this.getIsInvisibleRecaptcha() && parentForm.length > 0) {
157163
parentForm.submit(function (event) {
164+
var submitButton;
165+
158166
if (!this.tokenField.value) {
167+
submitButton = this.$parentForm.find('button:not([type]), [type=submit]');
168+
if (submitButton.length) { //eslint-disable-line max-depth
169+
submitButton.attr('disabled', true);
170+
}
159171
// eslint-disable-next-line no-undef
160172
grecaptcha.execute(widgetId);
161173
event.preventDefault(event);
162174
event.stopImmediatePropagation();
163-
if (this.$parentForm.valid()) {
164-
let formSubmitButton = this.$parentForm.find('button:not([type]), [type=submit]');
165-
166-
if (formSubmitButton.length) { //eslint-disable-line max-depth
167-
formSubmitButton.attr('disabled', true);
168-
}
169-
}
170175
}
171176
}.bind(this));
172177

TwoFactorAuth/view/adminhtml/web/js/u2fkey/auth.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ define([
8484
*/
8585
waitForTouch: function () {
8686
this.idle(false);
87+
if (!navigator.credentials) {
88+
this.currentStep('no-webauthn');
89+
return;
90+
}
8791
navigator.credentials.get({
8892
publicKey: this.authenticateData.credentialRequestOptions
8993
})
@@ -158,8 +162,8 @@ define([
158162
_onCredentialError: function (u2fError) {
159163
this.idle(true);
160164

161-
if (['AbortError', 'NS_ERROR_ABORT', 'NotAllowedError'].indexOf(u2fError.name) === -1) {
162-
error.display($t('Unable to register your device'));
165+
if (['AbortError', 'NS_ERROR_ABORT'].indexOf(u2fError.name) === -1) {
166+
error.display($t(u2fError.message));
163167
}
164168
}
165169
});

TwoFactorAuth/view/adminhtml/web/js/u2fkey/configure.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ define([
7878
*/
7979
waitForTouch: function () {
8080
this.idle(false);
81+
if (!navigator.credentials) {
82+
this.currentStep('no-webauthn');
83+
return;
84+
}
8185
navigator.credentials.create({
8286
publicKey: this.registerData.publicKey
8387
})
@@ -150,8 +154,8 @@ define([
150154
_onCredentialError: function (u2fError) {
151155
this.idle(true);
152156

153-
if (['AbortError', 'NS_ERROR_ABORT', 'NotAllowedError'].indexOf(u2fError.name) === -1) {
154-
error.display($t('Unable to register your device'));
157+
if (['AbortError', 'NS_ERROR_ABORT'].indexOf(u2fError.name) === -1) {
158+
error.display($t(u2fError.message));
155159
}
156160
}
157161
});

TwoFactorAuth/view/adminhtml/web/template/u2fkey/auth.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<fieldset class="admin__fieldset">
1010
<legend class="admin__legend">
1111
<span translate="'2FA - U2F key verification'"></span>
12-
</legend><br/>
12+
</legend><br>
1313
<div class="tfa-u2f-touch-key">
1414
<h3 translate="'Plug in your U2F key and follow instructions'"></h3>
1515
<div visible="$data.idle" class="tfa-u2f-try-again">
@@ -27,6 +27,10 @@ <h3 translate="'Plug in your U2F key and follow instructions'"></h3>
2727
</div>
2828
<div translate="'Redirecting to Magento Admin Panel...'"></div>
2929
</div>
30+
<div visible='currentStep() === "no-webauthn"'
31+
translate="'Error! Your browser does not support WebAuthn or you are not using a secure connection'"
32+
>
33+
</div>
3034
<div visible='$data.loading' class="tfa-waitbox">
3135
<div data-role="spinner">
3236
<div class="spinner">

TwoFactorAuth/view/adminhtml/web/template/u2fkey/configure.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<fieldset class="admin__fieldset">
1010
<legend class="admin__legend">
1111
<span translate="'2FA - U2F key device registration'"></span>
12-
</legend><br/>
12+
</legend><br>
1313
<div id="u2f-touch-key">
1414
<h3 translate="'Plug in your U2F key and follow instructions'"></h3>
1515
<div visible="$data.idle" class="tfa-u2f-try-again">
@@ -27,6 +27,10 @@ <h3 translate="'Plug in your U2F key and follow instructions'"></h3>
2727
</div>
2828
<div translate="'Redirecting to Magento Admin Panel...'"></div>
2929
</div>
30+
<div visible='currentStep() === "no-webauthn"'
31+
translate="'Error! Your browser does not support WebAuthn or you are not using a secure connection'"
32+
>
33+
</div>
3034
<div visible='$data.loading' class="tfa-waitbox">
3135
<div data-role="spinner">
3236
<div class="spinner">
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/************************************************************************
2+
*
3+
* Copyright 2023 Adobe
4+
* All Rights Reserved.
5+
*
6+
* NOTICE: All information contained herein is, and remains
7+
* the property of Adobe and its suppliers, if any. The intellectual
8+
* and technical concepts contained herein are proprietary to Adobe
9+
* and its suppliers and are protected by all applicable intellectual
10+
* property laws, including trade secret and copyright laws.
11+
* Dissemination of this information or reproduction of this material
12+
* is strictly forbidden unless prior written permission is obtained
13+
* from Adobe.
14+
* ************************************************************************
15+
*/
16+
17+
/* eslint-disable max-nested-callbacks */
18+
define([
19+
'squire'
20+
], function (Squire) {
21+
'use strict';
22+
23+
var injector = new Squire(),
24+
mocks = {
25+
'Magento_ReCaptchaFrontendUi/js/registry': {
26+
ds: [],
27+
captchaList: [],
28+
tokenFields: []
29+
},
30+
'Magento_ReCaptchaFrontendUi/js/reCaptchaScriptLoader': {
31+
addReCaptchaScriptTag: jasmine.createSpy('reCaptchaScriptLoader.addReCaptchaScriptTag')
32+
},
33+
'Magento_ReCaptchaFrontendUi/js/nonInlineReCaptchaRenderer': {
34+
add: jasmine.createSpy('nonInlineReCaptchaRenderer.add')
35+
}
36+
},
37+
reCaptchaModel,
38+
formElement,
39+
submitButtonElement,
40+
$;
41+
42+
beforeEach(function (done) {
43+
injector.mock(mocks);
44+
injector.require(['jquery', 'Magento_ReCaptchaFrontendUi/js/reCaptcha'], function (jq, reCaptchaUiComponent) {
45+
reCaptchaModel = new reCaptchaUiComponent();
46+
$ = jq;
47+
done();
48+
});
49+
formElement = document.createElement('form');
50+
submitButtonElement = document.createElement('button');
51+
formElement.appendChild(submitButtonElement);
52+
window.document.body.appendChild(formElement);
53+
window.grecaptcha = {
54+
render: jasmine.createSpy('window.grecaptcha.render'),
55+
execute: jasmine.createSpy('window.grecaptcha.execute')
56+
};
57+
});
58+
59+
afterEach(function () {
60+
try {
61+
injector.clean();
62+
injector.remove();
63+
} catch (e) {
64+
}
65+
formElement.remove();
66+
formElement = undefined;
67+
submitButtonElement = undefined;
68+
});
69+
70+
describe('Magento_ReCaptchaFrontendUi/js/reCaptcha', function () {
71+
describe('Invisible ReCaptcha', function () {
72+
beforeEach(function () {
73+
reCaptchaModel.getIsInvisibleRecaptcha = jasmine.createSpy().and.returnValue(true);
74+
});
75+
76+
describe('"initParentForm" method', function () {
77+
it(
78+
'should disable submit button, prevent submit handlers from executing and execute recaptcha' +
79+
' on submit',
80+
function () {
81+
var request = {
82+
send: jasmine.createSpy('request.send')
83+
};
84+
85+
// check that submit button is enabled
86+
expect(submitButtonElement.disabled).toBeFalse();
87+
$(formElement).on('submit', function (event) {
88+
event.preventDefault();
89+
request.send();
90+
});
91+
reCaptchaModel.initParentForm($(formElement), 'test');
92+
$(formElement).submit();
93+
// check that submit button is disabled
94+
expect(submitButtonElement.disabled).toBeTrue();
95+
// check that grecaptcha is executed
96+
expect(window.grecaptcha.execute).toHaveBeenCalledOnceWith('test');
97+
// check that other submit handlers are not executed
98+
expect(request.send).not.toHaveBeenCalled();
99+
});
100+
101+
it('should add a token input field to the form', function () {
102+
submitButtonElement.disabled = true;
103+
reCaptchaModel.initParentForm($(formElement), 'test');
104+
expect(submitButtonElement.disabled).toBeFalse();
105+
expect(reCaptchaModel.tokenField).not.toBeNull();
106+
expect($(reCaptchaModel.tokenField).parents('form').is($(formElement))).toBeTrue();
107+
});
108+
});
109+
describe('"reCaptchaCallback" method', function () {
110+
it('should enable submit button, set token input value and submit the form', function () {
111+
var request = {
112+
send: jasmine.createSpy('request.send')
113+
};
114+
115+
submitButtonElement.disabled = true;
116+
reCaptchaModel.$parentForm = $(formElement);
117+
reCaptchaModel.tokenField = $('<input type="text" name="token" style="display: none" />')[0];
118+
119+
$(formElement).on('submit', function (event) {
120+
event.preventDefault();
121+
request.send();
122+
});
123+
reCaptchaModel.reCaptchaCallback('testtoken');
124+
// check that submit button is enabled
125+
expect(submitButtonElement.disabled).toBeFalse();
126+
// check that token input value is set
127+
expect(reCaptchaModel.tokenField.value).toEqual('testtoken');
128+
// check that form is submitted
129+
expect(request.send).toHaveBeenCalled();
130+
});
131+
});
132+
});
133+
});
134+
});

0 commit comments

Comments
 (0)