Skip to content

Commit a61874f

Browse files
committed
OXDEV-9243 Allow Honeypot CAPTCHA to be enabled independently
1 parent 7bc7f53 commit a61874f

12 files changed

Lines changed: 131 additions & 21 deletions

File tree

src/Captcha/Captcha/HoneyPot/Exception/CaptchaValidateException.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
namespace OxidEsales\SecurityModule\Captcha\Captcha\HoneyPot\Exception;
1111

12-
use OxidEsales\Eshop\Core\Exception\StandardException;
12+
use OxidEsales\Eshop\Core\Exception\InputException;
1313

14-
class CaptchaValidateException extends StandardException
14+
class CaptchaValidateException extends InputException
1515
{
1616
}

src/Captcha/Captcha/HoneyPot/Service/HoneyPotCaptchaService.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace OxidEsales\SecurityModule\Captcha\Captcha\HoneyPot\Service;
1111

1212
use OxidEsales\Eshop\Core\Request;
13+
use OxidEsales\SecurityModule\Captcha\Captcha\HoneyPot\Exception\CaptchaValidateException;
1314
use OxidEsales\SecurityModule\Captcha\Service\ModuleSettingsServiceInterface;
1415
use Psr\Log\LoggerInterface;
1516

@@ -43,7 +44,8 @@ public function validate(Request $request): void
4344
}
4445

4546
if (strlen($value) > 1) {
46-
$this->logger->debug('FORM_VALIDATION_FAILED');
47+
$this->logger->debug('HONEYPOT_VALIDATION_FAILED');
48+
throw new CaptchaValidateException('FORM_VALIDATION_FAILED');
4749
}
4850
}
4951

src/Captcha/Form/ContactFormCaptchaValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function __construct(
3838
*/
3939
public function isValid(FormInterface $form)
4040
{
41-
if (!$this->settingsService->isCaptchaEnabled()) {
41+
if (!$this->settingsService->isCaptchaEnabled() && !$this->settingsService->isHoneyPotCaptchaEnabled()) {
4242
return true;
4343
}
4444

src/Captcha/Shop/NewsletterController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
namespace OxidEsales\SecurityModule\Captcha\Shop;
1111

12+
use OxidEsales\Eshop\Core\Exception\StandardException;
1213
use OxidEsales\Eshop\Core\Registry;
13-
use OxidEsales\SecurityModule\Captcha\Captcha\Image\Exception\CaptchaValidateException;
1414
use OxidEsales\SecurityModule\Captcha\Service\CaptchaServiceInterface;
1515
use OxidEsales\SecurityModule\Captcha\Service\ModuleSettingsServiceInterface;
1616

@@ -19,7 +19,7 @@ class NewsletterController extends NewsletterController_parent
1919
public function send(): ?bool
2020
{
2121
$settingsService = $this->getService(ModuleSettingsServiceInterface::class);
22-
if (!$settingsService->isCaptchaEnabled()) {
22+
if (!$settingsService->isCaptchaEnabled() && !$settingsService->isHoneyPotCaptchaEnabled()) {
2323
return parent::send();
2424
}
2525

@@ -29,7 +29,7 @@ public function send(): ?bool
2929
$captchaService->validate(
3030
Registry::getRequest()
3131
);
32-
} catch (CaptchaValidateException $e) {
32+
} catch (StandardException $e) {
3333
Registry::getUtilsView()->addErrorToDisplay($e->getMessage());
3434
return false;
3535
}

src/Shared/Model/User.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
use OxidEsales\Eshop\Core\Exception\InputException;
1313
use OxidEsales\Eshop\Core\Exception\UserException;
1414
use OxidEsales\Eshop\Core\Registry;
15-
use OxidEsales\SecurityModule\Captcha\Captcha\Image\Exception\CaptchaValidateException;
15+
use OxidEsales\SecurityModule\Captcha\Captcha\Image\Exception\CaptchaValidateException as ImageCaptchaException;
16+
use OxidEsales\SecurityModule\Captcha\Captcha\HoneyPot\Exception\CaptchaValidateException as HoneyPotCaptchaException;
1617
use OxidEsales\SecurityModule\Captcha\Service\CaptchaServiceInterface;
1718
use OxidEsales\SecurityModule\Captcha\Service\ModuleSettingsServiceInterface;
1819
use OxidEsales\SecurityModule\Shared\Core\InputValidator;
@@ -28,7 +29,7 @@ class User extends User_parent
2829
public function checkValues($sLogin, $sPassword, $sPassword2, $aInvAddress, $aDelAddress): void
2930
{
3031
$settingsService = $this->getService(ModuleSettingsServiceInterface::class);
31-
if ($settingsService->isCaptchaEnabled()) {
32+
if ($settingsService->isCaptchaEnabled() || $settingsService->isHoneyPotCaptchaEnabled()) {
3233
/** @var InputValidator $oInputValidator */
3334
$oInputValidator = Registry::getInputValidator();
3435
$captchaService = $this->getService(CaptchaServiceInterface::class);
@@ -37,14 +38,16 @@ public function checkValues($sLogin, $sPassword, $sPassword2, $aInvAddress, $aDe
3738
$captchaService->validate(
3839
Registry::getRequest()
3940
);
40-
} catch (CaptchaValidateException $e) {
41+
} catch (ImageCaptchaException $e) {
4142
$oInputValidator->addValidationError(
4243
"captcha",
4344
oxNew(
4445
InputException::class,
4546
Registry::getLang()->translateString($e->getMessage())
4647
)
4748
);
49+
} catch (HoneyPotCaptchaException $e) {
50+
throw $e;
4851
}
4952
}
5053

@@ -68,7 +71,7 @@ public function login($userName, $password, $setSessionCookie = false): bool
6871
$captchaService->validate(
6972
Registry::getRequest()
7073
);
71-
} catch (CaptchaValidateException $e) {
74+
} catch (ImageCaptchaException $e) {
7275
throw oxNew(UserException::class, $e->getMessage());
7376
}
7477
}

tests/Codeception/Acceptance/BaseCest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ protected function getExistingUserData()
2121
return Fixtures::get('existingUser');
2222
}
2323

24+
protected function getNewUserData()
25+
{
26+
return Fixtures::get('newUser');
27+
}
28+
2429
protected function setPasswordState(bool $state)
2530
{
2631
ContainerFacade::get(PasswordSettingsServiceInterface::class)->saveIsPasswordPolicyEnabled($state);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Tests\Codeception\Acceptance;
11+
12+
use Codeception\Util\Fixtures;
13+
use OxidEsales\Codeception\Module\Translation\Translator;
14+
use OxidEsales\Codeception\Page\DataObject\ContactData;
15+
use OxidEsales\SecurityModule\Tests\Codeception\Support\AcceptanceTester;
16+
17+
/**
18+
* @group oe_security_module
19+
* @group oe_security_module_honeypot_captcha
20+
*/
21+
class HoneyPotCaptchaCest extends BaseCest
22+
{
23+
private string $honeyPotInput = "lastname_confirm";
24+
25+
public function _before(AcceptanceTester $I): void
26+
{
27+
$this->setCaptchaState(false);
28+
$this->setPasswordState(false);
29+
}
30+
31+
public function testHoneyPotCaptchaOnRegistrationPage(AcceptanceTester $I): void
32+
{
33+
$homePage = $I->openShop();
34+
$registrationPage = $homePage->openUserRegistrationPage();
35+
$userData = $this->getNewUserData();
36+
$this->fillRegistrationForm($I, $userData);
37+
$I->executeJS("document.querySelector('input[name=\"$this->honeyPotInput\"]').value = 'some value';");
38+
$I->retryClick($registrationPage->saveFormButton);
39+
40+
$I->see(Translator::translate('FORM_VALIDATION_FAILED'));
41+
}
42+
43+
public function testHoneyPotCaptchaOnContactPage(AcceptanceTester $I): void
44+
{
45+
$homePage = $I->openShop();
46+
$contactPage = $homePage->openContactPage();
47+
$userData = $this->getExistingUserData();
48+
49+
$contactData = new ContactData();
50+
$contactData->setEmail($userData['userLoginName']);
51+
$contactPage->fillInContactData($contactData);
52+
$I->executeJS("document.querySelector('input[name=\"$this->honeyPotInput\"]').value = 'some value';");
53+
$contactPage->sendContactData();
54+
55+
$I->see(Translator::translate('FORM_VALIDATION_FAILED'));
56+
}
57+
58+
public function testHoneyPotCaptchaOnNewsletterPage(AcceptanceTester $I): void
59+
{
60+
61+
$userData = Fixtures::get('existingUser');
62+
63+
$homePage = $I->openShop();
64+
$newsletterPage = $homePage->subscribeForNewsletter($userData['userLoginName']);
65+
$I->executeJS("document.querySelector('input[name=\"$this->honeyPotInput\"]').value = 'some value';");
66+
$newsletterPage->subscribe();
67+
68+
$I->see(Translator::translate('FORM_VALIDATION_FAILED'));
69+
}
70+
71+
private function fillRegistrationForm(AcceptanceTester $I, array $userData)
72+
{
73+
foreach ($userData['inputFields'] as $key => $value) {
74+
$I->fillField("#$key", $value);
75+
}
76+
77+
foreach ($userData['selectFields'] as $key => $value) {
78+
$I->selectOption("select#$key", $value);
79+
}
80+
}
81+
}

tests/Codeception/Support/Data/users.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,20 @@
1515
'userName' => 'UserNamešÄßüл',
1616
'userLastName' => 'UserSurnamešÄßüл',
1717
],
18+
'newUser' => [
19+
'inputFields' => [
20+
'userLoginName' => 'new_test_user@oxid-esales.dev',
21+
'userPassword' => 'useruser',
22+
'userPasswordConfirm' => 'useruser',
23+
'invadr[oxuser__oxfname]' => 'New',
24+
'invadr[oxuser__oxlname]' => 'User',
25+
'invadr[oxuser__oxstreet]' => 'Street',
26+
'invadr[oxuser__oxstreetnr]' => '55',
27+
'invadr[oxuser__oxzip]' => '5555',
28+
'invadr[oxuser__oxcity]' => 'City',
29+
],
30+
'selectFields' => [
31+
'invCountrySelect' => 'a7c40f631fc920687.20179984'
32+
]
33+
]
1834
];

tests/Unit/Captcha/Captcha/HoneyPot/Service/HoneyPotCaptchaServiceTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function testValidationThrowsException(): void
6767
logger: $logger
6868
);
6969

70+
$this->expectException(CaptchaValidateException::class);
7071
$sut->validate($request);
7172
}
7273

translations/de/oesecuritymodule_lang.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
'ERROR_EXPIRED_CAPTCHA' => 'CAPTCHA ist abgelaufen.',
2424
'ERROR_INVALID_CAPTCHA' => 'CAPTCHA Texteingabe ist nicht korrekt.',
2525
'ERROR_EMPTY_CAPTCHA' => 'CAPTCHA Eingabefeld bitte mit dem Bildtext füllen.',
26+
'FORM_VALIDATION_FAILED' => 'Unexpected error occurred. Please refresh and try again.',
2627

2728
'PASSWORD_REQUIREMENTS' => 'Passwort-Anforderungen',
2829
'PASSWORD_MIN_LENGTH' => 'Mindestens %d Zeichen.',

0 commit comments

Comments
 (0)