Skip to content

Commit 63a7bc5

Browse files
committed
OXDEV-9078 Move unnecessary viewconfig methods logic to controller
Signed-off-by: Anton Fedurtsya <anton@fedurtsya.com>
1 parent 32cf6c8 commit 63a7bc5

4 files changed

Lines changed: 115 additions & 47 deletions

File tree

src/Authentication/TwoFactorAuth/Controller/TwoFactorAuthController.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ public function __construct(
3939
parent::__construct();
4040
}
4141

42+
public function render(): string
43+
{
44+
parent::render();
45+
46+
$isResendable = $this->twoFAService instanceof TwoFAResendableInterface;
47+
$this->addTplParam('resendable', $isResendable);
48+
49+
if ($isResendable) {
50+
$userId = $this->twoFAUserService->getPendingUserId();
51+
$this->addTplParam('remainingAttempts', $this->twoFAService->getRemainingAttempts($userId));
52+
$this->addTplParam('resendCooldownRemaining', $this->twoFAService->getCooldownRemaining($userId));
53+
}
54+
55+
return $this->_sThisTemplate;
56+
}
57+
4258
public function handleOTP(): ?string
4359
{
4460
$userId = $this->twoFAUserService->getPendingUserId();

src/Shared/Core/ViewConfig.php

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99

1010
namespace OxidEsales\SecurityModule\Shared\Core;
1111

12-
use OxidEsales\SecurityModule\Authentication\OAuth2\Service\ProviderCollectorInterface;
13-
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAResendableInterface;
14-
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAServiceInterface;
15-
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAUserServiceInterface;
16-
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAUserSettingsServiceInterface;
1712
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Settings\TwoFAShopSettingsInterface;
1813
use OxidEsales\SecurityModule\Captcha\Captcha\Image\Service\ImageCaptchaService;
1914
use OxidEsales\SecurityModule\Captcha\Service\CaptchaServiceInterface;
@@ -57,30 +52,6 @@ public function getImage(): string
5752
return 'data:image/jpeg;base64,' . base64_encode($images[ImageCaptchaService::CAPTCHA_NAME]);
5853
}
5954

60-
// todo-critical: move to controller
61-
public function getRemainingAttempts(): int
62-
{
63-
$twoFAService = $this->getService(TwoFAServiceInterface::class);
64-
if (!$twoFAService instanceof TwoFAResendableInterface) {
65-
return 0;
66-
}
67-
68-
$userId = $this->getService(TwoFAUserServiceInterface::class)->getPendingUserId();
69-
return $twoFAService->getRemainingAttempts($userId);
70-
}
71-
72-
// todo-critical: move to controller
73-
public function getResendCooldownRemaining(): int
74-
{
75-
$twoFAService = $this->getService(TwoFAServiceInterface::class);
76-
if (!$twoFAService instanceof TwoFAResendableInterface) {
77-
return 0;
78-
}
79-
80-
$userId = $this->getService(TwoFAUserServiceInterface::class)->getPendingUserId();
81-
return $twoFAService->getCooldownRemaining($userId);
82-
}
83-
8455
// todo-high: questionable if we want this method here at all, its just for one template - controller instead?
8556
public function isTwoFAEnabledForShop(): bool
8657
{
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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\Integration\Authentication\TwoFactorAuth\Controller;
11+
12+
use OxidEsales\Eshop\Core\UtilsView;
13+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Controller\TwoFactorAuthController;
14+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAResendableInterface;
15+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAServiceInterface;
16+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\TwoFAUserServiceInterface;
17+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Transput\AuthCodeRequestInterface;
18+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Transput\JsonResponseInterface;
19+
use OxidEsales\SecurityModule\Tests\Integration\IntegrationTestCase;
20+
use PHPUnit\Framework\Attributes\Test;
21+
use PHPUnit\Framework\MockObject\Generator\MockClass;
22+
use PHPUnit\Framework\MockObject\MockObject;
23+
24+
class TwoFactorAuthControllerTest extends IntegrationTestCase
25+
{
26+
#[Test]
27+
public function renderSetsResendableFalseWhenServiceIsNotResendable(): void
28+
{
29+
$sut = $this->getSut(
30+
twoFAService: $this->createStub(TwoFAServiceInterface::class),
31+
);
32+
$sut->render();
33+
34+
$this->assertFalse($sut->getViewDataElement('resendable'));
35+
}
36+
37+
#[Test]
38+
public function renderSetsResendableTrueAndParamsFromServiceWhenResendable(): void
39+
{
40+
$userId = uniqid();
41+
42+
$twoFAUserServiceStub = $this->createStub(TwoFAUserServiceInterface::class);
43+
$twoFAUserServiceStub->method('getPendingUserId')->willReturn($userId);
44+
45+
/** @var TwoFAServiceInterface&TwoFAResendableInterface&MockObject $twoFAServiceStub */
46+
$twoFAServiceStub = $this->createMockForIntersectionOfInterfaces([
47+
TwoFAServiceInterface::class,
48+
TwoFAResendableInterface::class,
49+
]);
50+
$twoFAServiceStub->method('getRemainingAttempts')->with($userId)->willReturn($remaining = random_int(1, 5));
51+
$twoFAServiceStub->method('getCooldownRemaining')->with($userId)->willReturn($cooldown = random_int(0, 30));
52+
53+
$sut = $this->getSut(
54+
twoFAService: $twoFAServiceStub,
55+
twoFAUserService: $twoFAUserServiceStub,
56+
);
57+
$sut->render();
58+
59+
$this->assertTrue($sut->getViewDataElement('resendable'));
60+
$this->assertSame($remaining, $sut->getViewDataElement('remainingAttempts'));
61+
$this->assertSame($cooldown, $sut->getViewDataElement('resendCooldownRemaining'));
62+
}
63+
64+
private function getSut(
65+
TwoFAServiceInterface $twoFAService = null,
66+
TwoFAUserServiceInterface $twoFAUserService = null,
67+
AuthCodeRequestInterface $authCodeRequest = null,
68+
UtilsView $utilsView = null,
69+
JsonResponseInterface $jsonResponse = null,
70+
): TwoFactorAuthController {
71+
return new TwoFactorAuthController(
72+
twoFAService: $twoFAService ?? $this->createStub(TwoFAServiceInterface::class),
73+
twoFAUserService: $twoFAUserService ?? $this->createStub(TwoFAUserServiceInterface::class),
74+
authCodeRequest: $authCodeRequest ?? $this->createStub(AuthCodeRequestInterface::class),
75+
utilsView: $utilsView ?? $this->createStub(UtilsView::class),
76+
jsonResponse: $jsonResponse ?? $this->createStub(JsonResponseInterface::class),
77+
);
78+
}
79+
}

views/twig/templates/two_factor_auth.html.twig

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,26 @@
3535
<label for="auth_code" class="req">{{ translate({ ident: "OE_SECURITY_ENTER_CODE" }) }}</label>
3636
</div>
3737

38-
<div class="mb-3 d-flex justify-content-between align-items-center">
39-
<small class="text-muted">
40-
{{ translate({ ident: "OE_SECURITY_REMAINING_ATTEMPTS" }) }}:
41-
<strong id="remaining-attempts">{{ oViewConf.getRemainingAttempts() }}</strong>
42-
</small>
43-
<button
44-
id="resend-btn"
45-
class="btn btn-link btn-sm px-0"
46-
type="button"
47-
data-cooldown="60"
48-
data-cooldown-remaining="{{ oViewConf.getResendCooldownRemaining() }}"
49-
data-url="{{ seo_url({ ident: oViewConf.getSelfLink()|cat("cl=twofactorauth&fnc=resendCode") }) }}"
50-
data-text-default="{{ translate({ ident: "RESEND_CODE" }) }}"
51-
data-text-sending="{{ translate({ ident: "RESEND_CODE_SENDING" }) }}"
52-
data-text-error="{{ translate({ ident: "RESEND_CODE_ERROR" }) }}"
53-
data-text-countdown="{{ translate({ ident: "RESEND_CODE_COUNTDOWN" }) }}"
54-
>{{ translate({ ident: "RESEND_CODE" }) }}</button>
55-
</div>
38+
{% if resendable %}
39+
<div class="mb-3 d-flex justify-content-between align-items-center">
40+
<small class="text-muted">
41+
{{ translate({ ident: "OE_SECURITY_REMAINING_ATTEMPTS" }) }}:
42+
<strong id="remaining-attempts">{{ remainingAttempts }}</strong>
43+
</small>
44+
<button
45+
id="resend-btn"
46+
class="btn btn-link btn-sm px-0"
47+
type="button"
48+
data-cooldown="60"
49+
data-cooldown-remaining="{{ resendCooldownRemaining }}"
50+
data-url="{{ seo_url({ ident: oViewConf.getSelfLink()|cat("cl=twofactorauth&fnc=resendCode") }) }}"
51+
data-text-default="{{ translate({ ident: "RESEND_CODE" }) }}"
52+
data-text-sending="{{ translate({ ident: "RESEND_CODE_SENDING" }) }}"
53+
data-text-error="{{ translate({ ident: "RESEND_CODE_ERROR" }) }}"
54+
data-text-countdown="{{ translate({ ident: "RESEND_CODE_COUNTDOWN" }) }}"
55+
>{{ translate({ ident: "RESEND_CODE" }) }}</button>
56+
</div>
57+
{% endif %}
5658

5759
<p id="resend-hint" class="small text-muted" aria-live="polite"></p>
5860

0 commit comments

Comments
 (0)