Skip to content

Commit 232dc03

Browse files
committed
OXDEV-10012 Rebase and fix tests
1 parent 677b6e4 commit 232dc03

9 files changed

Lines changed: 775 additions & 309 deletions

File tree

src/Shared/Model/User.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use OxidEsales\Eshop\Core\Exception\InputException;
1313
use OxidEsales\Eshop\Core\Exception\UserException;
1414
use OxidEsales\Eshop\Core\Registry;
15-
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\AuthorizeService;
1615
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Service\UserServiceInterface;
1716
use OxidEsales\SecurityModule\Captcha\Captcha\Image\Exception\CaptchaValidateException as ImageCaptchaException;
1817
use OxidEsales\SecurityModule\Captcha\Captcha\HoneyPot\Exception\CaptchaValidateException as HoneyPotCaptchaException;
@@ -89,14 +88,19 @@ protected function onLogin($userName, $password)
8988
return;
9089
}
9190

91+
$userId = $this->getId();
92+
if (!$userId) {
93+
return;
94+
}
95+
9296
$userService = $this->getService(UserServiceInterface::class);
9397
$userSessionKey = Registry::getSession()->getVariable('OTP_PASS');
94-
if ($userSessionKey && $userSessionKey === $this->getId()) {
98+
if ($userSessionKey && $userSessionKey === $userId) {
9599
$userService->clearOTPSessionVariables();
96100
return;
97101
}
98102

99-
$userService->handleLogin($this->getId());
103+
$userService->handleLogin($userId);
100104
}
101105

102106
private function isCaptchaEnabled(): bool

tests/Integration/Shared/Model/UserTest.php

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,26 @@ public function testLoginWithEmptyCaptcha()
116116
$subject->login('', '');
117117
}
118118

119-
public function testLoginWithOTPEnabledAndValidCredentialsReturnsFalse(): void
119+
public function testLoginWithValidCaptchaAndValidCredentials(): void
120+
{
121+
$this->disableTwoFactorAuth();
122+
123+
$this->requestMock
124+
->method('getRequestParameter')
125+
->willReturnCallback(function ($param) {
126+
if ($param === 'captcha') {
127+
return 'valid_captcha';
128+
}
129+
return null;
130+
});
131+
132+
$subject = oxNew(User::class);
133+
$result = $subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
134+
135+
$this->assertTrue($result);
136+
}
137+
138+
public function testLoginWithOTPEnabledAndValidCredentialsRedirectsToOTP(): void
120139
{
121140
$this->disableCaptcha();
122141
$this->enableTwoFactorAuth();
@@ -126,11 +145,9 @@ public function testLoginWithOTPEnabledAndValidCredentialsReturnsFalse(): void
126145
Registry::set(Utils::class, $utilsMock);
127146

128147
$subject = oxNew(User::class);
129-
$result = $subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
148+
$subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
130149

131-
$this->assertFalse($result);
132-
$this->assertEquals(
133-
self::OTP_USER_NAME,
150+
$this->assertNotNull(
134151
Registry::getSession()->getVariable(AuthorizeService::USER_SESSION_KEY)
135152
);
136153
}
@@ -173,20 +190,74 @@ public function testLoginWithOTPDisabledCallsParentLogin(): void
173190
);
174191
}
175192

176-
public function testLoginWithOTPEnabledStoresUserInSession(): void
193+
public function testLoginWithOTPEnabledStoresUserIdInSession(): void
194+
{
195+
$this->disableCaptcha();
196+
$this->enableTwoFactorAuth();
197+
198+
$utilsMock = $this->createMock(Utils::class);
199+
$utilsMock->method('redirect');
200+
Registry::set(Utils::class, $utilsMock);
201+
202+
$subject = oxNew(User::class);
203+
$subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
204+
205+
$sessionUserId = Registry::getSession()->getVariable(AuthorizeService::USER_SESSION_KEY);
206+
$this->assertNotNull($sessionUserId);
207+
$this->assertEquals($subject->getId(), $sessionUserId);
208+
}
209+
210+
public function testLoginWithOTPPassSessionVariableSkipsOTPRedirect(): void
211+
{
212+
$this->disableCaptcha();
213+
$this->enableTwoFactorAuth();
214+
215+
$subject = oxNew(User::class);
216+
$subject->load($this->getOTPUserId());
217+
218+
Registry::getSession()->setVariable('OTP_PASS', $subject->getId());
219+
220+
$utilsMock = $this->createMock(Utils::class);
221+
$utilsMock->expects($this->never())->method('redirect');
222+
Registry::set(Utils::class, $utilsMock);
223+
224+
$result = $subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
225+
226+
$this->assertTrue($result);
227+
$this->assertNull(
228+
Registry::getSession()->getVariable('OTP_PASS'),
229+
'OTP_PASS session variable should be cleared after successful login'
230+
);
231+
$this->assertNull(
232+
Registry::getSession()->getVariable(AuthorizeService::USER_SESSION_KEY),
233+
'USER_SESSION_KEY should not be set when OTP was already validated'
234+
);
235+
}
236+
237+
public function testLoginWithOTPPassSessionVariableMismatchTriggersOTPFlow(): void
177238
{
178239
$this->disableCaptcha();
179240
$this->enableTwoFactorAuth();
180241

242+
$mismatchedUserId = 'different-user-id';
243+
Registry::getSession()->setVariable('OTP_PASS', $mismatchedUserId);
244+
181245
$utilsMock = $this->createMock(Utils::class);
182246
$utilsMock->method('redirect');
183247
Registry::set(Utils::class, $utilsMock);
184248

185249
$subject = oxNew(User::class);
186250
$subject->login(self::OTP_USER_NAME, self::OTP_USER_PASSWORD);
187251

188-
$sessionUserName = Registry::getSession()->getVariable(AuthorizeService::USER_SESSION_KEY);
189-
$this->assertEquals(self::OTP_USER_NAME, $sessionUserName);
252+
$this->assertNotNull(
253+
Registry::getSession()->getVariable(AuthorizeService::USER_SESSION_KEY),
254+
'USER_SESSION_KEY should be set when OTP flow is triggered'
255+
);
256+
$this->assertSame(
257+
$mismatchedUserId,
258+
Registry::getSession()->getVariable('OTP_PASS'),
259+
'OTP_PASS should NOT be cleared when user ID does not match'
260+
);
190261
}
191262

192263
private function enableTwoFactorAuth(): void
@@ -219,4 +290,11 @@ private function disableCaptcha(): void
219290
$captchaSettings = ContainerFacade::get(CaptchaSettingsServiceInterface::class);
220291
$captchaSettings->saveIsCaptchaEnabled(false);
221292
}
293+
294+
private function getOTPUserId(): string
295+
{
296+
$user = oxNew(User::class);
297+
$user->load($user->getIdByUserName(self::OTP_USER_NAME));
298+
return $user->getId();
299+
}
222300
}

0 commit comments

Comments
 (0)