diff --git a/src/Application/Controller/Admin/d3webauthnadminlogin.php b/src/Application/Controller/Admin/d3webauthnadminlogin.php index 5233f5f..bfaf420 100755 --- a/src/Application/Controller/Admin/d3webauthnadminlogin.php +++ b/src/Application/Controller/Admin/d3webauthnadminlogin.php @@ -32,8 +32,10 @@ use OxidEsales\Eshop\Core\Exception\ConnectionException; use OxidEsales\Eshop\Core\Exception\CookieException; use OxidEsales\Eshop\Core\Exception\UserException; use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Request; use OxidEsales\Eshop\Core\SystemEventHandler; use OxidEsales\Eshop\Core\Utils; +use OxidEsales\Eshop\Core\UtilsServer; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -61,14 +63,14 @@ class d3webauthnadminlogin extends AdminController */ public function render(): string { - if ($this->d3GetSession()->hasVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_AUTH) || - !$this->d3GetSession()->hasVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER) - ) { + if ($this->d3GetSession()->hasVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_AUTH)) { $this->getUtils()->redirect('index.php?cl=admin_start'); + } elseif (!$this->d3GetSession()->hasVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER)) { + $this->getUtils()->redirect('index.php?cl=login'); } /** @var d3_LoginController_Webauthn $loginController */ - $loginController = oxNew(LoginController::class); + $loginController = $this->d3WebauthnGetLoginController(); $loginController->d3WebauthnAfterLoginChangeLanguage(); $this->generateCredentialRequest(); @@ -113,75 +115,77 @@ class d3webauthnadminlogin extends AdminController */ public function d3AssertAuthn(): ?string { - $myUtilsView = Registry::getUtilsView(); + $myUtilsView = $this->d3GetUtilsViewObject(); /** @var d3_User_Webauthn $user */ $user = $this->d3GetUserObject(); $userId = $this->d3GetSession()->getVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER); - $selectedProfile = Registry::getRequest()->getRequestEscapedParameter('profile'); + $selectedProfile = $this->d3WebAuthnGetRequest()->getRequestEscapedParameter('profile'); try { - $error = Registry::getRequest()->getRequestEscapedParameter('error'); + $error = $this->d3WebAuthnGetRequest()->getRequestEscapedParameter('error'); if (strlen((string) $error)) { /** @var WebauthnGetException $e */ $e = oxNew(WebauthnGetException::class, $error); throw $e; } - $credential = Registry::getRequest()->getRequestEscapedParameter('credential'); - if (strlen((string) $credential)) { - $webAuthn = $this->d3GetWebauthnObject(); - $webAuthn->assertAuthn($credential); - - $user->load($userId); - $session = $this->d3GetSession(); - $adminProfiles = $session->getVariable("aAdminProfiles"); - $session->initNewSession(); - $session->setVariable("aAdminProfiles", $adminProfiles); - $session->setVariable(WebauthnConf::OXID_ADMIN_AUTH, $userId); - - $cookie = Registry::getUtilsServer()->getOxCookie(); - if ($cookie === null) { - throw oxNew(CookieException::class, 'ERROR_MESSAGE_COOKIE_NOCOOKIE'); - } - - if ($user->oxuser__oxrights->value === 'user') { - throw oxNew(UserException::class, 'ERROR_MESSAGE_USER_NOVALIDLOGIN'); - } - $iSubshop = (int) $user->oxuser__oxrights->value; - if ($iSubshop) { - Registry::getSession()->setVariable("shp", $iSubshop); - Registry::getSession()->setVariable('currentadminshop', $iSubshop); - Registry::getConfig()->setShopId($iSubshop); - } - - //execute onAdminLogin() event - $oEvenHandler = oxNew(SystemEventHandler::class); - $oEvenHandler->onAdminLogin(Registry::getConfig()->getShopId()); - - /** @var d3_LoginController_Webauthn $loginController */ - $loginController = oxNew(LoginController::class); - $loginController->d3webauthnAfterLogin(); - - return "admin_start"; + $credential = $this->d3WebAuthnGetRequest()->getRequestEscapedParameter('credential'); + if (!strlen((string) $credential)) { + /** @var WebauthnGetException $e */ + $e = oxNew(WebauthnGetException::class, 'missing credential data'); + throw $e; } + + $webAuthn = $this->d3GetWebauthnObject(); + $webAuthn->assertAuthn($credential); + $user->load($userId); + $session = $this->d3GetSession(); + $adminProfiles = $session->getVariable("aAdminProfiles"); + $session->initNewSession(); + $session->setVariable("aAdminProfiles", $adminProfiles); + $session->setVariable(WebauthnConf::OXID_ADMIN_AUTH, $userId); + + $cookie = $this->d3WebauthnGetUtilsServer()->getOxCookie(); + if ($cookie === null) { + /** @var CookieException $exc */ + $exc = oxNew(CookieException::class, 'ERROR_MESSAGE_COOKIE_NOCOOKIE'); + throw $exc; + } + + if ($user->getFieldData('oxrights') === 'user') { + /** @var UserException $exc */ + $exc = oxNew(UserException::class, 'ERROR_MESSAGE_USER_NOVALIDLOGIN'); + throw $exc; + } + $iSubshop = (int) $user->getFieldData('oxrights'); + + if ($iSubshop) { + $session->setVariable("shp", $iSubshop); + $session->setVariable('currentadminshop', $iSubshop); + Registry::getConfig()->setShopId($iSubshop); + } + + //execute onAdminLogin() event + $oEvenHandler = $this->d3WebauthnGetEventHandler(); + $oEvenHandler->onAdminLogin(Registry::getConfig()->getShopId()); + + /** @var d3_LoginController_Webauthn $loginController */ + $loginController = $this->d3WebauthnGetLoginController(); + $loginController->d3webauthnAfterLogin(); + + return "admin_start"; } catch (UserException $oEx) { $myUtilsView->addErrorToDisplay('LOGIN_ERROR'); $oStr = getStr(); $this->addTplParam('user', $oStr->htmlspecialchars($userId)); $this->addTplParam('profile', $oStr->htmlspecialchars($selectedProfile)); - - return null; } catch (CookieException $oEx) { $myUtilsView->addErrorToDisplay('LOGIN_NO_COOKIE_SUPPORT'); $oStr = getStr(); $this->addTplParam('user', $oStr->htmlspecialchars($userId)); $this->addTplParam('profile', $oStr->htmlspecialchars($selectedProfile)); - - return null; - } catch (ConnectionException $oEx) { - $myUtilsView->addErrorToDisplay($oEx); } catch (WebauthnException $e) { - $this->d3GetUtilsViewObject()->addErrorToDisplay($e); + $myUtilsView->addErrorToDisplay($e); $this->d3GetLoggerObject()->error($e->getDetailedErrorMessage(), ['UserId' => $userId]); $this->d3GetLoggerObject()->debug($e->getTraceAsString()); $user->logout(); @@ -201,7 +205,7 @@ class d3webauthnadminlogin extends AdminController /** * @return string|null */ - public function getPreviousClass(): ?string + public function d3GetPreviousClass(): ?string { return $this->d3GetSession()->getVariable(WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTCLASS); } @@ -211,7 +215,7 @@ class d3webauthnadminlogin extends AdminController */ public function previousClassIsOrderStep(): bool { - $sClassKey = $this->getPreviousClass(); + $sClassKey = $this->d3GetPreviousClass(); $resolvedClass = $this->d3GetControllerClassNameResolver()->getClassNameById($sClassKey); $resolvedClass = $resolvedClass ?: 'start'; @@ -227,4 +231,36 @@ class d3webauthnadminlogin extends AdminController { return $this->previousClassIsOrderStep(); } + + /** + * @return mixed|LoginController + */ + public function d3WebauthnGetLoginController() + { + return oxNew(LoginController::class); + } + + /** + * @return SystemEventHandler + */ + public function d3WebauthnGetEventHandler(): SystemEventHandler + { + return oxNew(SystemEventHandler::class); + } + + /** + * @return Request + */ + public function d3WebAuthnGetRequest(): Request + { + return Registry::getRequest(); + } + + /** + * @return UtilsServer + */ + public function d3WebauthnGetUtilsServer(): UtilsServer + { + return Registry::getUtilsServer(); + } } \ No newline at end of file diff --git a/src/Application/Controller/d3webauthnlogin.php b/src/Application/Controller/d3webauthnlogin.php index 105072e..de0bb27 100755 --- a/src/Application/Controller/d3webauthnlogin.php +++ b/src/Application/Controller/d3webauthnlogin.php @@ -17,11 +17,9 @@ namespace D3\Webauthn\Application\Controller; use D3\TestingTools\Production\IsMockable; use D3\Webauthn\Application\Controller\Traits\helpersTrait; -use D3\Webauthn\Application\Model\Exceptions\WebauthnGetException; use D3\Webauthn\Application\Model\Webauthn; use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\Application\Model\Exceptions\WebauthnException; -use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn; use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; use Doctrine\DBAL\Exception as DoctrineException; use OxidEsales\Eshop\Application\Controller\FrontendController; @@ -66,11 +64,6 @@ class d3webauthnlogin extends FrontendController !$this->d3GetSession()->hasVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER) ) { $this->getUtils()->redirect('index.php?cl=start'); - if (!defined('OXID_PHP_UNIT')) { - // @codeCoverageIgnoreStart - exit; - // @codeCoverageIgnoreEnd - } } $this->generateCredentialRequest(); @@ -117,7 +110,7 @@ class d3webauthnlogin extends FrontendController /** * @return string|null */ - public function getPreviousClass(): ?string + public function d3GetPreviousClass(): ?string { return $this->d3GetSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS); } @@ -127,7 +120,7 @@ class d3webauthnlogin extends FrontendController */ public function previousClassIsOrderStep(): bool { - $sClassKey = $this->getPreviousClass(); + $sClassKey = $this->d3GetPreviousClass(); $resolvedClass = $this->d3GetControllerClassNameResolver()->getClassNameById($sClassKey); $resolvedClass = $resolvedClass ?: 'start'; diff --git a/src/Modules/Application/Component/d3_webauthn_UserComponent.php b/src/Modules/Application/Component/d3_webauthn_UserComponent.php index 6d8d92b..77f38ec 100755 --- a/src/Modules/Application/Component/d3_webauthn_UserComponent.php +++ b/src/Modules/Application/Component/d3_webauthn_UserComponent.php @@ -24,6 +24,7 @@ use Doctrine\DBAL\Driver\Exception as DoctrineDriverException; use Doctrine\DBAL\Exception; use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Request; use OxidEsales\Eshop\Core\Session; use OxidEsales\Eshop\Core\UtilsView; use Psr\Container\ContainerExceptionInterface; @@ -41,8 +42,8 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent */ public function login() { - $lgn_user = Registry::getRequest()->getRequestParameter('lgn_usr'); - $password = Registry::getRequest()->getRequestParameter('lgn_pwd'); + $lgn_user = $this->d3WebAuthnGetRequest()->getRequestParameter('lgn_usr'); + $password = $this->d3WebAuthnGetRequest()->getRequestParameter('lgn_pwd'); /** @var d3_User_Webauthn $user */ $user = oxNew(User::class); $userId = $user->d3GetLoginUserId($lgn_user); @@ -112,21 +113,21 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent $userId = $this->d3WebauthnGetSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER); try { - $error = Registry::getRequest()->getRequestEscapedParameter('error'); + $error = $this->d3WebAuthnGetRequest()->getRequestEscapedParameter('error'); if (strlen((string) $error)) { /** @var WebauthnGetException $e */ $e = oxNew(WebauthnGetException::class, $error); throw $e; } - $credential = Registry::getRequest()->getRequestEscapedParameter('credential'); + $credential = $this->d3WebAuthnGetRequest()->getRequestEscapedParameter('credential'); if (strlen((string) $credential)) { $webAuthn = $this->d3GetWebauthnObject(); $webAuthn->assertAuthn($credential); $user->load($userId); // relogin, don't extract from this try block - $setSessionCookie = Registry::getRequest()->getRequestParameter('lgn_cook'); + $setSessionCookie = $this->d3WebAuthnGetRequest()->getRequestParameter('lgn_cook'); $this->d3WebauthnGetSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $credential); $this->d3WebauthnGetSession()->setVariable(WebauthnConf::OXID_FRONTEND_AUTH, $user->getId()); $this->setUser(null); @@ -182,4 +183,12 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent { return Registry::getLogger(); } + + /** + * @return Request + */ + public function d3WebAuthnGetRequest(): Request + { + return Registry::getRequest(); + } } \ No newline at end of file diff --git a/src/tests/unit/Application/Controller/Admin/d3webauthnadminloginTest.php b/src/tests/unit/Application/Controller/Admin/d3webauthnadminloginTest.php index 5923490..67b2a06 100644 --- a/src/tests/unit/Application/Controller/Admin/d3webauthnadminloginTest.php +++ b/src/tests/unit/Application/Controller/Admin/d3webauthnadminloginTest.php @@ -17,7 +17,21 @@ namespace D3\Webauthn\tests\unit\Application\Controller\Admin; use D3\TestingTools\Development\CanAccessRestricted; use D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin; +use D3\Webauthn\Application\Controller\d3webauthnlogin; +use D3\Webauthn\Application\Model\Exceptions\WebauthnException; +use D3\Webauthn\Application\Model\Webauthn; +use D3\Webauthn\Application\Model\WebauthnConf; use D3\Webauthn\tests\unit\Application\Controller\d3webauthnloginTest; +use OxidEsales\Eshop\Application\Controller\Admin\LoginController; +use OxidEsales\Eshop\Application\Model\User; +use OxidEsales\Eshop\Core\Request; +use OxidEsales\Eshop\Core\Session; +use OxidEsales\Eshop\Core\SystemEventHandler; +use OxidEsales\Eshop\Core\Utils; +use OxidEsales\Eshop\Core\UtilsServer; +use OxidEsales\Eshop\Core\UtilsView; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use ReflectionException; class d3webauthnadminloginTest extends d3webauthnloginTest @@ -57,9 +71,64 @@ class d3webauthnadminloginTest extends d3webauthnloginTest * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::render * @dataProvider canRenderDataProvider */ - public function canRender($auth, $userFromLogin, $startRedirect, $redirectController = 'admin_start') + public function canRender($auth, $userFromLogin, $startRedirect, $redirectController) { - parent::canRender($auth, $userFromLogin, $startRedirect, 'admin_start'); + /** @var LoginController|MockObject $loginControllerMock */ + $loginControllerMock = $this->getMockBuilder(LoginController::class) + ->onlyMethods(['d3WebauthnAfterLoginChangeLanguage']) + ->getMock(); + $loginControllerMock->expects($this->once())->method('d3WebauthnAfterLoginChangeLanguage')->willReturn(true); + + /** @var Session|MockObject $sessionMock */ + $sessionMock = $this->getMockBuilder(Session::class) + ->onlyMethods(['hasVariable']) + ->getMock(); + $sessionMock->method('hasVariable')->willReturnMap([ + [WebauthnConf::WEBAUTHN_ADMIN_SESSION_AUTH, $auth], + [WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER, $userFromLogin] + ]); + + /** @var Utils|MockObject $utilsMock */ + $utilsMock = $this->getMockBuilder(Utils::class) + ->onlyMethods(['redirect']) + ->getMock(); + $utilsMock->expects($startRedirect ? $this->once() : $this->never()) + ->method('redirect')->with('index.php?cl='.$redirectController)->willReturn(true); + + /** @var d3webauthnlogin|MockObject $sut */ + $sut = $this->getMockBuilder($this->sutClassName) + ->onlyMethods(['d3GetSession', 'getUtils', 'd3CallMockableParent', + 'generateCredentialRequest', 'addTplParam', 'd3WebauthnGetLoginController']) + ->getMock(); + $sut->method('d3GetSession')->willReturn($sessionMock); + $sut->method('getUtils')->willReturn($utilsMock); + $sut->method('d3CallMockableParent')->willReturn('myTemplate.tpl'); + // "any" because redirect doesn't stop execution + $sut->expects($startRedirect ? $this->any() : $this->atLeastOnce()) + ->method('generateCredentialRequest'); + $sut->expects($startRedirect ? $this->any() : $this->atLeastOnce()) + ->method('addTplParam')->willReturn(true); + $sut->method('d3WebauthnGetLoginController')->willReturn($loginControllerMock); + + $this->assertSame( + 'myTemplate.tpl', + $this->callMethod( + $sut, + 'render' + ) + ); + } + + /** + * @return array + */ + public function canRenderDataProvider(): array + { + return [ + 'has request' => [false, true, false, 'start'], + 'has auth' => [true, true, true, 'admin_start'], + 'missing user' => [false, false, true, 'login'], + ]; } /** @@ -68,9 +137,9 @@ class d3webauthnadminloginTest extends d3webauthnloginTest * @throws ReflectionException * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::generateCredentialRequest */ - public function canGenerateCredentialRequest() + public function canGenerateCredentialRequest($userSessionVarName = WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER) { - parent::canGenerateCredentialRequest(); + parent::canGenerateCredentialRequest($userSessionVarName); } /** @@ -79,9 +148,9 @@ class d3webauthnadminloginTest extends d3webauthnloginTest * @throws ReflectionException * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::generateCredentialRequest */ - public function generateCredentialRequestFailed($redirectClass = 'login') + public function generateCredentialRequestFailed($redirectClass = 'login', $userVarName = WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTUSER) { - parent::generateCredentialRequestFailed($redirectClass); + parent::generateCredentialRequestFailed($redirectClass, $userVarName); } /** @@ -99,11 +168,11 @@ class d3webauthnadminloginTest extends d3webauthnloginTest * @test * @return void * @throws ReflectionException - * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::getPreviousClass + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3GetPreviousClass */ - public function canGetPreviousClass() + public function canGetPreviousClass($sessionVarName = WebauthnConf::WEBAUTHN_ADMIN_SESSION_CURRENTCLASS) { - parent::canGetPreviousClass(); + parent::canGetPreviousClass($sessionVarName); } /** @@ -135,4 +204,305 @@ class d3webauthnadminloginTest extends d3webauthnloginTest public function canGetBreadCrumb() { } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3WebauthnGetLoginController + */ + public function canGetLoginController() + { + $sut = oxNew(d3webauthnadminlogin::class); + + $this->assertInstanceOf( + LoginController::class, + $this->callMethod( + $sut, + 'd3WebauthnGetLoginController' + ) + ); + } + + /** + * @test + * @param $error + * @param $credential + * @param $canAssert + * @param $return + * @param $showErrorMsg + * @return void + * @throws ReflectionException + * @dataProvider canAssertAuthnDataProvider + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3AssertAuthn + */ + public function canAssertAuthn($error, $credential, $canAssert, $return, $showErrorMsg) + { + /** @var Request|MockObject $requestMock */ + $requestMock = $this->getMockBuilder(Request::class) + ->onlyMethods(['getRequestEscapedParameter']) + ->getMock(); + $requestMock->method('getRequestEscapedParameter')->willReturnCallback( + function () use ($error, $credential) { + $args = func_get_args(); + if ($args[0] === 'error') + return $error; + elseif ($args[0] === 'credential') + return $credential; + return null; + } + ); + + /** @var Webauthn|MockObject $webauthnMock */ + $webauthnMock = $this->getMockBuilder(Webauthn::class) + ->onlyMethods(['assertAuthn']) + ->getMock(); + if ($canAssert) { + $webauthnMock->expects($error || !$credential ? $this->never() : $this->once())->method('assertAuthn'); + } else { + $webauthnMock->expects($error || !$credential ? $this->never() : $this->once())->method('assertAuthn') + ->willThrowException(oxNew(WebauthnException::class)); + } + + /** @var Session|MockObject $sessionMock */ + $sessionMock = $this->getMockBuilder(Session::class) + ->onlyMethods(['initNewSession', 'setVariable']) + ->getMock(); + $sessionMock->expects($canAssert ? $this->once() : $this->never())->method('initNewSession'); + $sessionMock->expects($canAssert ? $this->atLeast(2) : $this->never())->method('setVariable'); + + /** @var SystemEventHandler|MockObject $eventHandlerMock */ + $eventHandlerMock = $this->getMockBuilder(SystemEventHandler::class) + ->onlyMethods(['onAdminLogin']) + ->getMock(); + $eventHandlerMock->expects($canAssert ? $this->once() : $this->never())->method('onAdminLogin'); + + /** @var LoginController|MockObject $loginControllerMock */ + $loginControllerMock = $this->getMockBuilder(LoginController::class) + ->onlyMethods(['d3webauthnAfterLogin']) + ->getMock(); + $loginControllerMock->expects($canAssert ? $this->once() : $this->never())->method('d3webauthnAfterLogin'); + + /** @var UtilsView|MockObject $utilsViewMock */ + $utilsViewMock = $this->getMockBuilder(UtilsView::class) + ->onlyMethods(['addErrorToDisplay']) + ->getMock(); + $utilsViewMock->expects($showErrorMsg ? $this->once() : $this->never())->method('addErrorToDisplay'); + + /** @var UtilsServer|MockObject $utilsServerMock */ + $utilsServerMock = $this->getMockBuilder(UtilsServer::class) + ->onlyMethods(['getOxCookie']) + ->getMock(); + $utilsServerMock->method('getOxCookie')->willReturn('cookie'); + + /** @var LoggerInterface|MockObject $loggerMock */ + $loggerMock = $this->getMockForAbstractClass(LoggerInterface::class, [], '', true, true, true, ['error', 'debug']); + $loggerMock->method('error')->willReturn(true); + $loggerMock->method('debug')->willReturn(true); + + /** @var d3webauthnadminlogin|MockObject $sut */ + $sut = $this->getMockBuilder(d3webauthnadminlogin::class) + ->onlyMethods(['d3WebAuthnGetRequest', 'd3GetWebauthnObject', 'd3GetSession', 'd3WebauthnGetEventHandler', + 'd3WebauthnGetLoginController', 'd3GetUtilsViewObject', 'd3GetLoggerObject', 'd3WebauthnGetUtilsServer']) + ->getMock(); + $sut->method('d3WebAuthnGetRequest')->willReturn($requestMock); + $sut->method('d3GetWebauthnObject')->willReturn($webauthnMock); + $sut->method('d3GetSession')->willReturn($sessionMock); + $sut->method('d3WebauthnGetEventHandler')->willReturn($eventHandlerMock); + $sut->method('d3WebauthnGetLoginController')->willReturn($loginControllerMock); + $sut->method('d3GetUtilsViewObject')->willReturn($utilsViewMock); + $sut->method('d3GetLoggerObject')->willReturn($loggerMock); + $sut->method('d3WebauthnGetUtilsServer')->willReturn($utilsServerMock); + + $this->assertSame( + $return, + $this->callMethod( + $sut, + 'd3AssertAuthn' + ) + ); + } + + /** + * @return array + */ + public function canAssertAuthnDataProvider(): array + { + return [ + 'has error' => ['errorFixture', null, false, 'login', true], + 'missing credential' => [null, null, false, 'login', true], + 'assertion failed' => [null, 'credential', false, 'login', true], + 'assertion succ' => [null, 'credential', true, 'admin_start', false], + ]; + } + + /** + * @test + * @param $return + * @param $showErrorMsg + * @param $cookie + * @return void + * @throws ReflectionException + * @dataProvider canAssertAuthnCookieSubshopDataProvider + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3AssertAuthn + */ + public function canAssertAuthnCookieSubshop($return, $showErrorMsg, $cookie, $rights) + { + /** @var Request|MockObject $requestMock */ + $requestMock = $this->getMockBuilder(Request::class) + ->onlyMethods(['getRequestEscapedParameter']) + ->getMock(); + $requestMock->method('getRequestEscapedParameter')->willReturnCallback( + function () { + $args = func_get_args(); + if ($args[0] === 'error') + return null; + elseif ($args[0] === 'credential') + return 'credential'; + return null; + } + ); + + /** @var Webauthn|MockObject $webauthnMock */ + $webauthnMock = $this->getMockBuilder(Webauthn::class) + ->onlyMethods(['assertAuthn']) + ->getMock(); + $webauthnMock->expects($this->once())->method('assertAuthn'); + + /** @var Session|MockObject $sessionMock */ + $sessionMock = $this->getMockBuilder(Session::class) + ->onlyMethods(['initNewSession', 'setVariable']) + ->getMock(); + $sessionMock->expects($this->once())->method('initNewSession'); + $sessionMock->expects($this->atLeast(is_int($rights) ? 4 : 2))->method('setVariable'); + + /** @var SystemEventHandler|MockObject $eventHandlerMock */ + $eventHandlerMock = $this->getMockBuilder(SystemEventHandler::class) + ->onlyMethods(['onAdminLogin']) + ->getMock(); + $eventHandlerMock->expects($cookie && $rights != 'user' ? $this->once() : $this->never())->method('onAdminLogin'); + + /** @var LoginController|MockObject $loginControllerMock */ + $loginControllerMock = $this->getMockBuilder(LoginController::class) + ->onlyMethods(['d3webauthnAfterLogin']) + ->getMock(); + $loginControllerMock->expects($cookie && $rights != 'user' ? $this->once() : $this->never())->method('d3webauthnAfterLogin'); + + /** @var UtilsView|MockObject $utilsViewMock */ + $utilsViewMock = $this->getMockBuilder(UtilsView::class) + ->onlyMethods(['addErrorToDisplay']) + ->getMock(); + $utilsViewMock->expects($showErrorMsg ? $this->once() : $this->never())->method('addErrorToDisplay'); + + /** @var UtilsServer|MockObject $utilsServerMock */ + $utilsServerMock = $this->getMockBuilder(UtilsServer::class) + ->onlyMethods(['getOxCookie']) + ->getMock(); + $utilsServerMock->method('getOxCookie')->willReturn($cookie); + + /** @var LoggerInterface|MockObject $loggerMock */ + $loggerMock = $this->getMockForAbstractClass(LoggerInterface::class, [], '', true, true, true, ['error', 'debug']); + $loggerMock->method('error')->willReturn(true); + $loggerMock->method('debug')->willReturn(true); + + /** @var User|MockObject $userMock */ + $userMock = $this->getMockBuilder(User::class) + ->onlyMethods(['getFieldData']) + ->getMock(); + $userMock->method('getFieldData')->willReturn($rights); + + /** @var d3webauthnadminlogin|MockObject $sut */ + $sut = $this->getMockBuilder(d3webauthnadminlogin::class) + ->onlyMethods(['d3WebAuthnGetRequest', 'd3GetWebauthnObject', 'd3GetSession', 'd3WebauthnGetEventHandler', + 'd3WebauthnGetLoginController', 'd3GetUtilsViewObject', 'd3GetLoggerObject', 'd3WebauthnGetUtilsServer', + 'd3GetUserObject']) + ->getMock(); + $sut->method('d3WebAuthnGetRequest')->willReturn($requestMock); + $sut->method('d3GetWebauthnObject')->willReturn($webauthnMock); + $sut->method('d3GetSession')->willReturn($sessionMock); + $sut->method('d3WebauthnGetEventHandler')->willReturn($eventHandlerMock); + $sut->method('d3WebauthnGetLoginController')->willReturn($loginControllerMock); + $sut->method('d3GetUtilsViewObject')->willReturn($utilsViewMock); + $sut->method('d3GetLoggerObject')->willReturn($loggerMock); + $sut->method('d3WebauthnGetUtilsServer')->willReturn($utilsServerMock); + $sut->method('d3GetUserObject')->willReturn($userMock); + + $this->assertSame( + $return, + $this->callMethod( + $sut, + 'd3AssertAuthn' + ) + ); + } + + /** + * @return array + */ + public function canAssertAuthnCookieSubshopDataProvider(): array + { + return [ + 'missing cookie' => ['login', true, null, 'user'], + 'no admin user' => ['login', true, 'cookie', 'user'], + 'assertion succ malladmin' => ['admin_start', false, 'cookie', 'malladmin'], + 'assertion succ shop1' => ['admin_start', false, 'cookie', 1], + ]; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3WebauthnGetEventHandler + */ + public function canGetSystemEventHandler() + { + $sut = oxNew(d3webauthnadminlogin::class); + + $this->assertInstanceOf( + SystemEventHandler::class, + $this->callMethod( + $sut, + 'd3WebauthnGetEventHandler' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3WebAuthnGetRequest + */ + public function canGetRequest() + { + $sut = oxNew(d3webauthnadminlogin::class); + + $this->assertInstanceOf( + Request::class, + $this->callMethod( + $sut, + 'd3WebAuthnGetRequest' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\Webauthn\Application\Controller\Admin\d3webauthnadminlogin::d3WebauthnGetUtilsServer + */ + public function canGetUtilsServer() + { + $sut = oxNew(d3webauthnadminlogin::class); + + $this->assertInstanceOf( + UtilsServer::class, + $this->callMethod( + $sut, + 'd3WebauthnGetUtilsServer' + ) + ); + } } \ No newline at end of file diff --git a/src/tests/unit/Application/Controller/d3webauthnloginTest.php b/src/tests/unit/Application/Controller/d3webauthnloginTest.php index 7bd1ade..d06343e 100644 --- a/src/tests/unit/Application/Controller/d3webauthnloginTest.php +++ b/src/tests/unit/Application/Controller/d3webauthnloginTest.php @@ -23,12 +23,13 @@ use D3\Webauthn\Application\Model\WebauthnConf; use OxidEsales\Eshop\Core\Routing\ControllerClassNameResolver; use OxidEsales\Eshop\Core\Session; use OxidEsales\Eshop\Core\Utils; +use OxidEsales\TestingLibrary\UnitTestCase; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use ReflectionException; -class d3webauthnloginTest extends TestCase +class d3webauthnloginTest extends UnitTestCase { use CanAccessRestricted; @@ -80,7 +81,7 @@ class d3webauthnloginTest extends TestCase * @covers \D3\Webauthn\Application\Controller\d3webauthnlogin::render * @dataProvider canRenderDataProvider */ - public function canRender($auth, $userFromLogin, $startRedirect, $redirectController = 'start') + public function canRender($auth, $userFromLogin, $startRedirect, $redirectController) { /** @var Session|MockObject $sessionMock */ $sessionMock = $this->getMockBuilder(Session::class) @@ -126,9 +127,9 @@ class d3webauthnloginTest extends TestCase public function canRenderDataProvider(): array { return [ - 'has request' => [false, true, false], - 'has auth' => [true, true, true], - 'missing user' => [false, false, true], + 'has request' => [false, true, false, 'start'], + 'has auth' => [true, true, true, 'start'], + 'missing user' => [false, false, true, 'start'], ]; } @@ -138,7 +139,7 @@ class d3webauthnloginTest extends TestCase * @throws ReflectionException * @covers \D3\Webauthn\Application\Controller\d3webauthnlogin::generateCredentialRequest */ - public function canGenerateCredentialRequest() + public function canGenerateCredentialRequest($userSessionVarName = WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER) { $currUserFixture = 'currentUserFixture'; @@ -152,7 +153,7 @@ class d3webauthnloginTest extends TestCase ->onlyMethods(['getVariable']) ->getMock(); $sessionMock->method('getVariable')->willReturnMap([ - [WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $currUserFixture] + [$userSessionVarName, $currUserFixture] ]); /** @var Webauthn|MockObject $webAuthnMock */ @@ -184,7 +185,7 @@ class d3webauthnloginTest extends TestCase * @throws ReflectionException * @covers \D3\Webauthn\Application\Controller\d3webauthnlogin::generateCredentialRequest */ - public function generateCredentialRequestFailed($redirectClass = 'start') + public function generateCredentialRequestFailed($redirectClass = 'start', $userVarName = WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER) { $currUserFixture = 'currentUserFixture'; @@ -198,7 +199,7 @@ class d3webauthnloginTest extends TestCase ->onlyMethods(['getVariable', 'setVariable']) ->getMock(); $sessionMock->method('getVariable')->willReturnMap([ - [WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $currUserFixture] + [$userVarName, $currUserFixture] ]); $sessionMock->expects($this->once())->method('setVariable')->with(WebauthnConf::GLOBAL_SWITCH) ->willReturn(true); @@ -258,9 +259,9 @@ class d3webauthnloginTest extends TestCase * @test * @return void * @throws ReflectionException - * @covers \D3\Webauthn\Application\Controller\d3webauthnlogin::getPreviousClass + * @covers \D3\Webauthn\Application\Controller\d3webauthnlogin::d3GetPreviousClass */ - public function canGetPreviousClass() + public function canGetPreviousClass($sessionVarName = WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS) { $currClassFixture = 'currentClassFixture'; @@ -269,7 +270,7 @@ class d3webauthnloginTest extends TestCase ->onlyMethods(['getVariable']) ->getMock(); $sessionMock->method('getVariable')->willReturnMap([ - [WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, $currClassFixture] + [$sessionVarName, $currClassFixture] ]); /** @var d3webauthnlogin|MockObject $sut */ @@ -282,7 +283,7 @@ class d3webauthnloginTest extends TestCase $currClassFixture, $this->callMethod( $sut, - 'getPreviousClass' + 'd3GetPreviousClass' ) ); } @@ -298,19 +299,11 @@ class d3webauthnloginTest extends TestCase */ public function canPreviousClassIsOrderStep($currClass, $isOrderStep) { - /** @var Session|MockObject $sessionMock */ - $sessionMock = $this->getMockBuilder(Session::class) - ->onlyMethods(['getVariable']) - ->getMock(); - $sessionMock->method('getVariable')->willReturnMap([ - [WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, $currClass] - ]); - /** @var d3webauthnlogin|MockObject $sut */ $sut = $this->getMockBuilder($this->sutClassName) - ->onlyMethods(['d3GetSession']) + ->onlyMethods(['d3GetPreviousClass']) ->getMock(); - $sut->method('d3GetSession')->willReturn($sessionMock); + $sut->method('d3GetPreviousClass')->willReturn($currClass); $this->assertSame( $isOrderStep,