Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c8ad867
security-package/issues/154: Add reCAPTCHA support for customer accco…
engcom-Foxtrot Mar 20, 2020
53d8db2
PB-582: Fix Page Builder builds
omiroshnichenko Jun 2, 2020
b122b3e
security-package/issues/234:
engcom-Foxtrot Jun 9, 2020
71d9c41
Merge pull request #238 from magento-obsessive-owls/PB-582-security
lenaorobei Jun 10, 2020
fcfaebf
security-package/issues/234:
engcom-Foxtrot Jun 10, 2020
16c0bc0
Merge branch '1.0.0-develop' into security-package/issues/234
engcom-Foxtrot Jun 10, 2020
c062d18
Merge pull request #241 from magento/security-package/issues/234
lenaorobei Jun 10, 2020
cb7b8fc
MQE-2194: fix mftf tests static check failures
jilu1 Jun 15, 2020
42d27ea
MQE-2194: fix mftf tests static check failures
jilu1 Jun 15, 2020
00f9c9b
MC-35119: U2F Key registration error in Chrome on Ubuntu
nathanjosiah Jun 16, 2020
674b8db
magento/security-package#224: Recaptcha badge is not shown on checkou…
engcom-Foxtrot Jun 2, 2020
4ff78d9
magento/security-package#224: Recaptcha badge is not shown on checkou…
engcom-Foxtrot Jun 16, 2020
2c2008b
magento/security-package#242: ReCAPTCHA v2 ("I am not a robot") for N…
engcom-Foxtrot Jun 12, 2020
a31d701
Static tests fix.
engcom-Foxtrot Jun 16, 2020
bd4465a
Fix JS code styles
lenaorobei Jun 16, 2020
70cd71c
Merge branch '224and242' of github.com:magento/security-package into …
lenaorobei Jun 16, 2020
e03deb4
Merge pull request #247 from magento/224and242
lenaorobei Jun 17, 2020
c3c6f99
Merge branch '1.0.0-develop' into MQE-2194-1.0.0
jilu1 Jun 17, 2020
08267b0
Merge pull request #246 from magento-pangolin/MQE-2194
nathanjosiah Jun 17, 2020
cfefd37
MC-35119: U2F Key registration error in Chrome on Ubuntu
nathanjosiah Jun 17, 2020
0a32b7c
Merge pull request #245 from magento-pangolin/MQE-2194-1.0.0
nathanjosiah Jun 17, 2020
c12081a
Merge branch '1.0.0-develop' into MC-35119
nathanjosiah Jun 17, 2020
55d1222
Merge pull request #250 from magento-borg/MC-35119
nathanjosiah Jun 18, 2020
92e6f43
Merge pull request #248 from magento/1.0.0-develop
lenaorobei Jun 18, 2020
89c7e9b
Merge pull request #251 from magento/1.0.0-master
lenaorobei Jun 22, 2020
e390f83
MC-35563: Unexpected reCAPTCHA Badge style appear when loading produc…
engcom-Foxtrot Jul 22, 2020
f23f46c
Merge remote-tracking branch 'origin/1.0-develop' into security-packa…
naydav Jul 22, 2020
dfa87e9
security-package/issues/154: Add reCAPTCHA support for customer accou…
naydav Jul 23, 2020
3e798f9
security-package/issues/154: Add reCAPTCHA support for customer accou…
engcom-Foxtrot Jul 23, 2020
083d3b6
Merge pull request #155 from magento/security-package/issues/154
naydav Jul 31, 2020
8ebc157
magento/security-package#260: Cover reCAPTCHA for customer account ed…
engcom-Foxtrot Aug 3, 2020
7ced666
Merge pull request #261 from magento/magento/security-package#260
naydav Aug 4, 2020
340e843
Merge pull request #257 from magento/MC-35563
naydav Aug 4, 2020
63756a1
Merge pull request #258 from magento/1.0-master
naydav Aug 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions ReCaptchaCustomer/Observer/EditCustomerObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\ReCaptchaCustomer\Observer;

use Magento\Framework\App\Action\Action;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\UrlInterface;
use Magento\ReCaptchaUi\Model\IsCaptchaEnabledInterface;
use Magento\ReCaptchaUi\Model\RequestHandlerInterface;

/**
* NewsletterObserver
*
* Process the response during customer account editing
*/
class EditCustomerObserver implements ObserverInterface
{
/**
* @var UrlInterface
*/
private $url;

/**
* @var IsCaptchaEnabledInterface
*/
private $isCaptchaEnabled;

/**
* @var RequestHandlerInterface
*/
private $requestHandler;

/**
* @param UrlInterface $url
* @param IsCaptchaEnabledInterface $isCaptchaEnabled
* @param RequestHandlerInterface $requestHandler
*/
public function __construct(
UrlInterface $url,
IsCaptchaEnabledInterface $isCaptchaEnabled,
RequestHandlerInterface $requestHandler
) {
$this->url = $url;
$this->isCaptchaEnabled = $isCaptchaEnabled;
$this->requestHandler = $requestHandler;
}

/**
* @inheritdoc
*
* @param Observer $observer
* @return void
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function execute(Observer $observer): void
{
$key = 'customer_edit';
if ($this->isCaptchaEnabled->isCaptchaEnabledFor($key)) {
/** @var Action $controller */
$controller = $observer->getControllerAction();
$request = $controller->getRequest();
$response = $controller->getResponse();
$redirectOnFailureUrl = $this->url->getUrl('*/*/edit', ['_secure' => true]);

$this->requestHandler->execute($key, $request, $response, $redirectOnFailureUrl);
}
}
}
316 changes: 316 additions & 0 deletions ReCaptchaCustomer/Test/Integration/EditFromTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\ReCaptchaCustomer\Test\Integration;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\Session;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Data\Form\FormKey;
use Magento\Framework\Message\MessageInterface;
use Magento\Framework\UrlInterface;
use Magento\Framework\Validation\ValidationResult;
use Magento\ReCaptchaUi\Model\CaptchaResponseResolverInterface;
use Magento\ReCaptchaValidation\Model\Validator;
use Magento\Store\Model\ScopeInterface;
use Magento\TestFramework\App\MutableScopeConfig;
use Magento\TestFramework\TestCase\AbstractController;
use PHPUnit\Framework\MockObject\MockObject;

/**
* @magentoDataFixture Magento/Customer/_files/customer.php
* @magentoAppArea frontend
* @magentoAppIsolation enabled
*/
class EditFromTest extends AbstractController
{
/**
* @var MutableScopeConfig
*/
private $mutableScopeConfig;

/**
* @var CustomerRepositoryInterface
*/
private $customerRepository;

/**
* @var FormKey
*/
private $formKey;

/**
* @var Session
*/
private $session;

/**
* @var UrlInterface
*/
private $url;

/**
* @var ValidationResult|MockObject
*/
private $captchaValidationResultMock;

/**
* @inheritDoc
*/
protected function setUp(): void
{
parent::setUp();
$this->mutableScopeConfig = $this->_objectManager->get(MutableScopeConfig::class);
$this->formKey = $this->_objectManager->get(FormKey::class);
$this->customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class);
$this->session = $this->_objectManager->get(Session::class);
$this->url = $this->_objectManager->get(UrlInterface::class);

$this->captchaValidationResultMock = $this->createMock(ValidationResult::class);
$captchaValidationResultMock = $this->createMock(Validator::class);
$captchaValidationResultMock->expects($this->any())
->method('isValid')
->willReturn($this->captchaValidationResultMock);
$this->_objectManager->addSharedInstance($captchaValidationResultMock, Validator::class);
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
*/
public function testGetRequestIfReCaptchaIsDisabled(): void
{
$this->setConfig(false, 'test_public_key', 'test_private_key');

$this->checkSuccessfulGetResponse();
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*
* It's needed for proper work of "ifconfig" in layout during tests running
* @magentoConfigFixture default_store recaptcha_frontend/type_for/customer_edit invisible
*/
public function testGetRequestIfReCaptchaKeysAreNotConfigured(): void
{
$this->setConfig(true, null, null);

$this->checkSuccessfulGetResponse();
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*
* It's needed for proper work of "ifconfig" in layout during tests running
* @magentoConfigFixture default_store recaptcha_frontend/type_for/customer_edit invisible
*/
public function testGetRequestIfReCaptchaIsEnabled(): void
{
$this->setConfig(true, 'test_public_key', 'test_private_key');

$this->checkSuccessfulGetResponse(true);
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
*/
public function testPostRequestIfReCaptchaIsDisabled(): void
{
$this->setConfig(false, 'test_public_key', 'test_private_key');

$this->checkSuccessfulPostResponse();
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*/
public function testPostRequestIfReCaptchaKeysAreNotConfigured(): void
{
$this->setConfig(true, null, null);

$this->checkSuccessfulPostResponse();
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*/
public function testPostRequestWithSuccessfulReCaptchaValidation(): void
{
$this->setConfig(true, 'test_public_key', 'test_private_key');
$this->captchaValidationResultMock->expects($this->once())->method('isValid')->willReturn(true);

$this->checkSuccessfulPostResponse(
[CaptchaResponseResolverInterface::PARAM_RECAPTCHA => 'test']
);
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*/
public function testPostRequestIfReCaptchaParameterIsMissed(): void
{
$this->setConfig(true, 'test_public_key', 'test_private_key');

$this->checkFailedPostResponse();
}

/**
* @magentoConfigFixture default_store customer/captcha/enable 0
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/public_key test_public_key
* @magentoConfigFixture base_website recaptcha_frontend/type_invisible/private_key test_private_key
* @magentoConfigFixture base_website recaptcha_frontend/type_for/customer_edit invisible
*/
public function testPostRequestWithFailedReCaptchaValidation(): void
{
$this->setConfig(true, 'test_public_key', 'test_private_key');
$this->captchaValidationResultMock->expects($this->once())->method('isValid')->willReturn(false);

$this->checkFailedPostResponse(
[CaptchaResponseResolverInterface::PARAM_RECAPTCHA => 'test']
);
}

/**
* @param bool $shouldContainReCaptcha
* @return void
*/
private function checkSuccessfulGetResponse($shouldContainReCaptcha = false): void
{
$this->session->loginById(1);
$this->dispatch('customer/account/edit');
$content = $this->getResponse()->getBody();

self::assertNotEmpty($content);

$shouldContainReCaptcha
? $this->assertStringContainsString('field-recaptcha', $content)
: $this->assertStringNotContainsString('field-recaptcha', $content);

self::assertEmpty($this->getSessionMessages(MessageInterface::TYPE_ERROR));
}

/**
* @param array $postValues
* @return void
*/
private function checkSuccessfulPostResponse(array $postValues = []): void
{
$this->session->loginById(1);
$this->makePostRequest($postValues);

$this->assertRedirect(self::equalTo($this->url->getRouteUrl('customer/account')));
self::assertEmpty($this->getSessionMessages(MessageInterface::TYPE_ERROR));

$customer = $this->customerRepository->getById(1);
$this->assertEquals('Test First Name', $customer->getFirstname());
$this->assertEquals('Test Last Name', $customer->getLastname());
$this->assertEquals('customer@example.com', $customer->getEmail());
}

/**
* @param array $postValues
* @return void
*/
private function checkFailedPostResponse(array $postValues = []): void
{
$this->session->loginById(1);
$this->makePostRequest($postValues);

$this->assertRedirect(self::stringStartsWith($this->url->getRouteUrl('customer/account/edit')));
$this->assertSessionMessages(
self::equalTo(['reCAPTCHA verification failed']),
MessageInterface::TYPE_ERROR
);

$customer = $this->customerRepository->getById(1);
$this->assertEquals('John', $customer->getFirstname());
$this->assertEquals('Smith', $customer->getLastname());
$this->assertEquals('customer@example.com', $customer->getEmail());
}

/**
* @param array $postValues
* @return void
*/
private function makePostRequest(array $postValues = []): void
{
$this->getRequest()
->setMethod(Http::METHOD_POST)
->setPostValue(
array_replace_recursive(
[
'form_key' => $this->formKey->getFormKey(),
'firstname' => 'Test First Name',
'lastname' => 'Test Last Name',
],
$postValues
)
);

$this->dispatch('customer/account/editpost');
}

/**
* @param bool $isEnabled
* @param string|null $public
* @param string|null $private
* @return void
*/
private function setConfig(bool $isEnabled, ?string $public, ?string $private): void
{
$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_for/customer_edit',
$isEnabled ? 'invisible' : null,
ScopeInterface::SCOPE_WEBSITE
);
$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_invisible/public_key',
$public,
ScopeInterface::SCOPE_WEBSITE
);
$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_invisible/private_key',
$private,
ScopeInterface::SCOPE_WEBSITE
);
}

protected function tearDown(): void
{
parent::tearDown();

$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_for/customer_edit',
null,
ScopeInterface::SCOPE_WEBSITE
);
$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_invisible/public_key',
null,
ScopeInterface::SCOPE_WEBSITE
);
$this->mutableScopeConfig->setValue(
'recaptcha_frontend/type_invisible/private_key',
null,
ScopeInterface::SCOPE_WEBSITE
);
}
}
Loading