Compare commits
2 Commits
master
...
dev_2.x_we
Author | SHA1 | Date | |
---|---|---|---|
b725333e86 | |||
911ff99c83 |
14
CHANGELOG.md
14
CHANGELOG.md
@ -4,19 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased](https://git.d3data.de/D3Public/oxtotp/compare/2.1.1.0...rel_2.x)
|
||||
|
||||
## [2.1.1.0](https://git.d3data.de/D3Public/oxtotp/compare/2.1.0.0...2.1.1.0) - 2023-09-07
|
||||
- add product logo
|
||||
- installable in OXID 6.5.2 + 6.5.3
|
||||
|
||||
## [2.1.0.0](https://git.d3data.de/D3Public/oxtotp/compare/2.0.0.1...2.1.0.0) - 2023-02-18
|
||||
- add compatibility to D3 Webauthn plugin
|
||||
- installable in OXID 6.5.1
|
||||
|
||||
## [2.0.0.1](https://git.d3data.de/D3Public/oxtotp/compare/2.0.0.0...2.0.0.1) - 2022-11-09
|
||||
### Fixed
|
||||
- Further protection of the login
|
||||
## [Unreleased](https://git.d3data.de/D3Public/oxtotp/compare/2.0.0.0...rel_2.x)
|
||||
|
||||
## [2.0.0.0](https://git.d3data.de/D3Public/oxtotp/compare/1.1.0.0...2.0.0.0) - 2022-09-30
|
||||
### Added
|
||||
|
14
README.en.md
14
README.en.md
@ -1,9 +1,9 @@
|
||||
[![deutsche Version](https://logos.oxidmodule.com/de2_xs.svg)](README.md)
|
||||
[![english version](https://logos.oxidmodule.com/en2_xs.svg)](README.en.md)
|
||||
|
||||
# 2-factor authentication (one-time password) for OXID eShop
|
||||
# 2-factor authentication (TOTP) for OXID eShop
|
||||
|
||||
This module provides a 2-factor authentication (time-dependent one-time password / TOTP) for login in front- and backend in addition to user name and password.
|
||||
This module provides a 2-factor authentication (time-dependent one-time password) for login in front- and backend in addition to user name and password.
|
||||
|
||||
## Features
|
||||
|
||||
@ -20,8 +20,8 @@ This module provides a 2-factor authentication (time-dependent one-time password
|
||||
![Setup Frontend](assets/setup_frontend.jpg "Setup Frontend")
|
||||
|
||||
### Login
|
||||
![Login Backend](assets/login_backend.png "Login Backend")
|
||||
![Login Frontend](assets/login_frontend.png "Login Frontend")
|
||||
![Login Backend](assets/login_backend.jpg "Login Backend")
|
||||
![Login Frontend](assets/login_frontend.jpg "Login Frontend")
|
||||
|
||||
## System requirements
|
||||
|
||||
@ -33,14 +33,10 @@ This package requires an OXID eShop installed with Composer in one of the follow
|
||||
|
||||
and its requirements.
|
||||
|
||||
The Flow and Wave themes are supported by default. Other themes may require customisation.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Open a command line interface and navigate to the shop root directory (parent of source and vendor). Execute the following command. Adapt the paths to your environment.
|
||||
|
||||
```
|
||||
composer require d3/oxid-twofactor-onetimepassword
|
||||
composer require d3/oxtotp
|
||||
```
|
||||
|
||||
Activate the module in the admin area of the shop in "Extensions -> Modules".
|
||||
|
14
README.md
14
README.md
@ -1,9 +1,9 @@
|
||||
[![deutsche Version](https://logos.oxidmodule.com/de2_xs.svg)](README.md)
|
||||
[![english version](https://logos.oxidmodule.com/en2_xs.svg)](README.en.md)
|
||||
|
||||
# 2-Faktor-Authentisierung (Einmalpasswort) fĂĽr OXID eShop
|
||||
# 2-Faktor-Authentisierung (TOTP) fĂĽr OXID eShop
|
||||
|
||||
Dieses Modul stellt eine 2-Faktor-Authentisierung (zeitabhängiges Einmalpasswort / TOTP) zum Login in Front- und Backend zusätzlich zu Benutzername und Passwort zur Verfügung.
|
||||
Dieses Modul stellt eine 2-Faktor-Authentisierung (zeitabhängiges Einmalpasswort) zum Login in Front- und Backend zusätzlich zu Benutzername und Passwort zur Verfügung.
|
||||
|
||||
## Features
|
||||
|
||||
@ -20,8 +20,8 @@ Dieses Modul stellt eine 2-Faktor-Authentisierung (zeitabhängiges Einmalpasswor
|
||||
![Einrichtung Frontend](assets/setup_frontend.jpg "Einrichtung Frontend")
|
||||
|
||||
### Login
|
||||
![Login Backend](assets/login_backend.png "Login Backend")
|
||||
![Login Frontend](assets/login_frontend.png "Login Frontend")
|
||||
![Login Backend](assets/login_backend.jpg "Login Backend")
|
||||
![Login Frontend](assets/login_frontend.jpg "Login Frontend")
|
||||
|
||||
## Systemanforderungen
|
||||
|
||||
@ -33,14 +33,10 @@ Dieses Paket erfordert einen mit Composer installierten OXID eShop in einer der
|
||||
|
||||
und dessen Anforderungen.
|
||||
|
||||
Im Standard wird das Flow- und Wave-Theme unterstützt. Andere Themes können Anpassungen erfordern.
|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Ă–ffnen Sie eine Kommandozeile und navigieren Sie zum Stammverzeichnis des Shops (Elternverzeichnis von source und vendor). FĂĽhren Sie den folgenden Befehl aus. Passen Sie die Pfadangaben an Ihre Installationsumgebung an.
|
||||
|
||||
```
|
||||
composer require d3/oxid-twofactor-onetimepassword
|
||||
composer require d3/oxtotp
|
||||
```
|
||||
|
||||
Aktivieren Sie das Modul im Shopadmin unter "Erweiterungen -> Module".
|
||||
|
BIN
assets/login_backend.jpg
Normal file
BIN
assets/login_backend.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Before Width: | Height: | Size: 31 KiB |
BIN
assets/login_frontend.jpg
Normal file
BIN
assets/login_frontend.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
Before Width: | Height: | Size: 31 KiB |
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "d3/oxid-twofactor-onetimepassword",
|
||||
"name": "d3/oxtotp",
|
||||
"description": "Two-factor authentication via time-based one-time password for OXID eSales shop",
|
||||
"type": "oxideshop-module",
|
||||
"keywords": [
|
||||
@ -7,13 +7,7 @@
|
||||
"modules",
|
||||
"eShop",
|
||||
"d3",
|
||||
"2FA",
|
||||
"two factor",
|
||||
"second factor",
|
||||
"TOTP",
|
||||
"OTP",
|
||||
"one-time password",
|
||||
"authenticator"
|
||||
"2FA"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
@ -46,28 +40,24 @@
|
||||
"php": ">=7.2",
|
||||
"ext-xmlwriter": "*",
|
||||
"ext-openssl": "*",
|
||||
"oxid-esales/oxideshop-ce": "6.8.0 - 6.14",
|
||||
"oxid-esales/oxideshop-ce": "6.8.0 - 6.12",
|
||||
"spomky-labs/otphp": "^10.0 || ^11.0",
|
||||
"bacon/bacon-qr-code": "^2.0",
|
||||
"laminas/laminas-math": "^3.2",
|
||||
"d3/testingtools": "^1.0"
|
||||
"web-auth/webauthn-lib": "^3.3",
|
||||
"nyholm/psr7": "^1.5.1",
|
||||
"nyholm/psr7-server": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.19",
|
||||
"phpstan/phpstan": "^1.8"
|
||||
},
|
||||
"suggest": {
|
||||
"d3/modcfg": "Provides automatic installation routines"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"D3\\Totp\\": "../../../source/modules/d3/totp"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"totp_phpstan": "./vendor/bin/phpstan -c./vendor/d3/oxtotp/phpstan.neon"
|
||||
},
|
||||
"suggest": {
|
||||
"d3/oxid-twofactor-passwordless": "Passwordless login with FIDO2 hardware token."
|
||||
},
|
||||
"replace": {
|
||||
"d3/oxtotp": "*"
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,4 @@ parameters:
|
||||
paths:
|
||||
- src
|
||||
level: 5
|
||||
phpVersion: 70300
|
||||
ignoreErrors:
|
||||
- '#Call to method getFieldData\(\) on an unknown class oxShop.#'
|
||||
- '#Return type \(array\) of method D3\\Totp\\Application\\Controller\\d3totplogin::getBreadCrumb\(\) should be compatible with return type \(null\) of method OxidEsales\\EshopCommunity\\Application\\Controller\\FrontendController::getBreadCrumb\(\)#'
|
||||
- '#Parameter \#\d+ \$value of method OxidEsales\\EshopCommunity\\Core\\Config::setConfigParam\(\) expects string, (true|false) given.#'
|
||||
parallel:
|
||||
processTimeout: 900.0
|
||||
phpVersion: 70300
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Application\Controller\Admin;
|
||||
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
|
||||
@ -14,7 +13,7 @@ class d3force_2fa extends d3user_totp
|
||||
{
|
||||
$this->addTplParam('force2FA', true);
|
||||
|
||||
$userID = $this->d3TotpGetSessionObject()->getVariable(d3totp_conf::OXID_ADMIN_AUTH);
|
||||
$userID = $this->d3GetSessionObject()->getVariable("auth");
|
||||
$this->_sEditObjectId = $userID;
|
||||
|
||||
return parent::render();
|
||||
@ -23,7 +22,7 @@ class d3force_2fa extends d3user_totp
|
||||
|
||||
protected function _authorize()
|
||||
{
|
||||
$userID = $this->d3TotpGetSessionObject()->getVariable(d3totp_conf::OXID_ADMIN_AUTH);
|
||||
$userID = $this->d3GetSessionObject()->getVariable("auth");
|
||||
|
||||
return ($this->d3IsAdminForce2FA() && !empty($userID));
|
||||
}
|
||||
@ -31,7 +30,7 @@ class d3force_2fa extends d3user_totp
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
private function d3TotpGetSessionObject()
|
||||
private function d3GetSessionObject()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
@ -1,234 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Application\Controller\Admin;
|
||||
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\AdminController;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class d3totpadminlogin extends AdminController
|
||||
{
|
||||
protected $_sThisTemplate = 'd3totpadminlogin.tpl';
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function _authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3totp|mixed
|
||||
*/
|
||||
public function d3TotpGetTotpObject()
|
||||
{
|
||||
return oxNew(d3totp::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
protected function isTotpIsNotRequired(): bool
|
||||
{
|
||||
/** @var d3_totp_user $user */
|
||||
$user = $this->d3TotpGetUserObject();
|
||||
$userId = $user->d3TotpGetCurrentUser();
|
||||
|
||||
$totp = $this->d3TotpGetTotpObject();
|
||||
$totp->loadByUserId($userId);
|
||||
|
||||
return $this->d3TotpGetSession()->hasVariable(d3totp_conf::SESSION_ADMIN_AUTH) ||
|
||||
!$totp->isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function isTotpLoginNotPossible(): bool
|
||||
{
|
||||
$user = $this->d3TotpGetUserObject();
|
||||
return !$user->d3TotpGetCurrentUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function render(): string
|
||||
{
|
||||
if ($this->isTotpLoginNotPossible()) {
|
||||
$this->d3TotpGetUtils()->redirect('index.php?cl=login', false);
|
||||
} elseif ($this->isTotpIsNotRequired()) {
|
||||
$this->d3TotpGetUtils()->redirect('index.php?cl=admin_start', false);
|
||||
}
|
||||
|
||||
$this->addTplParam('selectedProfile', Registry::getRequest()->getRequestEscapedParameter('profile'));
|
||||
$this->addTplParam('selectedChLanguage', Registry::getRequest()->getRequestEscapedParameter('chlanguage'));
|
||||
|
||||
/** @var d3_totp_LoginController $loginController */
|
||||
$loginController = $this->d3GetLoginController();
|
||||
$loginController->d3totpAfterLoginSetLanguage();
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3backupcodelist
|
||||
*/
|
||||
public function d3GetBackupCodeListObject(): d3backupcodelist
|
||||
{
|
||||
return oxNew(d3backupcodelist::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|void
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function getBackupCodeCountMessage()
|
||||
{
|
||||
/** @var d3_totp_user $user */
|
||||
$user = oxNew(User::class);
|
||||
$userId = $user->d3TotpGetCurrentUser();
|
||||
|
||||
$oBackupCodeList = $this->d3GetBackupCodeListObject();
|
||||
$iCount = $oBackupCodeList->getAvailableCodeCount($userId);
|
||||
|
||||
if ($iCount < 4) {
|
||||
return sprintf(
|
||||
Registry::getLang()->translateString('D3_TOTP_AVAILBACKUPCODECOUNT'),
|
||||
$iCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function d3CancelLogin(): string
|
||||
{
|
||||
/** @var d3_totp_user $oUser */
|
||||
$oUser = $this->d3TotpGetUserObject();
|
||||
$oUser->logout();
|
||||
return "login";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function d3TotpGetUserObject(): User
|
||||
{
|
||||
return oxNew(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|void
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function checklogin()
|
||||
{
|
||||
$session = $this->d3TotpGetSession();
|
||||
/** @var d3_totp_user $user */
|
||||
$user = oxNew(User::class);
|
||||
$userId = $user->d3TotpGetCurrentUser();
|
||||
|
||||
try {
|
||||
$sTotp = implode('', Registry::getRequest()->getRequestEscapedParameter('d3totp') ?: []);
|
||||
|
||||
$totp = $this->d3TotpGetTotpObject();
|
||||
$totp->loadByUserId($userId);
|
||||
|
||||
$this->d3TotpHasValidTotp($sTotp, $totp);
|
||||
|
||||
$selectedProfile = Registry::getRequest()->getRequestEscapedParameter('profile');
|
||||
$selectedLanguage = Registry::getRequest()->getRequestEscapedParameter('chlanguage');
|
||||
|
||||
$session->initNewSession();
|
||||
$session->setVariable(d3totp_conf::SESSION_ADMIN_PROFILE, $selectedProfile);
|
||||
$session->setVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE, $selectedLanguage);
|
||||
$session->setVariable(d3totp_conf::OXID_ADMIN_AUTH, $userId);
|
||||
$session->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, $userId);
|
||||
$session->deleteVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER);
|
||||
|
||||
/** @var d3_totp_LoginController $loginController */
|
||||
$loginController = $this->d3GetLoginController();
|
||||
$loginController->d3totpAfterLogin();
|
||||
|
||||
return "admin_start";
|
||||
} catch (d3totp_wrongOtpException $e) {
|
||||
Registry::getUtilsView()->addErrorToDisplay($e);
|
||||
$this->getLogger()->error($e->getMessage(), ['UserId' => $userId]);
|
||||
$this->getLogger()->debug($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sTotp
|
||||
* @param d3totp $totp
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws d3totp_wrongOtpException
|
||||
*/
|
||||
public function d3TotpHasValidTotp(string $sTotp = null, d3totp $totp): bool
|
||||
{
|
||||
return $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_AUTH)
|
||||
|| $totp->verify($sTotp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Utils
|
||||
*/
|
||||
public function d3TotpGetUtils(): Utils
|
||||
{
|
||||
return Registry::getUtils();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSession(): Session
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
public function getLogger(): LoggerInterface
|
||||
{
|
||||
return Registry::getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LoginController
|
||||
*/
|
||||
public function d3GetLoginController(): LoginController
|
||||
{
|
||||
return oxNew(LoginController::class);
|
||||
}
|
||||
}
|
@ -35,6 +35,12 @@ class d3_account_totp extends AccountController
|
||||
{
|
||||
$sRet = parent::render();
|
||||
|
||||
/** @var User|null $oUser */
|
||||
$oUser = $this->getUser();
|
||||
if (false === $oUser instanceof User) {
|
||||
return $this->_sThisTemplate = $this->_sThisLoginTemplate;
|
||||
}
|
||||
|
||||
$this->addTplParam('user', $this->getUser());
|
||||
|
||||
return $sRet;
|
||||
@ -108,7 +114,7 @@ class d3_account_totp extends AccountController
|
||||
$oTotp->save();
|
||||
$oTotpBackupCodes->save();
|
||||
} catch (Exception $oExcp) {
|
||||
Registry::get(UtilsView::class)->addErrorToDisplay($oExcp->getMessage());
|
||||
Registry::get(UtilsView::class)->addErrorToDisplay($oExcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ declare(strict_types=1);
|
||||
namespace D3\Totp\Application\Controller;
|
||||
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
@ -28,11 +28,18 @@ class d3totplogin extends FrontendController
|
||||
|
||||
public function render()
|
||||
{
|
||||
if (!Registry::getSession()->hasVariable(d3totp_conf::SESSION_CURRENTUSER)) {
|
||||
$this->getUtils()->redirect('index.php?cl=start', false);
|
||||
if (Registry::getSession()->hasVariable(d3totp::TOTP_SESSION_VARNAME) ||
|
||||
false == Registry::getSession()->hasVariable(d3totp::TOTP_SESSION_CURRENTUSER)
|
||||
) {
|
||||
$this->getUtils()->redirect('index.php?cl=start');
|
||||
if (false == defined('OXID_PHP_UNIT')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
exit;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
$this->addTplParam('navFormParams', Registry::getSession()->getVariable(d3totp_conf::SESSION_NAVFORMPARAMS));
|
||||
$this->addTplParam('navFormParams', Registry::getSession()->getVariable(d3totp::TOTP_SESSION_NAVFORMPARAMS));
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
@ -52,8 +59,7 @@ class d3totplogin extends FrontendController
|
||||
public function getBackupCodeCountMessage()
|
||||
{
|
||||
$oBackupCodeList = $this->getBackupCodeListObject();
|
||||
$userId = Registry::getSession()->getVariable(d3totp_conf::SESSION_CURRENTUSER);
|
||||
$iCount = $oBackupCodeList->getAvailableCodeCount($userId);
|
||||
$iCount = $oBackupCodeList->getAvailableCodeCount(Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTUSER));
|
||||
|
||||
if ($iCount < 4) {
|
||||
return sprintf(
|
||||
@ -73,12 +79,12 @@ class d3totplogin extends FrontendController
|
||||
|
||||
public function getPreviousClass()
|
||||
{
|
||||
return Registry::getSession()->getVariable(d3totp_conf::SESSION_CURRENTCLASS);
|
||||
return Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTCLASS);
|
||||
}
|
||||
|
||||
public function previousClassIsOrderStep(): bool
|
||||
{
|
||||
$sClassKey = Registry::getSession()->getVariable(d3totp_conf::SESSION_CURRENTCLASS);
|
||||
$sClassKey = Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTCLASS);
|
||||
$resolvedClass = Registry::getControllerClassNameResolver()->getClassNameById($sClassKey);
|
||||
$resolvedClass = $resolvedClass ?: 'start';
|
||||
|
||||
@ -100,7 +106,7 @@ class d3totplogin extends FrontendController
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBreadCrumb()
|
||||
public function getBreadCrumb(): array
|
||||
{
|
||||
$aPaths = [];
|
||||
$aPath = [];
|
||||
|
117
src/Application/Model/Webauthn/PublicKeyCredentials.php
Normal file
117
src/Application/Model/Webauthn/PublicKeyCredentials.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace D3\Totp\Application\Model\Webauthn;
|
||||
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use OxidEsales\Eshop\Core\Model\BaseModel;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
|
||||
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
|
||||
use Webauthn\PublicKeyCredentialSource;
|
||||
use Webauthn\PublicKeyCredentialSourceRepository;
|
||||
use Webauthn\PublicKeyCredentialUserEntity;
|
||||
|
||||
class PublicKeyCredentials extends BaseModel implements PublicKeyCredentialSourceRepository
|
||||
{
|
||||
protected $_sCoreTable = 'd3wa_usercredentials';
|
||||
|
||||
public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource
|
||||
{
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('credential')
|
||||
->from($this->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'credid_hex',
|
||||
$qb->createNamedParameter(bin2hex($publicKeyCredentialId))
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
)
|
||||
)
|
||||
);
|
||||
$credential = $qb->execute()->fetchOne();
|
||||
|
||||
if (!strlen($credential)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$credential = unserialize(hex2bin($credential));
|
||||
|
||||
return $credential instanceof PublicKeyCredentialSource ? $credential : null;
|
||||
}
|
||||
|
||||
public function getIdByCredentialId(string $publicKeyCredentialId): ?string
|
||||
{
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('oxid')
|
||||
->from($this->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'credid_hex',
|
||||
$qb->createNamedParameter(bin2hex($publicKeyCredentialId))
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
)
|
||||
)
|
||||
);
|
||||
$oxid = $qb->execute()->fetchOne();
|
||||
|
||||
return strlen($oxid) ? $oxid : null;
|
||||
}
|
||||
|
||||
public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array
|
||||
{
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('credential')
|
||||
->from($this->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'oxuserid',
|
||||
$qb->createNamedParameter($publicKeyCredentialUserEntity->getId())
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// generate decoded credentials list
|
||||
return array_map(function (array $fields) {
|
||||
return unserialize(hex2bin($fields['credential']));
|
||||
}, $qb->execute()->fetchAllAssociative());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PublicKeyCredentialSource $publicKeyCredentialSource
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void
|
||||
{
|
||||
// will saved on every successfully assertion, set id to prevent duplicated database entries
|
||||
$id = $this->getIdByCredentialId($publicKeyCredentialSource->getPublicKeyCredentialId());
|
||||
$this->setId($id);
|
||||
|
||||
$this->assign([
|
||||
'oxshopid' => Registry::getConfig()->getShopId(),
|
||||
'oxuserid' => $publicKeyCredentialSource->getUserHandle(),
|
||||
'credid_bin' => $publicKeyCredentialSource->getPublicKeyCredentialId(),
|
||||
'credid_hex' => bin2hex($publicKeyCredentialSource->getPublicKeyCredentialId()),
|
||||
'pubkey_bin' => $publicKeyCredentialSource->getCredentialPublicKey(),
|
||||
'pubkey_hex' => bin2hex($publicKeyCredentialSource->getCredentialPublicKey()),
|
||||
'credential' => bin2hex(serialize($publicKeyCredentialSource)),
|
||||
]);
|
||||
$this->save();
|
||||
}
|
||||
}
|
166
src/Application/Model/Webauthn/Webauthn.php
Normal file
166
src/Application/Model/Webauthn/Webauthn.php
Normal file
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Application\Model\Webauthn;
|
||||
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Nyholm\Psr7Server\ServerRequestCreator;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use Webauthn\PublicKeyCredentialCreationOptions;
|
||||
use Webauthn\PublicKeyCredentialRequestOptions;
|
||||
use Webauthn\PublicKeyCredentialRpEntity;
|
||||
use Webauthn\PublicKeyCredentialSource;
|
||||
use Webauthn\Server;
|
||||
|
||||
class Webauthn
|
||||
{
|
||||
public const SESSION_CREATIONS_OPTIONS = 'd3WebAuthnCreationOptions';
|
||||
public const SESSION_ASSERTION_OPTIONS = 'd3WebAuthnAssertionOptions';
|
||||
|
||||
public function getCreationOptions()
|
||||
{
|
||||
/** @var d3_totp_user $user */
|
||||
$user = oxNew(User::class);
|
||||
$user->load('oxdefaultadmin');
|
||||
$userEntity = $user->d3GetWebauthnUserEntity();
|
||||
|
||||
$credentialSourceRepository = new PublicKeyCredentials();
|
||||
$credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity);
|
||||
$excludeCredentials = array_map(function (PublicKeyCredentialSource $credential) {
|
||||
return $credential->getPublicKeyCredentialDescriptor();
|
||||
}, $credentialSources);
|
||||
|
||||
$server = $this->getServer();
|
||||
$publicKeyCredentialCreationOptions = $server->generatePublicKeyCredentialCreationOptions(
|
||||
$userEntity,
|
||||
PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE,
|
||||
$excludeCredentials
|
||||
);
|
||||
|
||||
Registry::getSession()->setVariable(self::SESSION_CREATIONS_OPTIONS, $publicKeyCredentialCreationOptions);
|
||||
|
||||
return json_encode($publicKeyCredentialCreationOptions);
|
||||
}
|
||||
|
||||
public function getRequestOptions()
|
||||
{
|
||||
/** @var d3_totp_user $user */
|
||||
$user = oxNew(User::class);
|
||||
$user->load('oxdefaultadmin');
|
||||
$userEntity = $user->d3GetWebauthnUserEntity();
|
||||
|
||||
// Get the list of authenticators associated to the user
|
||||
$credentialSourceRepository = oxNew(PublicKeyCredentials::class);
|
||||
$credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity);
|
||||
|
||||
// Convert the Credential Sources into Public Key Credential Descriptors
|
||||
$allowedCredentials = array_map(function (PublicKeyCredentialSource $credential) {
|
||||
return $credential->getPublicKeyCredentialDescriptor();
|
||||
}, $credentialSources);
|
||||
|
||||
$server = $this->getServer();
|
||||
|
||||
// We generate the set of options.
|
||||
$publicKeyCredentialRequestOptions = $server->generatePublicKeyCredentialRequestOptions(
|
||||
PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED, // Default value
|
||||
$allowedCredentials
|
||||
);
|
||||
|
||||
Registry::getSession()->setVariable(self::SESSION_ASSERTION_OPTIONS, $publicKeyCredentialRequestOptions);
|
||||
|
||||
return json_encode($publicKeyCredentialRequestOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Server
|
||||
*/
|
||||
public function getServer()
|
||||
{
|
||||
$rpEntity = new PublicKeyCredentialRpEntity(
|
||||
Registry::getConfig()->getActiveShop()->getFieldData('oxname'),
|
||||
preg_replace('/(^www\.)(.*)/mi', '$2', $_SERVER['HTTP_HOST'])
|
||||
);
|
||||
|
||||
return new Server($rpEntity, new PublicKeyCredentials());
|
||||
}
|
||||
|
||||
public function saveAuthn(string $credential)
|
||||
{
|
||||
try {
|
||||
$psr17Factory = new Psr17Factory();
|
||||
$creator = new ServerRequestCreator(
|
||||
$psr17Factory,
|
||||
$psr17Factory,
|
||||
$psr17Factory,
|
||||
$psr17Factory
|
||||
);
|
||||
$serverRequest = $creator->fromGlobals();
|
||||
|
||||
$publicKeyCredentialSource = $this->getServer()->loadAndCheckAttestationResponse(
|
||||
html_entity_decode($credential),
|
||||
Registry::getSession()->getVariable(self::SESSION_CREATIONS_OPTIONS),
|
||||
$serverRequest
|
||||
);
|
||||
|
||||
dumpvar($publicKeyCredentialSource);
|
||||
dumpvar(serialize($publicKeyCredentialSource));
|
||||
dumpvar(unserialize(serialize($publicKeyCredentialSource)));
|
||||
echo "<hr>";
|
||||
dumpvar(bin2hex(serialize($publicKeyCredentialSource)));
|
||||
dumpvar(unserialize(hex2bin(bin2hex(serialize($publicKeyCredentialSource)))));
|
||||
|
||||
$pkCredential = oxNew(PublicKeyCredentials::class);
|
||||
$pkCredential->saveCredentialSource($publicKeyCredentialSource);
|
||||
} catch (\Exception $e) {
|
||||
dumpvar($e->getMessage());
|
||||
dumpvar($e);
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
public function assertAuthn(string $response)
|
||||
{
|
||||
try {
|
||||
$psr17Factory = new Psr17Factory();
|
||||
$creator = new ServerRequestCreator(
|
||||
$psr17Factory,
|
||||
$psr17Factory,
|
||||
$psr17Factory,
|
||||
$psr17Factory
|
||||
);
|
||||
$serverRequest = $creator->fromGlobals();
|
||||
|
||||
/** @var d3_totp_user $user */
|
||||
$user = oxNew(User::class);
|
||||
$user->load('oxdefaultadmin');
|
||||
$userEntity = $user->d3GetWebauthnUserEntity();
|
||||
|
||||
$publicKeySource = $this->getServer()->loadAndCheckAssertionResponse(
|
||||
html_entity_decode($response),
|
||||
Registry::getSession()->getVariable(self::SESSION_ASSERTION_OPTIONS),
|
||||
$userEntity,
|
||||
$serverRequest
|
||||
);
|
||||
/*
|
||||
dumpvar($publicKeySource);
|
||||
dumpvar(serialize($publicKeySource));
|
||||
dumpvar(unserialize(serialize($publicKeySource)));
|
||||
echo "<hr>";
|
||||
dumpvar(bin2hex(serialize($publicKeySource)));
|
||||
dumpvar(unserialize(hex2bin(bin2hex(serialize($publicKeySource)))));
|
||||
*/
|
||||
|
||||
dumpvar('successfully');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
dumpvar($e->getMessage());
|
||||
dumpvar($e);
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
@ -15,11 +15,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Application\Model;
|
||||
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\DatabaseProvider;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Model\BaseModel;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
|
||||
class d3backupcode extends BaseModel
|
||||
{
|
||||
@ -57,7 +57,7 @@ class d3backupcode extends BaseModel
|
||||
public function d3EncodeBC($code, $sUserId)
|
||||
{
|
||||
$oDb = DatabaseProvider::getDb();
|
||||
$oUser = $this->d3TotpGetUserObject();
|
||||
$oUser = $this->d3GetUserObject();
|
||||
$oUser->load($sUserId);
|
||||
$salt = $oUser->getFieldData('oxpasssalt');
|
||||
$sSelect = "SELECT BINARY MD5( CONCAT( " . $oDb->quote($code) . ", UNHEX( ".$oDb->quote($salt)." ) ) )";
|
||||
@ -74,9 +74,8 @@ class d3backupcode extends BaseModel
|
||||
return $this->getUser();
|
||||
}
|
||||
|
||||
/** @var d3_totp_user $oUser */
|
||||
$sUserId = Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTUSER);
|
||||
$oUser = oxNew(User::class);
|
||||
$sUserId = $oUser->d3TotpGetCurrentUser();
|
||||
$oUser->load($sUserId);
|
||||
return $oUser;
|
||||
}
|
||||
@ -84,7 +83,7 @@ class d3backupcode extends BaseModel
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function d3TotpGetUserObject()
|
||||
public function d3GetUserObject()
|
||||
{
|
||||
return oxNew(User::class);
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ use OxidEsales\Eshop\Core\Registry;
|
||||
|
||||
class d3totp extends BaseModel
|
||||
{
|
||||
public const TOTP_SESSION_VARNAME = 'totp_auth';
|
||||
public const TOTP_SESSION_CURRENTUSER = 'd3totpCurrentUser';
|
||||
public const TOTP_SESSION_CURRENTCLASS = 'd3totpCurrentClass';
|
||||
public const TOTP_SESSION_NAVFORMPARAMS = 'd3totpNavFormParams';
|
||||
|
||||
public $tableName = 'd3totp';
|
||||
public $userId;
|
||||
public $totp;
|
||||
@ -143,7 +148,7 @@ class d3totp extends BaseModel
|
||||
{
|
||||
if (false == $this->totp) {
|
||||
$this->totp = TOTP::create($seed ?: $this->getSavedSecret());
|
||||
$this->totp->setLabel($this->getUser()->getFieldData('oxusername') ?: '');
|
||||
$this->totp->setLabel($this->getUser()->getFieldData('oxusername'));
|
||||
$this->totp->setIssuer(Registry::getConfig()->getActiveShop()->getFieldData('oxname'));
|
||||
}
|
||||
|
||||
@ -268,7 +273,7 @@ class d3totp extends BaseModel
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|string $oxid
|
||||
* @param null $oxid
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Application\Model;
|
||||
|
||||
class d3totp_conf
|
||||
{
|
||||
public const OXID_ADMIN_AUTH = 'auth';
|
||||
public const OXID_FRONTEND_AUTH = 'usr';
|
||||
public const SESSION_AUTH = 'd3Totp_auth'; // has valid totp, user is logged in completly
|
||||
public const SESSION_CURRENTUSER = 'd3Totp_currentUser'; // oxid assigned to user from entered username
|
||||
public const SESSION_CURRENTCLASS = 'd3Totp_currentClass'; // oxid assigned to user from entered username
|
||||
public const SESSION_NAVFORMPARAMS = 'd3Totp_navFormParams';
|
||||
public const SESSION_ADMIN_AUTH = 'd3Totp_auth'; // has valid totp, user is logged in completly
|
||||
public const SESSION_ADMIN_CURRENTUSER = 'd3Totp_currentUser'; // oxid assigned to user from entered username
|
||||
public const SESSION_ADMIN_PROFILE = 'd3Totp_currentProfile'; // selected profile
|
||||
public const SESSION_ADMIN_CHLANGUAGE = 'd3Totp_currentChLanguage'; // selected language
|
||||
}
|
@ -25,7 +25,6 @@ $aLang = [
|
||||
'D3_TOTP_BREADCRUMB' => 'Einmalpasswort-Anmeldung',
|
||||
'D3_TOTP_ERROR_UNVALID' => 'Das Einmalpasswort ist ungĂĽltig.',
|
||||
'D3_TOTP_ACCOUNT' => '2-Faktor-Authentisierung',
|
||||
'D3_TOTP_ACCOUNT_DESC' => 'Sichern Sie Ihre Kontoanmeldung mit einem zweiten Faktor.',
|
||||
|
||||
'D3_TOTP_ACCOUNT_USE' => '2-Faktor-Authentisierung verwenden',
|
||||
|
||||
|
@ -25,7 +25,6 @@ $aLang = [
|
||||
'D3_TOTP_BREADCRUMB' => 'one-time password login',
|
||||
'D3_TOTP_ERROR_UNVALID' => 'The one-time password is invalid.',
|
||||
'D3_TOTP_ACCOUNT' => '2-factor authentication',
|
||||
'D3_TOTP_ACCOUNT_DESC' => 'Secure your account login with a second factor.',
|
||||
|
||||
'D3_TOTP_ACCOUNT_USE' => 'Use 2-factor authentication',
|
||||
|
||||
|
@ -41,7 +41,6 @@ $aLang = [
|
||||
'D3_TOTP_REGISTERDELETE_DESC' => 'Um die Registrierung zu ändern, löschen Sie diese bitte vorerst. Sie können sofort im Anschluss eine neue Registrierung anlegen.<br>Wenn Sie die Registrierung löschen, ist das Konto nicht mehr durch die Zwei-Faktor-Authentisierung geschützt.',
|
||||
'D3_TOTP_REGISTERDELETED' => 'Die Registrierung wurde gelöscht.',
|
||||
|
||||
'D3_TOTP_CONFIRMATION' => 'Bestätigung',
|
||||
'D3_TOTP_BACKUPCODES' => 'Backupcodes',
|
||||
'D3_TOTP_BACKUPCODES_DESC' => 'Mit diesen Backupcodes können Sie sich anmelden, wenn die Generierung des Einmalpasswortes nicht möglich ist (z.B. Gerät verloren oder neu installiert). Sie können dann die Einstellungen zur Verwendung der 2-Faktor-Authentisierung ändern oder einen neuen Zugang erstellen. Speichern Sie sich diese Codes bitte in diesem Moment sicher ab. Nach Verlassen dieser Seite können diese Codes nicht erneut angezeigt werden.',
|
||||
'D3_TOTP_AVAILBACKUPCODECOUNT' => 'noch %1$s Backupcode(s) verfĂĽgbar',
|
||||
|
@ -41,7 +41,6 @@ $aLang = [
|
||||
'D3_TOTP_REGISTERDELETE_DESC' => 'To change the registration, please delete it. You can then immediately create a new registration. <br> If you delete the registration, the account is no longer protected by the two-factor authentication.',
|
||||
'D3_TOTP_REGISTERDELETED' => 'The registration has been deleted.',
|
||||
|
||||
'D3_TOTP_CONFIRMATION' => 'confirmation',
|
||||
'D3_TOTP_BACKUPCODES' => 'backup codes',
|
||||
'D3_TOTP_BACKUPCODES_DESC' => 'You can use these backup codes to log on if it is not possible to generate the one-time password (e.g. device lost or newly installed). You can then change the settings to use 2-factor authentication or create a new 2FA login. Please save these codes safely at this moment. After leaving this page, these codes cannot be displayed again.',
|
||||
'D3_TOTP_AVAILBACKUPCODECOUNT' => '%1$s backup code(s) still available',
|
||||
|
@ -1,126 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>[{oxmultilang ident="LOGIN_TITLE"}]</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=[{$charset}]">
|
||||
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
|
||||
<link rel="shortcut icon" href="[{$oViewConf->getImageUrl()}]favicon.ico">
|
||||
<link rel="stylesheet" href="[{$oViewConf->getResourceUrl()}]login.css">
|
||||
<link rel="stylesheet" href="[{$oViewConf->getResourceUrl()}]colors_[{$oViewConf->getEdition()|lower}].css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="admin-login-box">
|
||||
|
||||
<div id="shopLogo"><img src="[{$oViewConf->getImageUrl('logo_dark.svg')}]" alt="" /></div>
|
||||
|
||||
<form action="[{$oViewConf->getSelfLink()}]" method="post" id="login">
|
||||
|
||||
[{block name="admin_login_form"}]
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
|
||||
<input type="hidden" name="fnc" value="checklogin">
|
||||
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
|
||||
<input type="hidden" name="profile" value="[{$selectedProfile}]">
|
||||
<input type="hidden" name="chlanguage" value="[{$selectedChLanguage}]">
|
||||
|
||||
<h3>[{oxmultilang ident="TOTP_INPUT"}]</h3>
|
||||
|
||||
[{if !empty($Errors.default)}]
|
||||
[{include file="inc_error.tpl" Errorlist=$Errors.default}]
|
||||
[{/if}]
|
||||
|
||||
[{$oView->getBackupCodeCountMessage()}]
|
||||
|
||||
<div class="container">
|
||||
<label for="1st">erste TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id='1st' inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent(null, '2nd')" autofocus autocomplete="off">
|
||||
<label for="2nd">zweite TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="2nd" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('1st', '3rd')" autocomplete="off">
|
||||
<label for="3rd">dritte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="3rd" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('2nd', '4th')" autocomplete="off">
|
||||
<label for="4th">vierte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="4th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('3rd', '5th')" autocomplete="off">
|
||||
<label for="5th">fĂĽnfte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="5th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('4th', '6th')" autocomplete="off">
|
||||
<label for="6th">sechste TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="6th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('5th', null)" autocomplete="off">
|
||||
</div>
|
||||
|
||||
[{capture name="d3js"}]
|
||||
function clickEvent(previous, next){
|
||||
const digitKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
const deleteKeys = ['Backspace', 'Delete'];
|
||||
if(next && digitKeys.includes(event.key)){
|
||||
document.getElementById(next).focus();
|
||||
} else if(previous && deleteKeys.includes(event.key)){
|
||||
document.getElementById(previous).focus();
|
||||
}
|
||||
}
|
||||
document.addEventListener("paste", function(e) {
|
||||
if (e.target.type === "text") {
|
||||
var data = e.clipboardData.getData('Text');
|
||||
data = data.split('');
|
||||
[].forEach.call(document.querySelectorAll("#login input[type=text]"), (node, index) => {
|
||||
node.value = data[index];
|
||||
});
|
||||
}
|
||||
});
|
||||
[{/capture}]
|
||||
[{oxscript add=$smarty.capture.d3js}]
|
||||
|
||||
<div>[{oxmultilang ident="TOTP_INPUT_HELP"}]</div>
|
||||
|
||||
<input type="submit" value="[{oxmultilang ident="LOGIN_START"}]" class="btn"><br>
|
||||
|
||||
<input class="btn btn_cancel" value="[{oxmultilang ident="TOTP_CANCEL_LOGIN"}]" type="submit"
|
||||
onclick="document.getElementById('login').fnc.value='d3CancelLogin'; document.getElementById('login').submit();"
|
||||
>
|
||||
|
||||
[{oxstyle include=$oViewConf->getModuleUrl('d3totp', 'out/admin/src/css/d3totplogin.css')}]
|
||||
[{oxstyle}]
|
||||
|
||||
|
||||
|
||||
[{**
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
|
||||
<input type="hidden" name="fnc" value="">
|
||||
<input type="hidden" name="cl" value="login">
|
||||
|
||||
[{if !empty($Errors.default)}]
|
||||
[{include file="inc_error.tpl" Errorlist=$Errors.default}]
|
||||
[{/if}]
|
||||
|
||||
<div class="d3webauthn_icon">
|
||||
<div class="svg-container">
|
||||
[{include file=$oViewConf->getModulePath('d3webauthn', 'out/img/fingerprint.svg')}]
|
||||
</div>
|
||||
<div class="message">[{oxmultilang ident="WEBAUTHN_INPUT_HELP"}]</div>
|
||||
</div>
|
||||
**}]
|
||||
[{* prevent cancel button (1st button) action when form is sent via Enter key *}]
|
||||
[{**
|
||||
<input type="submit" style="display:none !important;">
|
||||
|
||||
<input class="btn btn_cancel" value="[{oxmultilang ident="WEBAUTHN_CANCEL_LOGIN"}]" type="submit"
|
||||
onclick="document.getElementById('login').fnc.value='d3WebauthnCancelLogin'; document.getElementById('login').submit();"
|
||||
>
|
||||
|
||||
[{oxstyle include=$oViewConf->getModuleUrl('d3webauthn', 'out/admin/src/css/d3webauthnlogin.css')}]
|
||||
[{oxstyle}]
|
||||
**}]
|
||||
[{/block}]
|
||||
</form>
|
||||
</div>
|
||||
|
||||
[{oxscript}]
|
||||
<script type="text/javascript">if (window !== window.top) top.location.href = document.location.href;</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,12 +1,5 @@
|
||||
[{include file="headitem.tpl" title="GENERAL_ADMIN_TITLE"|oxmultilangassign}]
|
||||
|
||||
[{oxstyle include="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"}]
|
||||
[{oxscript include="https://code.jquery.com/jquery-3.2.1.slim.min.js"}]
|
||||
[{oxscript include="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"}]
|
||||
[{oxscript include="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"}]
|
||||
[{oxstyle include="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/solid.min.css"}]
|
||||
[{oxstyle}]
|
||||
|
||||
[{assign var="totp" value=$edit->d3GetTotp()}]
|
||||
[{assign var="userid" value=$edit->getId()}]
|
||||
[{$totp->loadByUserId($userid)}]
|
||||
@ -31,9 +24,6 @@
|
||||
text-align: right;
|
||||
color: #6c7c98;
|
||||
}
|
||||
.container-fluid {
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
[{if $force2FA}]
|
||||
@ -67,124 +57,132 @@
|
||||
[{/if}]
|
||||
|
||||
[{if $oxid && $oxid != '-1'}]
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="card">
|
||||
<table style="padding:0; border:0; width:98%;">
|
||||
<tr>
|
||||
<td class="edittext" style="vertical-align: top; padding-top:10px;padding-left:10px; width: 50%;">
|
||||
<table style="padding:0; border:0">
|
||||
[{block name="user_d3user_totp_form1"}]
|
||||
[{if false == $totp->getId()}]
|
||||
<div class="card-header">
|
||||
[{oxmultilang ident="D3_TOTP_REGISTERNEW"}]
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
[{oxmultilang ident="D3_TOTP_QRCODE" suffix="COLON"}]
|
||||
</div>
|
||||
<div class="col-8">
|
||||
[{$totp->getQrCodeElement()}]
|
||||
[{oxinputhelp ident="D3_TOTP_QRCODE_HELP"}]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<h4>[{oxmultilang ident="D3_TOTP_REGISTERNEW"}]</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext">
|
||||
[{oxmultilang ident="D3_TOTP_QRCODE"}]
|
||||
</td>
|
||||
<td class="edittext">
|
||||
[{$totp->getQrCodeElement()}]
|
||||
[{oxinputhelp ident="D3_TOTP_QRCODE_HELP"}]
|
||||
</td>
|
||||
</tr>
|
||||
[{elseif $force2FA}]
|
||||
<div class="card-header">
|
||||
[{oxmultilang ident="D3_TOTP_ADMINBACKEND"}]
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<input
|
||||
type="submit" class="edittext" id="oLockButton" name="delete"
|
||||
value="[{oxmultilang ident="D3_TOTP_ADMINCONTINUE"}]"
|
||||
onClick="document.myedit.fnc.value='';document.myedit.cl.value='admin_start'"
|
||||
>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<h4>[{oxmultilang ident="D3_TOTP_ADMINBACKEND"}]</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<input
|
||||
type="submit" class="edittext" id="oLockButton" name="delete"
|
||||
value="[{oxmultilang ident="D3_TOTP_ADMINCONTINUE"}]"
|
||||
onClick="document.myedit.fnc.value='';document.myedit.cl.value='admin_start'"
|
||||
>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
[{else}]
|
||||
<div class="card-header">
|
||||
[{oxmultilang ident="D3_TOTP_REGISTEREXIST"}]
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
[{oxmultilang ident="D3_TOTP_REGISTERDELETE_DESC"}]
|
||||
<br>
|
||||
<br>
|
||||
<button type="submit" [{$readonly}] class="btn btn-primary btn-outline-danger btn-sm" onClick="document.myedit.fnc.value='delete'">
|
||||
[{oxmultilang ident="D3_TOTP_REGISTERDELETE"}]
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<h4>[{oxmultilang ident="D3_TOTP_REGISTEREXIST"}]</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
[{oxmultilang ident="D3_TOTP_REGISTERDELETE_DESC"}]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2"><br><br>
|
||||
<input type="submit" class="edittext" id="oLockButton" name="delete" value="[{oxmultilang ident="D3_TOTP_REGISTERDELETE"}]" onClick="document.myedit.fnc.value='delete'" [{$readonly}]>
|
||||
</td>
|
||||
</tr>
|
||||
[{/if}]
|
||||
|
||||
[{/block}]
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="card">
|
||||
</table>
|
||||
</td>
|
||||
<!-- Anfang rechte Seite -->
|
||||
<td class="edittext" style="text-align: left; vertical-align: top; height:99%;padding-left:5px;padding-bottom:30px;padding-top:10px; width: 50%;">
|
||||
<table style="padding:0; border:0">
|
||||
[{block name="user_d3user_totp_form2"}]
|
||||
[{if false == $totp->getId()}]
|
||||
<div class="card-header">
|
||||
[{oxmultilang ident="D3_TOTP_CONFIRMATION"}]
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<label for="secret">[{oxmultilang ident="D3_TOTP_SECRET" suffix="COLON"}]</label>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<textarea rows="3" cols="50" id="secret" name="secret" class="editinput" readonly="readonly">[{$totp->getSecret()}]</textarea>
|
||||
[{oxinputhelp ident="D3_TOTP_SECRET_HELP"}]
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" style="margin-top: 20px;">
|
||||
<div class="col-4">
|
||||
<label for="otp">[{oxmultilang ident="D3_TOTP_CURROTP"}]</label>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<input type="text" class="editinput" size="6" maxlength="6" id="otp" name="otp" value="" autofocus="autofocus" [{$readonly}]>
|
||||
[{oxinputhelp ident="D3_TOTP_CURROTP_HELP"}]
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4"></div>
|
||||
<div class="col-8">
|
||||
<button type="submit" [{$readonly}] class="btn btn-primary btn-success btn-sm" onClick="document.myedit.fnc.value='save'">
|
||||
[{oxmultilang ident="D3_TOTP_SAVE"}]
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<h4> </h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext">
|
||||
<label for="secret">[{oxmultilang ident="D3_TOTP_SECRET"}]</label>
|
||||
</td>
|
||||
<td class="edittext">
|
||||
<textarea rows="3" cols="50" id="secret" name="secret" class="editinput" readonly="readonly">[{$totp->getSecret()}]</textarea>
|
||||
[{oxinputhelp ident="D3_TOTP_SECRET_HELP"}]
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="edittext">
|
||||
<label for="otp">[{oxmultilang ident="D3_TOTP_CURROTP"}]</label>
|
||||
</td>
|
||||
<td class="edittext">
|
||||
<input type="text" class="editinput" size="6" maxlength="6" id="otp" name="otp" value="" [{$readonly}]>
|
||||
[{oxinputhelp ident="D3_TOTP_CURROTP_HELP"}]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2"><br><br>
|
||||
<input type="submit" class="edittext" id="oLockButton" name="save" value="[{oxmultilang ident="D3_TOTP_SAVE"}]" onClick="document.myedit.fnc.value='save'" [{$readonly}]>
|
||||
</td>
|
||||
</tr>
|
||||
[{else}]
|
||||
<div class="card-header">
|
||||
[{oxmultilang ident="D3_TOTP_BACKUPCODES"}]
|
||||
</div>
|
||||
<div class="card-body">
|
||||
[{if $oView->getBackupCodes()}]
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="backupcodes">[{oxmultilang ident="D3_TOTP_BACKUPCODES_DESC"}]</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<textarea id="backupcodes" rows="10" cols="20">[{$oView->getBackupCodes()}]</textarea>
|
||||
</div>
|
||||
</div>
|
||||
[{else}]
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
[{oxmultilang ident="D3_TOTP_AVAILBACKUPCODECOUNT" args=$oView->getAvailableBackupCodeCount()}]
|
||||
<br>
|
||||
<br>
|
||||
[{oxmultilang ident="D3_TOTP_AVAILBACKUPCODECOUNT_DESC"}]
|
||||
</div>
|
||||
</div>
|
||||
[{/if}]
|
||||
</div>
|
||||
<tr>
|
||||
<td class="edittext" colspan="2">
|
||||
<h4>[{oxmultilang ident="D3_TOTP_BACKUPCODES"}]</h4>
|
||||
</td>
|
||||
</tr>
|
||||
[{if $oView->getBackupCodes()}]
|
||||
<tr>
|
||||
<td>
|
||||
<label for="backupcodes">[{oxmultilang ident="D3_TOTP_BACKUPCODES_DESC"}]</label>
|
||||
<br>
|
||||
<br>
|
||||
<textarea id="backupcodes" rows="10" cols="20">[{$oView->getBackupCodes()}]</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
[{else}]
|
||||
<tr>
|
||||
<td>
|
||||
[{oxmultilang ident="D3_TOTP_AVAILBACKUPCODECOUNT" args=$oView->getAvailableBackupCodeCount()}]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
[{oxmultilang ident="D3_TOTP_AVAILBACKUPCODECOUNT_DESC"}]
|
||||
</td>
|
||||
</tr>
|
||||
[{/if}]
|
||||
[{/if}]
|
||||
|
||||
[{/block}]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</table>
|
||||
</td>
|
||||
<!-- Ende rechte Seite -->
|
||||
</tr>
|
||||
</table>
|
||||
[{/if}]
|
||||
</form>
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
[{$smarty.block.parent}]
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="[{oxgetseourl ident=$oViewConf->getSelfLink()|cat:"cl=d3_account_totp"}]">[{oxmultilang ident="D3_TOTP_ACCOUNT"}]</a>
|
||||
<a href="[{oxgetseourl ident=$oViewConf->getSslSelfLink()|cat:"cl=d3_account_totp"}]" class="btn btn-default btn-xs pull-right">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="panel-body">[{oxmultilang ident="D3_TOTP_ACCOUNT_DESC"}]</div>
|
||||
</div>
|
@ -1,11 +0,0 @@
|
||||
[{$smarty.block.parent}]
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<a href="[{oxgetseourl ident=$oViewConf->getSelfLink()|cat:"cl=d3_account_totp"}]">[{oxmultilang ident="D3_TOTP_ACCOUNT"}]</a>
|
||||
<a href="[{oxgetseourl ident=$oViewConf->getSslSelfLink()|cat:"cl=d3_account_totp"}]" class="btn btn-outline-dark btn-sm float-right edit-button">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">[{oxmultilang ident="D3_TOTP_ACCOUNT_DESC"}]</div>
|
||||
</div>
|
18
src/Application/views/blocks/page/info/d3webauthn.tpl
Normal file
18
src/Application/views/blocks/page/info/d3webauthn.tpl
Normal file
@ -0,0 +1,18 @@
|
||||
[{oxscript include=$oViewConf->getModuleUrl('d3totp', 'out/src/js/index.js')}]
|
||||
|
||||
[{capture name="d3script"}]
|
||||
var creationOptions = [{$requestOptions}];
|
||||
requestCredentials(creationOptions);
|
||||
[{/capture}]
|
||||
[{oxscript add=$smarty.capture.d3script}]
|
||||
--A--
|
||||
<form id="webauthn" action="[{$oViewConf->getSelfActionLink()}]" method="post">
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
[{$oViewConf->getNavFormParams()}]
|
||||
<input type="hidden" name="fnc" value="assertAuthn">
|
||||
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
|
||||
<input type="hidden" name="credential" value='credent'>
|
||||
</form>
|
||||
--B--
|
||||
|
||||
[{$smarty.block.parent}]
|
@ -0,0 +1,20 @@
|
||||
[{* from https://github.com/jcjones/webauthn.bin.coffee *}]
|
||||
|
||||
[{oxscript include=$oViewConf->getModuleUrl('d3totp', 'out/src/js/index.js')}]
|
||||
|
||||
[{capture name="d3script"}]
|
||||
var creationOptions = [{$creationOptions}];
|
||||
createCredentials(creationOptions);
|
||||
[{/capture}]
|
||||
[{oxscript add=$smarty.capture.d3script}]
|
||||
--A--
|
||||
<form id="webauthn" action="[{$oViewConf->getSelfActionLink()}]" method="post">
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
[{$oViewConf->getNavFormParams()}]
|
||||
<input type="hidden" name="fnc" value="saveAuthn">
|
||||
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
|
||||
<input type="hidden" name="credential" value='credent'>
|
||||
</form>
|
||||
--B--
|
||||
|
||||
[{$smarty.block.parent}]
|
@ -1,4 +0,0 @@
|
||||
[{$smarty.block.parent}]
|
||||
<li>
|
||||
<a href="[{oxgetseourl ident=$oViewConf->getSslSelfLink()|cat:"cl=d3_account_totp"}]">[{oxmultilang ident="D3_TOTP_ACCOUNT"}]</a>
|
||||
</li>
|
@ -11,56 +11,20 @@
|
||||
<form action="[{$oViewConf->getSelfActionLink()}]" method="post" name="login" id="login">
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
|
||||
<input type="hidden" name="fnc" value="d3TotpCheckTotpLogin">
|
||||
<input type="hidden" name="fnc" value="checkTotplogin">
|
||||
<input type="hidden" name="cl" value="[{$oView->getPreviousClass()}]">
|
||||
[{$navFormParams}]
|
||||
|
||||
<h3>[{oxmultilang ident="D3_TOTP_INPUT"}]</h3>
|
||||
|
||||
[{if !empty($Errors.default)}]
|
||||
[{include file="inc_error.tpl" Errorlist=$Errors.default}]
|
||||
[{/if}]
|
||||
|
||||
[{$oView->getBackupCodeCountMessage()}]
|
||||
|
||||
<div class="container">
|
||||
<label for="1st">erste TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id='1st' inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent(null, '2nd')" autofocus autocomplete="off">
|
||||
<label for="2nd">zweite TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="2nd" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('1st', '3rd')" autocomplete="off">
|
||||
<label for="3rd">dritte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="3rd" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('2nd', '4th')" autocomplete="off">
|
||||
<label for="4th">vierte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="4th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('3rd', '5th')" autocomplete="off">
|
||||
<label for="5th">fĂĽnfte TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="5th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('4th', '6th')" autocomplete="off">
|
||||
<label for="6th">sechste TOTP-Ziffer</label>
|
||||
<input type="text" name="d3totp[]" class="digit" id="6th" inputmode="numeric" pattern="[0-9]*" maxlength="1" onkeyup="clickEvent('5th', null)" autocomplete="off">
|
||||
</div>
|
||||
<label for="d3totp">[{oxmultilang ident="D3_TOTP_INPUT"}]</label>
|
||||
<input type="text" name="d3totp" id="d3totp" value="" size="49" autofocus autocomplete="off"><br>
|
||||
|
||||
[{capture name="d3js"}]
|
||||
function clickEvent(previous, next){
|
||||
const digitKeys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
const deleteKeys = ['Backspace', 'Delete'];
|
||||
if(next && digitKeys.includes(event.key)){
|
||||
document.getElementById(next).focus();
|
||||
} else if(previous && deleteKeys.includes(event.key)){
|
||||
document.getElementById(previous).focus();
|
||||
}
|
||||
}
|
||||
document.addEventListener("paste", function(e) {
|
||||
if (e.target.type === "text") {
|
||||
var data = e.clipboardData.getData('Text');
|
||||
data = data.split('');
|
||||
[].forEach.call(document.querySelectorAll("#login input[type=text]"), (node, index) => {
|
||||
node.value = data[index];
|
||||
});
|
||||
}
|
||||
});
|
||||
[{/capture}]
|
||||
[{oxscript add=$smarty.capture.d3js}]
|
||||
|
||||
<div>[{oxmultilang ident="D3_TOTP_INPUT_HELP"}]</div>
|
||||
[{oxmultilang ident="D3_TOTP_INPUT_HELP"}]
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
[{oxmultilang ident="D3_TOTP_SUBMIT_LOGIN"}]
|
||||
@ -70,7 +34,7 @@
|
||||
<form action="[{$oViewConf->getSelfActionLink()}]" method="post" name="login" id="login">
|
||||
[{$oViewConf->getHiddenSid()}]
|
||||
|
||||
<input type="hidden" name="fnc" value="d3TotpCancelTotpLogin">
|
||||
<input type="hidden" name="fnc" value="cancelTotplogin">
|
||||
<input type="hidden" name="cl" value="[{$oView->getPreviousClass()}]">
|
||||
[{$navFormParams}]
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Modules\Application\Component
|
||||
{
|
||||
|
||||
@ -26,8 +24,10 @@ namespace D3\Totp\Modules\Application\Component
|
||||
namespace D3\Totp\Modules\Application\Controller
|
||||
{
|
||||
|
||||
use OxidEsales\Eshop\Application\Controller\ContactController;
|
||||
use OxidEsales\Eshop\Application\Controller\OrderController;
|
||||
use OxidEsales\Eshop\Application\Controller\PaymentController;
|
||||
use OxidEsales\Eshop\Application\Controller\StartController;
|
||||
use OxidEsales\Eshop\Application\Controller\UserController;
|
||||
|
||||
class d3_totp_UserController_parent extends UserController
|
||||
@ -41,6 +41,14 @@ namespace D3\Totp\Modules\Application\Controller
|
||||
class d3_totp_OrderController_parent extends OrderController
|
||||
{
|
||||
}
|
||||
|
||||
class d3_totp_StartController_parent extends StartController
|
||||
{
|
||||
}
|
||||
|
||||
class d3_totp_ContactController_parent extends ContactController
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3\Totp\Modules\Application\Controller\Admin
|
||||
@ -67,13 +75,8 @@ namespace D3\Totp\Modules\Core
|
||||
{
|
||||
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\EshopCommunity\Core\SystemEventHandler;
|
||||
|
||||
class d3_totp_utils_parent extends Utils
|
||||
{
|
||||
}
|
||||
|
||||
class totpSystemEventHandler_parent extends SystemEventHandler
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -16,64 +16,55 @@ declare(strict_types=1);
|
||||
namespace D3\Totp\Modules\Application\Component;
|
||||
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use InvalidArgumentException;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\Eshop\Core\UtilsView;
|
||||
|
||||
class d3_totp_UserComponent extends d3_totp_UserComponent_parent
|
||||
{
|
||||
/**
|
||||
* @param User $oUser
|
||||
*
|
||||
* @return string
|
||||
* @return string|void
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
protected function _afterLogin($oUser)
|
||||
public function login_noredirect()
|
||||
{
|
||||
if (!$oUser instanceof User) {
|
||||
throw oxNew(InvalidArgumentException::class, 'user argument must an instance of User class');
|
||||
}
|
||||
parent::login_noredirect();
|
||||
|
||||
if ($oUser->getId()) {
|
||||
$oUser = $this->getUser();
|
||||
|
||||
if ($oUser instanceof User && $oUser->getId()) {
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId($oUser->getId());
|
||||
|
||||
if ($totp->isActive()
|
||||
&& !$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_AUTH)
|
||||
&& !Registry::getSession()->getVariable(d3totp::TOTP_SESSION_VARNAME)
|
||||
) {
|
||||
$this->d3TotpGetSession()->setVariable(
|
||||
d3totp_conf::SESSION_CURRENTCLASS,
|
||||
Registry::getSession()->setVariable(
|
||||
d3totp::TOTP_SESSION_CURRENTCLASS,
|
||||
$this->getParent()->getClassKey() != 'd3totplogin' ? $this->getParent()->getClassKey() : 'start'
|
||||
);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, $oUser->getId());
|
||||
Registry::getSession()->setVariable(
|
||||
d3totp::TOTP_SESSION_NAVFORMPARAMS,
|
||||
$this->getParent()->getViewConfig()->getNavFormParams()
|
||||
);
|
||||
|
||||
$oUser->logout();
|
||||
|
||||
$this->d3TotpGetSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, $oUser->getId());
|
||||
$this->d3TotpGetSession()->setVariable(
|
||||
d3totp_conf::SESSION_NAVFORMPARAMS,
|
||||
$this->getParent()->getViewConfig()->getNavFormParams()
|
||||
);
|
||||
|
||||
$sUrl = Registry::getConfig()->getShopHomeUrl() . 'cl=d3totplogin';
|
||||
$this->d3TotpGetUtils()->redirect($sUrl, false);
|
||||
return "d3totplogin";
|
||||
}
|
||||
}
|
||||
|
||||
return parent::_afterLogin($oUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3totp
|
||||
*/
|
||||
public function d3GetTotpObject(): d3totp
|
||||
public function d3GetTotpObject()
|
||||
{
|
||||
return oxNew(d3totp::class);
|
||||
}
|
||||
@ -82,33 +73,26 @@ class d3_totp_UserComponent extends d3_totp_UserComponent_parent
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function d3TotpCheckTotpLogin()
|
||||
public function checkTotplogin()
|
||||
{
|
||||
$sTotp = implode('', Registry::getRequest()->getRequestEscapedParameter('d3totp') ?: []);
|
||||
$sTotp = Registry::getRequest()->getRequestEscapedParameter('d3totp', true);
|
||||
|
||||
/** @var d3_totp_user $oUser */
|
||||
$sUserId = Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTUSER);
|
||||
$oUser = oxNew(User::class);
|
||||
$sUserId = Registry::getSession()->getVariable(d3totp_conf::SESSION_CURRENTUSER);
|
||||
$oUser->load($sUserId);
|
||||
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId($sUserId);
|
||||
|
||||
try {
|
||||
if (!$this->d3TotpIsNoTotpOrNoLogin($totp) && $this->d3TotpHasValidTotp($sTotp, $totp)) {
|
||||
// relogin, don't extract from this try block
|
||||
$this->d3TotpGetSession()->setVariable(d3totp_conf::SESSION_AUTH, $oUser->getId());
|
||||
$this->d3TotpGetSession()->setVariable(d3totp_conf::OXID_FRONTEND_AUTH, $oUser->getId());
|
||||
$this->setUser($oUser);
|
||||
$this->setLoginStatus(USER_LOGIN_SUCCESS);
|
||||
$this->_afterLogin($oUser);
|
||||
|
||||
if (!$this->isNoTotpOrNoLogin($totp) && $this->hasValidTotp($sTotp, $totp)) {
|
||||
$this->d3TotpRelogin($oUser, $sTotp);
|
||||
$this->d3TotpClearSessionVariables();
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch (d3totp_wrongOtpException $oEx) {
|
||||
$this->d3TotpGetUtilsView()->addErrorToDisplay($oEx, false, false, "", 'd3totplogin');
|
||||
$this->d3GetUtilsView()->addErrorToDisplay($oEx, false, false, "", 'd3totplogin');
|
||||
}
|
||||
|
||||
return 'd3totplogin';
|
||||
@ -117,20 +101,12 @@ class d3_totp_UserComponent extends d3_totp_UserComponent_parent
|
||||
/**
|
||||
* @return UtilsView
|
||||
*/
|
||||
public function d3TotpGetUtilsView()
|
||||
public function d3GetUtilsView()
|
||||
{
|
||||
return Registry::getUtilsView();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Utils
|
||||
*/
|
||||
public function d3TotpGetUtils()
|
||||
{
|
||||
return Registry::getUtils();
|
||||
}
|
||||
|
||||
public function d3TotpCancelTotpLogin()
|
||||
public function cancelTotpLogin()
|
||||
{
|
||||
$this->d3TotpClearSessionVariables();
|
||||
|
||||
@ -141,9 +117,9 @@ class d3_totp_UserComponent extends d3_totp_UserComponent_parent
|
||||
* @param d3totp $totp
|
||||
* @return bool
|
||||
*/
|
||||
public function d3TotpIsNoTotpOrNoLogin($totp)
|
||||
public function isNoTotpOrNoLogin($totp)
|
||||
{
|
||||
return false == Registry::getSession()->getVariable(d3totp_conf::SESSION_CURRENTUSER)
|
||||
return false == Registry::getSession()->getVariable(d3totp::TOTP_SESSION_CURRENTUSER)
|
||||
|| false == $totp->isActive();
|
||||
}
|
||||
|
||||
@ -154,23 +130,38 @@ class d3_totp_UserComponent extends d3_totp_UserComponent_parent
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws d3totp_wrongOtpException
|
||||
*/
|
||||
public function d3TotpHasValidTotp($sTotp, $totp)
|
||||
public function hasValidTotp($sTotp, $totp)
|
||||
{
|
||||
return Registry::getSession()->getVariable(d3totp_conf::SESSION_AUTH) ||
|
||||
$totp->verify($sTotp);
|
||||
return Registry::getSession()->getVariable(d3totp::TOTP_SESSION_VARNAME) ||
|
||||
(
|
||||
$sTotp && $totp->verify($sTotp)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $oUser
|
||||
* @param $sTotp
|
||||
*/
|
||||
public function d3TotpRelogin(User $oUser, $sTotp)
|
||||
{
|
||||
$this->d3GetSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, $sTotp);
|
||||
$this->d3GetSession()->setVariable('usr', $oUser->getId());
|
||||
$this->setUser(null);
|
||||
$this->setLoginStatus(USER_LOGIN_SUCCESS);
|
||||
$this->_afterLogin($oUser);
|
||||
}
|
||||
|
||||
public function d3TotpClearSessionVariables()
|
||||
{
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_CURRENTCLASS);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_CURRENTUSER);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_NAVFORMPARAMS);
|
||||
$this->d3GetSession()->deleteVariable(d3totp::TOTP_SESSION_CURRENTCLASS);
|
||||
$this->d3GetSession()->deleteVariable(d3totp::TOTP_SESSION_CURRENTUSER);
|
||||
$this->d3GetSession()->deleteVariable(d3totp::TOTP_SESSION_NAVFORMPARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSession()
|
||||
public function d3GetSession()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
@ -15,115 +15,163 @@ declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Modules\Application\Controller\Admin;
|
||||
|
||||
use D3\TestingTools\Production\IsMockable;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Language;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\UtilsServer;
|
||||
use OxidEsales\Eshop\Core\UtilsView;
|
||||
|
||||
class d3_totp_LoginController extends d3_totp_LoginController_parent
|
||||
{
|
||||
use IsMockable;
|
||||
/**
|
||||
* @return string
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$auth = $this->d3GetSession()->getVariable("auth");
|
||||
|
||||
$return = parent::render();
|
||||
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId($auth);
|
||||
|
||||
if ($auth
|
||||
&& $totp->isActive()
|
||||
&& !$this->d3GetSession()->getVariable(d3totp::TOTP_SESSION_VARNAME)
|
||||
) {
|
||||
// set auth as secured parameter;
|
||||
$this->d3GetSession()->setVariable("auth", $auth);
|
||||
$this->addTplParam('request_totp', true);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3totp
|
||||
*/
|
||||
public function d3GetTotpObject(): d3totp
|
||||
public function d3GetTotpObject()
|
||||
{
|
||||
return oxNew(d3totp::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3backupcodelist
|
||||
*/
|
||||
public function d3GetBackupCodeListObject()
|
||||
{
|
||||
return oxNew(d3backupcodelist::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UtilsView
|
||||
*/
|
||||
public function d3GetUtilsView()
|
||||
{
|
||||
return Registry::getUtilsView();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSession(): Session
|
||||
public function d3GetSession()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function checklogin()
|
||||
{
|
||||
$this->d3TotpGetSession()->setVariable(
|
||||
d3totp_conf::SESSION_ADMIN_PROFILE,
|
||||
Registry::getRequest()->getRequestEscapedParameter('profile')
|
||||
);
|
||||
$this->d3TotpGetSession()->setVariable(
|
||||
d3totp_conf::SESSION_ADMIN_CHLANGUAGE,
|
||||
Registry::getRequest()->getRequestEscapedParameter('chlanguage')
|
||||
);
|
||||
$sTotp = Registry::getRequest()->getRequestEscapedParameter('d3totp', true);
|
||||
|
||||
return $this->d3CallMockableFunction([d3_totp_LoginController_parent::class, 'checklogin']);
|
||||
}
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId(Registry::getSession()->getVariable("auth"));
|
||||
|
||||
public function d3totpAfterLogin()
|
||||
{
|
||||
$myUtilsServer = $this->d3TotpGetUtilsServer();
|
||||
$sProfile = $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_PROFILE);
|
||||
$return = 'login';
|
||||
|
||||
// #533
|
||||
if (isset($sProfile)) {
|
||||
$aProfiles = $this->d3TotpGetSession()->getVariable("aAdminProfiles");
|
||||
if ($aProfiles && isset($aProfiles[$sProfile])) {
|
||||
// setting cookie to store last locally used profile
|
||||
$myUtilsServer->setOxCookie("oxidadminprofile", $sProfile . "@" . implode("@", $aProfiles[$sProfile]), time() + 31536000, "/");
|
||||
$this->d3TotpGetSession()->setVariable("profile", $aProfiles[$sProfile]);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_PROFILE);
|
||||
try {
|
||||
if ($this->isNoTotpOrNoLogin($totp) && $this->hasLoginCredentials()) {
|
||||
$return = parent::checklogin();
|
||||
} elseif ($this->hasValidTotp($sTotp, $totp)) {
|
||||
$this->d3GetSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, $sTotp);
|
||||
$return = "admin_start";
|
||||
}
|
||||
} else {
|
||||
//deleting cookie info, as setting profile to default
|
||||
$myUtilsServer->setOxCookie("oxidadminprofile", "", time() - 3600, "/");
|
||||
} catch (d3totp_wrongOtpException $oEx) {
|
||||
$this->d3GetUtilsView()->addErrorToDisplay($oEx);
|
||||
}
|
||||
|
||||
$this->d3totpAfterLoginSetLanguage();
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE);
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function d3totpAfterLoginSetLanguage()
|
||||
/**
|
||||
* @return string|void
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function getBackupCodeCountMessage()
|
||||
{
|
||||
$myUtilsServer = $this->d3TotpGetUtilsServer();
|
||||
$iLang = $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE);
|
||||
$oBackupCodeList = $this->d3GetBackupCodeListObject();
|
||||
$iCount = $oBackupCodeList->getAvailableCodeCount(Registry::getSession()->getVariable("auth"));
|
||||
|
||||
$aLanguages = $this->d3TotpGetLangObject()->getAdminTplLanguageArray();
|
||||
if (!isset($aLanguages[$iLang])) {
|
||||
$iLang = key($aLanguages);
|
||||
if ($iCount < 4) {
|
||||
return sprintf(
|
||||
Registry::getLang()->translateString('D3_TOTP_AVAILBACKUPCODECOUNT'),
|
||||
$iCount
|
||||
);
|
||||
}
|
||||
|
||||
$myUtilsServer->setOxCookie("oxidadminlanguage", $aLanguages[$iLang]->abbr, time() + 31536000, "/");
|
||||
$this->d3TotpGetLangObject()->setTplLanguage($iLang);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param d3totp $totp
|
||||
* @return bool
|
||||
*/
|
||||
public function d3TotpLoginMissing($totp)
|
||||
public function isNoTotpOrNoLogin($totp)
|
||||
{
|
||||
return $totp->isActive()
|
||||
&& false == $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_AUTH);
|
||||
return false == $this->d3GetSession()->getVariable("auth")
|
||||
|| false == $totp->isActive();
|
||||
}
|
||||
|
||||
protected function hasLoginCredentials()
|
||||
{
|
||||
return Registry::getRequest()->getRequestEscapedParameter('user') &&
|
||||
Registry::getRequest()->getRequestEscapedParameter('pwd');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UtilsServer
|
||||
* @param string $sTotp
|
||||
* @param d3totp $totp
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws d3totp_wrongOtpException
|
||||
*/
|
||||
protected function d3TotpGetUtilsServer(): UtilsServer
|
||||
public function hasValidTotp($sTotp, $totp)
|
||||
{
|
||||
return Registry::getUtilsServer();
|
||||
return Registry::getSession()->getVariable(d3totp::TOTP_SESSION_VARNAME) ||
|
||||
(
|
||||
$sTotp && $totp->verify($sTotp)
|
||||
);
|
||||
}
|
||||
|
||||
public function d3CancelLogin()
|
||||
{
|
||||
$oUser = $this->d3GetUserObject();
|
||||
$oUser->logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Language
|
||||
* @return User
|
||||
*/
|
||||
protected function d3TotpGetLangObject(): Language
|
||||
public function d3GetUserObject()
|
||||
{
|
||||
return Registry::getLang();
|
||||
return oxNew(User::class);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace D3\Totp\Modules\Application\Controller;
|
||||
|
||||
use D3\Totp\Application\Model\Webauthn\Webauthn;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
|
||||
class d3_totp_ContactController extends d3_totp_ContactController_parent
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
$webAuthn = oxNew(Webauthn::class);
|
||||
$this->addTplParam('requestOptions', $webAuthn->getRequestOptions());
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
public function assertAuthn()
|
||||
{
|
||||
$webAuthn = oxNew(Webauthn::class);
|
||||
$webAuthn->assertAuthn(Registry::getRequest()->getRequestEscapedParameter('credential'));
|
||||
}
|
||||
}
|
@ -18,6 +18,4 @@ namespace D3\Totp\Modules\Application\Controller;
|
||||
class d3_totp_OrderController extends d3_totp_OrderController_parent
|
||||
{
|
||||
use d3_totp_getUserTrait;
|
||||
|
||||
private $parentClass = d3_totp_OrderController_parent::class;
|
||||
}
|
||||
|
@ -18,6 +18,4 @@ namespace D3\Totp\Modules\Application\Controller;
|
||||
class d3_totp_PaymentController extends d3_totp_PaymentController_parent
|
||||
{
|
||||
use d3_totp_getUserTrait;
|
||||
|
||||
private $parentClass = d3_totp_PaymentController_parent::class;
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace D3\Totp\Modules\Application\Controller;
|
||||
|
||||
use D3\Totp\Application\Model\Webauthn\Webauthn;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
|
||||
class d3_totp_StartController extends d3_totp_StartController_parent
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
$webAuthn = oxNew(Webauthn::class);
|
||||
$this->addTplParam('creationOptions', $webAuthn->getCreationOptions());
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
public function saveAuthn()
|
||||
{
|
||||
$webAuthn = oxNew(Webauthn::class);
|
||||
$webAuthn->saveAuthn(Registry::getRequest()->getRequestEscapedParameter('credential'));
|
||||
}
|
||||
}
|
@ -18,6 +18,4 @@ namespace D3\Totp\Modules\Application\Controller;
|
||||
class d3_totp_UserController extends d3_totp_UserController_parent
|
||||
{
|
||||
use d3_totp_getUserTrait;
|
||||
|
||||
private $parentClass = d3_totp_UserController_parent::class;
|
||||
}
|
||||
|
@ -15,9 +15,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Modules\Application\Controller;
|
||||
|
||||
use D3\TestingTools\Production\IsMockable;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
@ -25,31 +23,26 @@ use OxidEsales\Eshop\Core\Session;
|
||||
|
||||
trait d3_totp_getUserTrait
|
||||
{
|
||||
use IsMockable;
|
||||
|
||||
/**
|
||||
* @return bool|object|User
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
/** @var User|null $user */
|
||||
$user = $this->d3CallMockableFunction([$this->parentClass, 'getUser']);
|
||||
$oUser = parent::getUser();
|
||||
|
||||
if ($user && $user->isLoaded() && $user->getId()) {
|
||||
if ($oUser instanceof User && $oUser->getId()) {
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId($user->getId());
|
||||
$totp->loadByUserId($oUser->getId());
|
||||
|
||||
if ($totp->isActive()
|
||||
&& !$this->d3TotpGetSessionObject()->getVariable(
|
||||
isAdmin() ? d3totp_conf::SESSION_ADMIN_AUTH : d3totp_conf::SESSION_AUTH
|
||||
)
|
||||
&& !$this->d3GetSessionObject()->getVariable(d3totp::TOTP_SESSION_VARNAME)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
return $oUser;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,7 +56,7 @@ trait d3_totp_getUserTrait
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSessionObject()
|
||||
public function d3GetSessionObject()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
@ -16,9 +16,10 @@ declare(strict_types=1);
|
||||
namespace D3\Totp\Modules\Application\Model;
|
||||
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use OxidEsales\Eshop\Core\Exception\StandardException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use Webauthn\PublicKeyCredentialUserEntity;
|
||||
|
||||
class d3_totp_user extends d3_totp_user_parent
|
||||
{
|
||||
@ -26,10 +27,7 @@ class d3_totp_user extends d3_totp_user_parent
|
||||
{
|
||||
$return = parent::logout();
|
||||
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_AUTH);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_CURRENTUSER);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_AUTH);
|
||||
$this->d3TotpGetSession()->deleteVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER);
|
||||
$this->d3GetSession()->deleteVariable(d3totp::TOTP_SESSION_VARNAME);
|
||||
|
||||
return $return;
|
||||
}
|
||||
@ -45,23 +43,24 @@ class d3_totp_user extends d3_totp_user_parent
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSession()
|
||||
public function d3GetSession()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @return PublicKeyCredentialUserEntity
|
||||
*/
|
||||
public function d3TotpGetCurrentUser(): ?string
|
||||
public function d3GetWebauthnUserEntity(): PublicKeyCredentialUserEntity
|
||||
{
|
||||
return $this->isAdmin() ?
|
||||
($this->d3TotpGetSession()->hasVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER) ?
|
||||
$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER) :
|
||||
$this->d3TotpGetSession()->getVariable(d3totp_conf::OXID_ADMIN_AUTH))
|
||||
:
|
||||
($this->d3TotpGetSession()->hasVariable(d3totp_conf::SESSION_CURRENTUSER) ?
|
||||
$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_CURRENTUSER) :
|
||||
$this->d3TotpGetSession()->getVariable(d3totp_conf::OXID_FRONTEND_AUTH));
|
||||
if ($this->isLoaded()) {
|
||||
return oxNew(PublicKeyCredentialUserEntity::class,
|
||||
$this->getFieldData('oxusername'),
|
||||
$this->getId(),
|
||||
$this->getFieldData('oxfname') . ' ' . $this->getFieldData('oxlname')
|
||||
);
|
||||
}
|
||||
|
||||
throw oxNew(StandardException::class, 'can not create webauthn user entity from not loaded user');
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,6 @@ declare(strict_types=1);
|
||||
namespace D3\Totp\Modules\Core;
|
||||
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use OxidEsales\Eshop\Core\Config;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
@ -33,9 +32,10 @@ class d3_totp_utils extends d3_totp_utils_parent
|
||||
public function checkAccessRights()
|
||||
{
|
||||
$blAuth = parent::checkAccessRights();
|
||||
|
||||
$blAuth = $this->d3AuthHook($blAuth);
|
||||
$userID = $this->d3TotpGetSessionObject()->getVariable(d3totp_conf::OXID_ADMIN_AUTH);
|
||||
$totpAuth = (bool) $this->d3TotpGetSessionObject()->getVariable(d3totp_conf::SESSION_ADMIN_AUTH);
|
||||
$userID = $this->d3GetSessionObject()->getVariable("auth");
|
||||
$totpAuth = (bool) $this->d3GetSessionObject()->getVariable(d3totp::TOTP_SESSION_VARNAME);
|
||||
/** @var d3totp $totp */
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$totp->loadByUserId($userID);
|
||||
@ -47,11 +47,21 @@ class d3_totp_utils extends d3_totp_utils_parent
|
||||
&& $totp->isActive() === false
|
||||
) {
|
||||
$this->redirect('index.php?cl=d3force_2fa');
|
||||
if (false == defined('OXID_PHP_UNIT')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
exit;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
//staten der prĂĽfung vom einmalpasswort
|
||||
if ($blAuth && $totp->isActive() && false === $totpAuth) {
|
||||
$this->redirect('index.php?cl=d3totpadminlogin', false);
|
||||
$this->redirect('index.php?cl=login');
|
||||
if (false == defined('OXID_PHP_UNIT')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
exit;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
||||
return $blAuth;
|
||||
@ -60,7 +70,7 @@ class d3_totp_utils extends d3_totp_utils_parent
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSessionObject()
|
||||
public function d3GetSessionObject()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\Modules\Core;
|
||||
|
||||
use D3\TestingTools\Production\IsMockable;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
|
||||
class totpSystemEventHandler extends totpSystemEventHandler_parent
|
||||
{
|
||||
use IsMockable;
|
||||
|
||||
public function onAdminLogin()
|
||||
{
|
||||
$this->d3RequestTotp();
|
||||
|
||||
$this->d3CallMockableFunction([totpSystemEventHandler_parent::class, 'onAdminLogin']);
|
||||
}
|
||||
|
||||
protected function d3requestTotp()
|
||||
{
|
||||
$totp = $this->d3GetTotpObject();
|
||||
$userId = $this->d3TotpGetSession()->getVariable(d3totp_conf::OXID_ADMIN_AUTH);
|
||||
$totp->loadByUserId($userId);
|
||||
|
||||
if ($this->d3TotpLoginMissing($totp)) {
|
||||
/** @var d3_totp_user $user */
|
||||
$user = $this->d3TotpGetUserObject();
|
||||
$user->logout();
|
||||
|
||||
$this->d3TotpGetSession()->setVariable(d3totp_conf::SESSION_ADMIN_CURRENTUSER, $userId);
|
||||
|
||||
$this->getUtilsObject()->redirect(
|
||||
'index.php?cl=d3totpadminlogin&'.
|
||||
'profile='.$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_PROFILE).'&'.
|
||||
'chlanguage='.$this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_CHLANGUAGE),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return d3totp
|
||||
*/
|
||||
public function d3GetTotpObject()
|
||||
{
|
||||
return oxNew(d3totp::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Utils
|
||||
*/
|
||||
public function getUtilsObject(): Utils
|
||||
{
|
||||
return Registry::getUtils();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3TotpGetSession()
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param d3totp $totp
|
||||
* @return bool
|
||||
*/
|
||||
public function d3TotpLoginMissing($totp)
|
||||
{
|
||||
return $totp->isActive()
|
||||
&& false == $this->d3TotpGetSession()->getVariable(d3totp_conf::SESSION_ADMIN_AUTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
protected function d3TotpGetUserObject(): User
|
||||
{
|
||||
return oxNew(User::class);
|
||||
}
|
||||
}
|
BIN
src/logo.png
BIN
src/logo.png
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB |
43
src/metadata.php
Executable file → Normal file
43
src/metadata.php
Executable file → Normal file
@ -13,26 +13,27 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use D3\Totp\Application\Controller\Admin\d3totpadminlogin;
|
||||
use D3\Totp\Application\Controller\Admin\d3user_totp;
|
||||
use D3\Totp\Application\Controller\Admin\d3force_2fa;
|
||||
use D3\Totp\Application\Controller\d3_account_totp;
|
||||
use D3\Totp\Application\Controller\d3totplogin;
|
||||
use D3\Totp\Modules\Application\Component\d3_totp_UserComponent;
|
||||
use D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_ContactController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_OrderController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_PaymentController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_StartController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_UserController;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\Modules\Core\d3_totp_utils;
|
||||
use D3\Totp\Modules\Core\totpSystemEventHandler;
|
||||
use D3\Totp\Setup as ModuleSetup;
|
||||
use OxidEsales\Eshop\Application\Component\UserComponent;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
|
||||
use OxidEsales\Eshop\Application\Controller\ContactController;
|
||||
use OxidEsales\Eshop\Application\Controller\OrderController;
|
||||
use OxidEsales\Eshop\Application\Controller\PaymentController;
|
||||
use OxidEsales\Eshop\Application\Controller\StartController;
|
||||
use OxidEsales\Eshop\Application\Controller\UserController;
|
||||
use OxidEsales\Eshop\Core\SystemEventHandler;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\Eshop\Application\Model as OxidModel;
|
||||
|
||||
@ -50,18 +51,17 @@ $logo = '<img src="https://logos.oxidmodule.com/d3logo.svg" alt="(D3)" style="he
|
||||
$aModule = [
|
||||
'id' => $sModuleId,
|
||||
'title' => [
|
||||
'de' => $logo . ' zweiter Faktor - Einmalpasswort',
|
||||
'en' => $logo . ' second factor - one-time password',
|
||||
'de' => $logo . ' Zwei-Faktor-Authentisierung',
|
||||
'en' => $logo . ' two-factor authentication',
|
||||
],
|
||||
'description' => [
|
||||
'de' => 'Einmalpasswort (TOTP) als zweiter Faktor bei der Anmeldung im OXID eSales Shop',
|
||||
'en' => 'One-time password (TOTP) as second factor for login in OXID eSales shop',
|
||||
'de' => 'Zwei-Faktor-Authentisierung (TOTP) für OXID eSales Shop',
|
||||
'en' => 'Two-factor authentication (TOTP) for OXID eSales shop',
|
||||
],
|
||||
'version' => '2.1.1.0',
|
||||
'version' => '2.0.0.0',
|
||||
'author' => 'D³ Data Development (Inh.: Thomas Dartsch)',
|
||||
'email' => 'support@shopmodule.com',
|
||||
'url' => 'https://www.oxidmodule.com/',
|
||||
'thumbnail' => 'logo.png',
|
||||
'extend' => [
|
||||
UserController::class => d3_totp_UserController::class,
|
||||
PaymentController::class => d3_totp_PaymentController::class,
|
||||
@ -70,20 +70,19 @@ $aModule = [
|
||||
LoginController::class => d3_totp_LoginController::class,
|
||||
Utils::class => d3_totp_utils::class,
|
||||
UserComponent::class => d3_totp_UserComponent::class,
|
||||
SystemEventHandler::class => totpSystemEventHandler::class,
|
||||
StartController::class => d3_totp_StartController::class,
|
||||
ContactController::class => d3_totp_ContactController::class
|
||||
],
|
||||
'controllers' => [
|
||||
'd3user_totp' => d3user_totp::class,
|
||||
'd3force_2fa' => d3force_2fa::class,
|
||||
'd3totplogin' => d3totplogin::class,
|
||||
'd3_account_totp' => d3_account_totp::class,
|
||||
'd3totpadminlogin' => d3totpadminlogin::class,
|
||||
],
|
||||
'templates' => [
|
||||
'd3user_totp.tpl' => 'd3/totp/Application/views/admin/tpl/d3user_totp.tpl',
|
||||
'd3totplogin.tpl' => 'd3/totp/Application/views/tpl/d3totplogin.tpl',
|
||||
'd3_account_totp.tpl' => 'd3/totp/Application/views/tpl/d3_account_totp.tpl',
|
||||
'd3totpadminlogin.tpl' => 'd3/totp/Application/views/admin/tpl/d3totplogin.tpl',
|
||||
],
|
||||
'settings' => [
|
||||
[
|
||||
@ -109,20 +108,14 @@ $aModule = [
|
||||
'file' => 'Application/views/blocks/page/account/inc/account_menu.tpl',
|
||||
],
|
||||
[
|
||||
'template' => 'page/account/dashboard.tpl',
|
||||
'block' => 'account_dashboard_col2',
|
||||
'file' => 'Application/views/blocks/page/account/account_dashboard_col2_wave.tpl',
|
||||
'template' => 'page/shop/start.tpl',
|
||||
'block' => 'start_welcome_text',
|
||||
'file' => 'Application/views/blocks/page/shop/start_welcome_text.tpl',
|
||||
],
|
||||
[
|
||||
'theme' => 'flow',
|
||||
'template' => 'page/account/dashboard.tpl',
|
||||
'block' => 'account_dashboard_col2',
|
||||
'file' => 'Application/views/blocks/page/account/account_dashboard_col2_flow.tpl',
|
||||
'template' => 'page/info/contact.tpl',
|
||||
'block' => 'd3webauthn',
|
||||
'file' => 'Application/views/blocks/page/info/d3webauthn.tpl',
|
||||
],
|
||||
[
|
||||
'template' => 'widget/header/servicebox.tpl',
|
||||
'block' => 'widget_header_servicebox_items',
|
||||
'file' => 'Application/views/blocks/widget/header/widget_header_servicebox_items.tpl',
|
||||
],
|
||||
],
|
||||
]
|
||||
];
|
||||
|
@ -9,33 +9,4 @@
|
||||
order: 2;
|
||||
background: silver;
|
||||
color: black;
|
||||
}
|
||||
#login label {
|
||||
position: absolute;
|
||||
left: -2000px;
|
||||
}
|
||||
|
||||
#login label.show {
|
||||
position: relative;
|
||||
display: block;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#login .container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#login .digit {
|
||||
height: 3em;
|
||||
width: 2em;
|
||||
margin: 0 2px;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#login .digit:nth-of-type(4) {
|
||||
margin-left: 7px;
|
||||
}
|
@ -14,35 +14,4 @@
|
||||
.cl-d3totplogin .mainforms {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
#login label {
|
||||
position: absolute;
|
||||
left: -2000px;
|
||||
}
|
||||
|
||||
#login label.show {
|
||||
position: relative;
|
||||
display: block;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#login .container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 20px 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#login .digit {
|
||||
width: 2em;
|
||||
margin: 0 2px;
|
||||
text-align: center;
|
||||
height: 3em;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
#login .digit:nth-of-type(4) {
|
||||
margin-left: 15px;
|
||||
}
|
185
src/out/src/js/index.js
Normal file
185
src/out/src/js/index.js
Normal file
@ -0,0 +1,185 @@
|
||||
if (!window.PublicKeyCredential) {
|
||||
console.error('no window pubkeycred available');
|
||||
}
|
||||
|
||||
const base64UrlDecode = (input) => {
|
||||
"use strict";
|
||||
input = input
|
||||
.replace(/-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
|
||||
const pad = input.length % 4;
|
||||
if (pad) {
|
||||
if (pad === 1) {
|
||||
throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding');
|
||||
}
|
||||
input += new Array(5-pad).join('=');
|
||||
}
|
||||
|
||||
return window.atob(input);
|
||||
};
|
||||
|
||||
const prepareOptions = (publicKey) => {
|
||||
"use strict";
|
||||
//Convert challenge from Base64Url string to Uint8Array
|
||||
publicKey.challenge = Uint8Array.from(
|
||||
base64UrlDecode(publicKey.challenge),
|
||||
c => c.charCodeAt(0)
|
||||
);
|
||||
|
||||
//Convert the user ID from Base64 string to Uint8Array
|
||||
if (publicKey.user !== undefined) {
|
||||
publicKey.user = {
|
||||
...publicKey.user,
|
||||
id: Uint8Array.from(
|
||||
window.atob(publicKey.user.id),
|
||||
c => c.charCodeAt(0)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
//If excludeCredentials is defined, we convert all IDs to Uint8Array
|
||||
if (publicKey.excludeCredentials !== undefined) {
|
||||
publicKey.excludeCredentials = publicKey.excludeCredentials.map(
|
||||
data => {
|
||||
return {
|
||||
...data,
|
||||
id: Uint8Array.from(
|
||||
base64UrlDecode(data.id),
|
||||
c => c.charCodeAt(0)
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (publicKey.allowCredentials !== undefined) {
|
||||
publicKey.allowCredentials = publicKey.allowCredentials.map(
|
||||
data => {
|
||||
return {
|
||||
...data,
|
||||
id: Uint8Array.from(
|
||||
base64UrlDecode(data.id),
|
||||
c => c.charCodeAt(0)
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return publicKey;
|
||||
};
|
||||
|
||||
/** https://gist.github.com/jonleighton/958841 **/
|
||||
function base64ArrayBuffer(arrayBuffer) {
|
||||
"use strict";
|
||||
var base64 = ''
|
||||
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
|
||||
var bytes = new Uint8Array(arrayBuffer)
|
||||
var byteLength = bytes.byteLength
|
||||
var byteRemainder = byteLength % 3
|
||||
var mainLength = byteLength - byteRemainder
|
||||
|
||||
var a, b, c, d
|
||||
var chunk
|
||||
|
||||
// Main loop deals with bytes in chunks of 3
|
||||
for (var i = 0; i < mainLength; i = i + 3) {
|
||||
// Combine the three bytes into a single integer
|
||||
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
|
||||
|
||||
// Use bitmasks to extract 6-bit segments from the triplet
|
||||
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
|
||||
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
|
||||
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
|
||||
d = chunk & 63 // 63 = 2^6 - 1
|
||||
|
||||
// Convert the raw binary segments to the appropriate ASCII encoding
|
||||
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
|
||||
}
|
||||
|
||||
// Deal with the remaining bytes and padding
|
||||
if (byteRemainder === 1) {
|
||||
chunk = bytes[mainLength]
|
||||
|
||||
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
|
||||
|
||||
// Set the 4 least significant bits to zero
|
||||
b = (chunk & 3) << 4 // 3 = 2^2 - 1
|
||||
|
||||
base64 += encodings[a] + encodings[b] + '=='
|
||||
} else if (byteRemainder === 2) {
|
||||
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
|
||||
|
||||
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
|
||||
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
|
||||
|
||||
// Set the 2 least significant bits to zero
|
||||
c = (chunk & 15) << 2 // 15 = 2^4 - 1
|
||||
|
||||
base64 += encodings[a] + encodings[b] + encodings[c] + '='
|
||||
}
|
||||
|
||||
return base64
|
||||
}
|
||||
|
||||
const createCredentials = (publicKey) => {
|
||||
"use strict";
|
||||
|
||||
prepareOptions(publicKey);
|
||||
|
||||
navigator.credentials.create({publicKey: publicKey})
|
||||
.then(function (newCredentialInfo) {
|
||||
// Send new credential info to server for verification and registration.
|
||||
var cred = {
|
||||
id: newCredentialInfo.id,
|
||||
rawId: base64ArrayBuffer(newCredentialInfo.rawId),
|
||||
response: {
|
||||
clientDataJSON: base64ArrayBuffer(newCredentialInfo.response.clientDataJSON),
|
||||
attestationObject: base64ArrayBuffer(newCredentialInfo.response.attestationObject)
|
||||
},
|
||||
type: newCredentialInfo.type
|
||||
};
|
||||
|
||||
document.getElementById('webauthn').credential.value = JSON.stringify(cred);
|
||||
document.getElementById('webauthn').submit();
|
||||
}).catch(function (err) {
|
||||
console.log('--2--');
|
||||
console.log('WebAuthn create: ' + err);
|
||||
// No acceptable authenticator or user refused consent. Handle appropriately.
|
||||
});
|
||||
}
|
||||
|
||||
const requestCredentials = (publicKey) => {
|
||||
"use strict";
|
||||
console.log('--AB--');
|
||||
|
||||
prepareOptions(publicKey);
|
||||
|
||||
navigator.credentials.get({publicKey: publicKey})
|
||||
.then(function (authenticateInfo) {
|
||||
console.log(authenticateInfo);
|
||||
// Send authenticate info to server for verification.
|
||||
var cred = {
|
||||
id: authenticateInfo.id,
|
||||
rawId: base64ArrayBuffer(authenticateInfo.rawId),
|
||||
response: {
|
||||
authenticatorData: base64ArrayBuffer(authenticateInfo.response.authenticatorData),
|
||||
signature: base64ArrayBuffer(authenticateInfo.response.signature),
|
||||
userHandle: authenticateInfo.response.userHandle,
|
||||
clientDataJSON: base64ArrayBuffer(authenticateInfo.response.clientDataJSON)
|
||||
},
|
||||
type: authenticateInfo.type
|
||||
};
|
||||
console.log(cred);
|
||||
document.getElementById('webauthn').credential.value = JSON.stringify(cred);
|
||||
document.getElementById('webauthn').submit();
|
||||
}).catch(function (err) {
|
||||
console.log('--2--');
|
||||
console.log('WebAuthn auth: ' + err);
|
||||
// No acceptable authenticator or user refused consent. Handle appropriately.
|
||||
});
|
||||
|
||||
}
|
||||
|
37
src/tests/additional.inc.php
Normal file
37
src/tests/additional.inc.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
// Include totp test config
|
||||
|
||||
namespace D3\Totp\tests;
|
||||
|
||||
use D3\ModCfg\Tests\additional_abstract;
|
||||
use OxidEsales\Eshop\Core\Exception\StandardException;
|
||||
|
||||
include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'd3totp_config.php');
|
||||
|
||||
class additional extends additional_abstract
|
||||
{
|
||||
/**
|
||||
* additional constructor.
|
||||
* @throws StandardException
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (D3TOTP_REQUIRE_MODCFG) {
|
||||
$this->reactivateModCfg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oxNew(additional::class);
|
14
src/tests/d3totp_config.php
Normal file
14
src/tests/d3totp_config.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
const D3TOTP_REQUIRE_MODCFG = true;
|
@ -3,7 +3,6 @@
|
||||
namespace D3\Totp\tests\unit\Application\Controller\Admin;
|
||||
|
||||
use D3\Totp\Application\Controller\Admin\d3force_2fa;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
@ -28,7 +27,7 @@ class d3force_2faTest extends d3user_totpTest
|
||||
{
|
||||
$expected = 'fixture';
|
||||
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, $expected);
|
||||
Registry::getSession()->setVariable('auth', $expected);
|
||||
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
@ -65,7 +64,7 @@ class d3force_2faTest extends d3user_totpTest
|
||||
|
||||
Registry::getConfig()->setConfigParam('D3_TOTP_ADMIN_FORCE_2FA', $force2FA);
|
||||
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, $givenUserId);
|
||||
Registry::getSession()->setVariable('auth', $givenUserId);
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
@ -93,7 +92,7 @@ class d3force_2faTest extends d3user_totpTest
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3force_2fa::d3TotpGetSessionObject
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3force_2fa::d3GetSessionObject
|
||||
*/
|
||||
public function testD3GetSessionObject()
|
||||
{
|
||||
@ -101,7 +100,7 @@ class d3force_2faTest extends d3user_totpTest
|
||||
Session::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3TotpGetSessionObject'
|
||||
'd3GetSessionObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -1,654 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Controller\Admin;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Controller\Admin\d3totpadminlogin;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\EshopCommunity\Internal\Framework\Logger\Wrapper\LoggerWrapper;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use ReflectionException;
|
||||
|
||||
class d3totpadminloginTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3totpadminlogin */
|
||||
protected $_oController;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oController = oxNew(d3totpadminlogin::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oController);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::_authorize
|
||||
*/
|
||||
public function testAuthorize()
|
||||
{
|
||||
$this->assertTrue(
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'_authorize'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpGetTotpObject
|
||||
*/
|
||||
public function d3TotpGetTotpObjectReturnsRightInstance()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
d3totp::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3TotpGetTotpObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $hasAuthAlready
|
||||
* @param $totpActive
|
||||
* @param $expected
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::isTotpIsNotRequired
|
||||
* @dataProvider isTotpIsNotRequiredPassedDataProvider
|
||||
*/
|
||||
public function isTotpIsNotRequiredPassed($hasAuthAlready, $totpActive, $expected)
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'isActive',
|
||||
'loadByUserId',
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn($totpActive);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'hasVariable',
|
||||
])
|
||||
->getMock();
|
||||
$hasVariableMap = [
|
||||
[d3totp_conf::SESSION_ADMIN_AUTH, $hasAuthAlready],
|
||||
];
|
||||
$oSessionMock->method('hasVariable')->willReturnMap($hasVariableMap);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods([
|
||||
'd3TotpGetSession',
|
||||
'd3TotpGetTotpObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3TotpGetTotpObject')->willReturn($oTotpMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'isTotpIsNotRequired'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function isTotpIsNotRequiredPassedDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'auth already finished' => [true, true, true],
|
||||
'auth required' => [false, true, false],
|
||||
'totp inactive' => [false, false, true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $userId
|
||||
* @param $expected
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::isTotpLoginNotPossible
|
||||
* @dataProvider isTotpLoginNotPossiblePassedDataProvider
|
||||
*/
|
||||
public function isTotpLoginNotPossiblePassed($userId, $expected)
|
||||
{
|
||||
/** @var d3_totp_user|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['d3TotpGetCurrentUser'])
|
||||
->getMock();
|
||||
$oUserMock->method('d3TotpGetCurrentUser')->willReturn($userId);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods(['d3TotpGetUserObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpGetUserObject')->willReturn($oUserMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'isTotpLoginNotPossible'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function isTotpLoginNotPossiblePassedDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'no user' => [null, true],
|
||||
'has user' => ['userId', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $totpNotRequired
|
||||
* @param $totpNotPossible
|
||||
* @param $redirect
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::render
|
||||
* @dataProvider canRenderDataProvider
|
||||
*/
|
||||
public function canRender($totpNotRequired, $totpNotPossible, $redirect)
|
||||
{
|
||||
/** @var Utils|MockObject $oUtilsMock */
|
||||
$oUtilsMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods(['redirect'])
|
||||
->getMock();
|
||||
$oUtilsMock
|
||||
->expects(is_null($redirect) ? $this->never() : $this->once())
|
||||
->method('redirect')
|
||||
->with($this->identicalTo('index.php?cl='.$redirect))
|
||||
->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $loginControllerMock */
|
||||
$loginControllerMock = $this->getMockBuilder(LoginController::class)
|
||||
->onlyMethods(['d3totpAfterLoginSetLanguage'])
|
||||
->getMock();
|
||||
$loginControllerMock->expects($this->once())->method('d3totpAfterLoginSetLanguage')
|
||||
->willReturn(true);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods([
|
||||
'isTotpIsNotRequired',
|
||||
'isTotpLoginNotPossible',
|
||||
'd3TotpGetUtils',
|
||||
'd3GetLoginController',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('isTotpIsNotRequired')->willReturn($totpNotRequired);
|
||||
$oControllerMock->method('isTotpLoginNotPossible')->willReturn($totpNotPossible);
|
||||
$oControllerMock->method('d3TotpGetUtils')->willReturn($oUtilsMock);
|
||||
$oControllerMock->method('d3GetLoginController')->willReturn($loginControllerMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'render'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function canRenderDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'not required' => [true, false, 'admin_start'],
|
||||
'not possible' => [false, true, 'login'],
|
||||
'do auth' => [false, false, null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3GetBackupCodeListObject
|
||||
*/
|
||||
public function d3GetBackupCodeListObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
d3backupcodelist::class,
|
||||
$this->callMethod($this->_oController, 'd3GetBackupCodeListObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::getBackupCodeCountMessage
|
||||
*/
|
||||
public function getBackupCodeCountMessageShowMessage()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->method('getAvailableCodeCount')->willReturn(2);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods(['d3GetBackupCodeListObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetBackupCodeListObject')->willReturn($oBackupCodeListMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertGreaterThan(
|
||||
0,
|
||||
strpos(
|
||||
$this->callMethod($this->_oController, 'getBackupCodeCountMessage'),
|
||||
' 2 '
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::getBackupCodeCountMessage
|
||||
*/
|
||||
public function getBackupCodeCountMessageDontShowMessage()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->method('getAvailableCodeCount')->willReturn(10);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods(['d3GetBackupCodeListObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetBackupCodeListObject')->willReturn($oBackupCodeListMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertEmpty(
|
||||
$this->callMethod($this->_oController, 'getBackupCodeCountMessage')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3CancelLogin
|
||||
*/
|
||||
public function canCancelLogin()
|
||||
{
|
||||
/** @var d3_totp_user|MockObject $userMock */
|
||||
$userMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['logout'])
|
||||
->getMock();
|
||||
$userMock->expects($this->once())->method('logout')->willReturn(true);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods(['d3TotpGetUserObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpGetUserObject')->willReturn($userMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
'login',
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3CancelLogin'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpGetUserObject
|
||||
*/
|
||||
public function d3GetUserObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$this->callMethod($this->_oController, 'd3TotpGetUserObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::checklogin
|
||||
*/
|
||||
public function checkloginUnvalidTotp()
|
||||
{
|
||||
/** @var LoggerWrapper|MockObject $loggerMock */
|
||||
$loggerMock = $this->getMockBuilder(LoggerWrapper::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['error', 'debug'])
|
||||
->getMock();
|
||||
$loggerMock->expects($this->atLeastOnce())->method('error')->willReturn(true);
|
||||
$loggerMock->expects($this->atLeastOnce())->method('debug')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'initNewSession',
|
||||
'setVariable',
|
||||
'deleteVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->never())->method('initNewSession')->willReturn(false);
|
||||
$oSessionMock->expects($this->never())->method('setVariable')->willReturn(false);
|
||||
$oSessionMock->expects($this->never())->method('deleteVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $loginControllerMock */
|
||||
$loginControllerMock = $this->getMockBuilder(LoginController::class)
|
||||
->onlyMethods(['d3totpAfterLogin'])
|
||||
->getMock();
|
||||
$loginControllerMock->expects($this->never())->method('d3totpAfterLogin')->willReturn(true);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods([
|
||||
'getLogger',
|
||||
'd3TotpHasValidTotp',
|
||||
'd3TotpGetSession',
|
||||
'd3GetLoginController',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpHasValidTotp')
|
||||
->willThrowException(oxNew(d3totp_wrongOtpException::class));
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('getLogger')->willReturn($loggerMock);
|
||||
$oControllerMock->method('d3GetLoginController')->willReturn($loginControllerMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'checklogin'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::checklogin
|
||||
*/
|
||||
public function checkloginValidTotp()
|
||||
{
|
||||
/** @var LoggerWrapper|MockObject $loggerMock */
|
||||
$loggerMock = $this->getMockBuilder(LoggerWrapper::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['error', 'debug'])
|
||||
->getMock();
|
||||
$loggerMock->expects($this->never())->method('error')->willReturn(true);
|
||||
$loggerMock->expects($this->never())->method('debug')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'initNewSession',
|
||||
'setVariable',
|
||||
'deleteVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->atLeastOnce())->method('initNewSession')->willReturn(false);
|
||||
$oSessionMock->expects($this->atLeastOnce())->method('setVariable')->willReturn(false);
|
||||
$oSessionMock->expects($this->atLeastOnce())->method('deleteVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $loginControllerMock */
|
||||
$loginControllerMock = $this->getMockBuilder(LoginController::class)
|
||||
->onlyMethods(['d3totpAfterLogin'])
|
||||
->getMock();
|
||||
$loginControllerMock->expects($this->once())->method('d3totpAfterLogin')->willReturn(true);
|
||||
|
||||
/** @var d3totpadminlogin|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3totpadminlogin::class)
|
||||
->onlyMethods([
|
||||
'getLogger',
|
||||
'd3TotpHasValidTotp',
|
||||
'd3TotpGetSession',
|
||||
'd3GetLoginController',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpHasValidTotp')->willReturn(true);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('getLogger')->willReturn($loggerMock);
|
||||
$oControllerMock->method('d3GetLoginController')->willReturn($loginControllerMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'checklogin'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpHasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueSessionVarname()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($this->_oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpHasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueValidTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(true);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($this->_oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpHasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseMissingTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willThrowException(oxNew(d3totp_wrongOtpException::class));
|
||||
|
||||
$this->expectException(d3totp_wrongOtpException::class);
|
||||
$this->callMethod($this->_oController, 'd3TotpHasValidTotp', [null, $oTotpMock]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpHasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseUnverifiedTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_ADMIN_AUTH, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpGetUtils
|
||||
*/
|
||||
public function d3TotpGetUtilsReturnsRightInstance()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
Utils::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3TotpGetUtils'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3TotpGetSession
|
||||
*/
|
||||
public function d3GetSessionReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3TotpGetSession'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::getLogger
|
||||
*/
|
||||
public function getLoggerReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
LoggerInterface::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'getLogger'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Controller\Admin\d3totpadminlogin::d3GetLoginController
|
||||
*/
|
||||
public function d3GetLoginControllerReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
LoginController::class,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3GetLoginController'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -11,11 +11,8 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Controller\Admin;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Controller\Admin\d3user_totp;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
@ -27,8 +24,6 @@ use ReflectionException;
|
||||
|
||||
class d3user_totpTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3user_totp */
|
||||
protected $_oController;
|
||||
|
||||
@ -84,7 +79,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function canRenderSelectedUser()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
/** @var User|MockObject $oControllerMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods([
|
||||
'getId',
|
||||
@ -123,7 +118,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function canRenderUnloadableUser()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
/** @var User|MockObject $oControllerMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods([
|
||||
'getId',
|
||||
@ -219,13 +214,13 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function cantSaveBecauseOfNotVerifiable()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['save'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->expects($this->never())->method('save')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
/** @var d3totp|MockObject $oControllerMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'load',
|
||||
@ -269,13 +264,13 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function cantSaveBecauseExistingRegistration()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['save'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->expects($this->never())->method('save')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
/** @var d3totp|MockObject $oControllerMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods([
|
||||
@ -319,7 +314,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function canSave()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods([
|
||||
'save',
|
||||
@ -329,7 +324,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
$oBackupCodeListMock->expects($this->once())->method('save')->willReturn(true);
|
||||
$oBackupCodeListMock->method('generateBackupCodes')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
/** @var d3totp|MockObject $oControllerMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'load',
|
||||
@ -378,7 +373,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
];
|
||||
$_GET['editval'] = $aEditval;
|
||||
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods([
|
||||
'save',
|
||||
@ -388,7 +383,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
$oBackupCodeListMock->expects($this->once())->method('save')->willReturn(true);
|
||||
$oBackupCodeListMock->method('generateBackupCodes')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
/** @var d3totp|MockObject $oControllerMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'load',
|
||||
@ -514,7 +509,7 @@ class d3user_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function canGetAvailableBackupCodeCount()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
|
@ -11,11 +11,8 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Controller;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Controller\d3_account_totp;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
@ -27,8 +24,6 @@ use ReflectionException;
|
||||
|
||||
class d3_account_totpTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3_account_totp */
|
||||
protected $_oController;
|
||||
|
||||
@ -88,7 +83,7 @@ class d3_account_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function renderReturnsLoginTemplateIfNotLoggedIn()
|
||||
{
|
||||
$oUser = null;
|
||||
$oUser = false;
|
||||
|
||||
/** @var d3_account_totp|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_account_totp::class)
|
||||
@ -148,7 +143,7 @@ class d3_account_totpTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function canGetAvailableBackupCodeCount()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
/** @var d3backupcodelist|MockObject $oControllerMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
|
@ -11,14 +11,11 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Controller;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Controller\d3totplogin;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
@ -27,8 +24,6 @@ use ReflectionException;
|
||||
|
||||
class d3totploginTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3totplogin */
|
||||
protected $_oController;
|
||||
|
||||
@ -41,8 +36,8 @@ class d3totploginTest extends d3TotpUnitTestCase
|
||||
|
||||
$this->_oController = oxNew(d3totplogin::class);
|
||||
|
||||
Registry::getSession()->deleteVariable(d3totp_conf::SESSION_CURRENTUSER);
|
||||
Registry::getSession()->deleteVariable(d3totp_conf::SESSION_CURRENTCLASS);
|
||||
Registry::getSession()->deleteVariable(d3totp::TOTP_SESSION_CURRENTUSER);
|
||||
Registry::getSession()->deleteVariable(d3totp::TOTP_SESSION_CURRENTCLASS);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
@ -83,7 +78,7 @@ class d3totploginTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function renderDontRedirect()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, 'foo');
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, 'foo');
|
||||
|
||||
/** @var Utils|MockObject $oUtilsMock */
|
||||
$oUtilsMock = $this->getMockBuilder(Utils::class)
|
||||
@ -198,7 +193,7 @@ class d3totploginTest extends d3TotpUnitTestCase
|
||||
public function canGetPreviousClass()
|
||||
{
|
||||
$className = "testClass";
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTCLASS, $className);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTCLASS, $className);
|
||||
|
||||
$this->assertSame(
|
||||
$className,
|
||||
@ -214,7 +209,7 @@ class d3totploginTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function classIsOrderStep($className, $expected)
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTCLASS, $className);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTCLASS, $className);
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
@ -244,7 +239,7 @@ class d3totploginTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function getIsOrderStepIsSameLikeOrderClass($className, $expected)
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTCLASS, $className);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTCLASS, $className);
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
|
@ -11,19 +11,14 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Model\Exceptions;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use ReflectionException;
|
||||
|
||||
class d3totp_wrongOtpExceptionTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3totp_wrongOtpException */
|
||||
protected $_oModel;
|
||||
|
||||
|
@ -11,19 +11,14 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Model;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3RandomGenerator;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use ReflectionException;
|
||||
|
||||
class d3RandomGeneratorTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3RandomGenerator */
|
||||
protected $_oModel;
|
||||
|
||||
|
@ -11,13 +11,10 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Model;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3backupcode;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
@ -26,8 +23,6 @@ use ReflectionException;
|
||||
|
||||
class d3backupcodeTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3backupcode */
|
||||
protected $_oModel;
|
||||
|
||||
@ -114,9 +109,9 @@ class d3backupcodeTest extends d3TotpUnitTestCase
|
||||
|
||||
/** @var d3backupcode|MockObject $oModelMock */
|
||||
$oModelMock = $this->getMockBuilder(d3backupcode::class)
|
||||
->onlyMethods(['d3TotpGetUserObject'])
|
||||
->onlyMethods(['d3GetUserObject'])
|
||||
->getMock();
|
||||
$oModelMock->method('d3TotpGetUserObject')->willReturn($oUserMock);
|
||||
$oModelMock->method('d3GetUserObject')->willReturn($oUserMock);
|
||||
|
||||
$this->_oModel = $oModelMock;
|
||||
|
||||
@ -158,7 +153,7 @@ class d3backupcodeTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function d3GetUserReturnCurrentUser()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, 'foobar');
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, 'foobar');
|
||||
|
||||
$oUser = $this->callMethod($this->_oModel, 'd3GetUser');
|
||||
|
||||
@ -174,13 +169,13 @@ class d3backupcodeTest extends d3TotpUnitTestCase
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Application\Model\d3backupcode::d3TotpGetUserObject
|
||||
* @covers \D3\Totp\Application\Model\d3backupcode::d3GetUserObject
|
||||
*/
|
||||
public function d3getUserObjectReturnsRightInstance()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$this->callMethod($this->_oModel, 'd3TotpGetUserObject')
|
||||
$this->callMethod($this->_oModel, 'd3GetUserObject')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,8 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Model;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3backupcode;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
@ -28,8 +25,6 @@ use ReflectionException;
|
||||
|
||||
class d3backupcodelistTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3backupcodelist */
|
||||
protected $_oModel;
|
||||
|
||||
@ -57,7 +52,7 @@ class d3backupcodelistTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function generateBackupCodes()
|
||||
{
|
||||
/** @var FrontendController|MockObject $oViewMock */
|
||||
/** @var FrontendController|MockObject $oConfigMock */
|
||||
$oViewMock = $this->getMockBuilder(FrontendController::class)
|
||||
->addMethods(['setBackupCodes'])
|
||||
->getMock();
|
||||
|
@ -11,12 +11,9 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Application\Model;
|
||||
|
||||
use BaconQrCode\Writer;
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Factory\BaconQrCodeFactory;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
@ -32,8 +29,6 @@ use stdClass;
|
||||
|
||||
class d3totpTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3totp */
|
||||
protected $_oModel;
|
||||
|
||||
@ -867,7 +862,7 @@ class d3totpTest extends d3TotpUnitTestCase
|
||||
->onlyMethods(['d3Base64_decode'])
|
||||
->getMock();
|
||||
$oModelMock->method('d3Base64_decode')->willReturn(
|
||||
str_pad('foobar', 50, '0', STR_PAD_LEFT)
|
||||
str_pad('foobar', 50, 0, STR_PAD_LEFT)
|
||||
);
|
||||
|
||||
$this->_oModel = $oModelMock;
|
||||
|
@ -11,51 +11,59 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Component;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\Modules\Application\Component\d3_totp_UserComponent;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use InvalidArgumentException;
|
||||
use OxidEsales\Eshop\Application\Component\UserComponent;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Controller\BaseController;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\Eshop\Core\UtilsView;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use ReflectionException;
|
||||
|
||||
class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
/** @var d3_totp_UserComponent */
|
||||
protected $_oController;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oController = oxNew(UserComponent::class);
|
||||
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oController);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::_afterLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::login_noredirect
|
||||
*/
|
||||
public function afterLoginFailsIfNoUserLoggedIn()
|
||||
public function login_noredirectFailsIfNoUserLoggedIn()
|
||||
{
|
||||
$oUser = false;
|
||||
|
||||
/** @var Utils|MockObject $oUtilsMock */
|
||||
$oUtilsMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods(['redirect'])
|
||||
->getMock();
|
||||
$oUtilsMock->expects($this->never())->method('redirect')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
/** @var BaseController|MockObject $oParentMock */
|
||||
$oParentMock = $this->getMockBuilder(BaseController::class)
|
||||
->addMethods(['isEnabledPrivateSales'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->never())->method('setVariable');
|
||||
$oParentMock->method('isEnabledPrivateSales')->willReturn(false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -67,28 +75,28 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'getUser',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
'd3TotpGetUtils',
|
||||
'getParent',
|
||||
])
|
||||
->getMock();
|
||||
|
||||
$oControllerMock->method('getUser')->willReturn($oUser);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3TotpGetUtils')->willReturn($oUtilsMock);
|
||||
$oControllerMock->method('getParent')->willReturn($oParentMock);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$_GET['lgn_usr'] = 'username';
|
||||
|
||||
$this->callMethod($oControllerMock, '_afterLogin', [$oUser]);
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'login_noredirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::_afterLogin
|
||||
* @dataProvider afterLoginFailTotpNotActiveOrAlreadyCheckedDataProvider
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::login_noredirect
|
||||
*/
|
||||
public function afterLoginFailTotpNotActiveOrAlreadyChecked($isActive, $checked)
|
||||
public function login_noredirectFailTotpNotActive()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
@ -100,18 +108,11 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
$oUserMock->expects($this->never())->method('logout')->willReturn(false);
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var Utils|MockObject $oUtilsMock */
|
||||
$oUtilsMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods(['redirect'])
|
||||
->getMock();
|
||||
$oUtilsMock->expects($this->never())->method('redirect')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable', 'getVariable'])
|
||||
/** @var BaseController|MockObject $oParentMock */
|
||||
$oParentMock = $this->getMockBuilder(BaseController::class)
|
||||
->addMethods(['isEnabledPrivateSales'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->never())->method('setVariable');
|
||||
$oSessionMock->method('getVariable')->willReturn($checked);
|
||||
$oParentMock->method('isEnabledPrivateSales')->willReturn(false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -121,42 +122,34 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->expects($this->once())->method('isActive')->willReturn($isActive);
|
||||
$oTotpMock->expects($this->once())->method('isActive')->willReturn(false);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'getUser',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
'd3TotpGetUtils',
|
||||
'getParent',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('getUser')->willReturn($oUserMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3TotpGetUtils')->willReturn($oUtilsMock);
|
||||
$oControllerMock->method('getParent')->willReturn($oParentMock);
|
||||
|
||||
$this->callMethod($oControllerMock, '_afterLogin', [$oUserMock]);
|
||||
}
|
||||
$_GET['lgn_usr'] = 'username';
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function afterLoginFailTotpNotActiveOrAlreadyCheckedDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'TOTP not active, not checked' => [false, null],
|
||||
'TOTP not active, checked' => [false, true],
|
||||
'TOTP active, checked' => [true, true],
|
||||
];
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'login_noredirect');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::_afterLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::login_noredirect
|
||||
*/
|
||||
public function afterLoginPass()
|
||||
public function login_noredirectPass()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
@ -168,24 +161,11 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
$oUserMock->expects($this->once())->method('logout')->willReturn(false);
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var Utils|MockObject $oUtilsMock */
|
||||
$oUtilsMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods(['redirect'])
|
||||
->getMock();
|
||||
$oUtilsMock->expects($this->once())->method('redirect')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable', 'getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->atLeast(3))->method('setVariable');
|
||||
$oSessionMock->method('getVariable')->willReturn(null);
|
||||
|
||||
/** @var BaseController|MockObject $oParentMock */
|
||||
$oParentMock = $this->getMockBuilder(BaseController::class)
|
||||
->onlyMethods(['getClassKey'])
|
||||
->addMethods(['isEnabledPrivateSales'])
|
||||
->getMock();
|
||||
$oParentMock->method('getClassKey')->willReturn('foo');
|
||||
$oParentMock->method('isEnabledPrivateSales')->willReturn(false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -201,18 +181,23 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'getUser',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
'd3TotpGetUtils',
|
||||
'getParent',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('getUser')->willReturn($oUserMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('getParent')->willReturn($oParentMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3TotpGetUtils')->willReturn($oUtilsMock);
|
||||
|
||||
$this->callMethod($oControllerMock, '_afterLogin', [$oUserMock]);
|
||||
$_GET['lgn_usr'] = 'username';
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
'd3totplogin',
|
||||
$this->callMethod($this->_oController, 'login_noredirect')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,19 +207,16 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function d3GetTotpObjectReturnsRightInstance()
|
||||
{
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
d3totp::class,
|
||||
$this->callMethod($oController, 'd3GetTotpObject')
|
||||
$this->callMethod($this->_oController, 'd3GetTotpObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpCheckTotpLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::checkTotplogin
|
||||
*/
|
||||
public function checkTotploginNoTotpLogin()
|
||||
{
|
||||
@ -245,36 +227,32 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->never())->method('setVariable');
|
||||
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'd3TotpIsNoTotpOrNoLogin',
|
||||
'd3TotpHasValidTotp',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'd3TotpRelogin',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpIsNoTotpOrNoLogin')->willReturn(true);
|
||||
$oControllerMock->expects($this->never())->method('d3TotpHasValidTotp')->willReturn(false);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(true);
|
||||
$oControllerMock->expects($this->never())->method('hasValidTotp')->willReturn(false);
|
||||
$oControllerMock->expects($this->never())->method('d3TotpRelogin')->willReturn(false);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
'd3totplogin',
|
||||
$this->callMethod($oControllerMock, 'd3TotpCheckTotpLogin')
|
||||
$this->callMethod($this->_oController, 'checkTotplogin')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpCheckTotpLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::checkTotplogin
|
||||
*/
|
||||
public function checkTotploginUnvalidTotp()
|
||||
{
|
||||
@ -285,13 +263,7 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->never())->method('setVariable');
|
||||
|
||||
/** @var d3totp_wrongOtpException|MockObject $oTotpExceptionMock */
|
||||
/** @var d3totp_wrongOtpException|MockObject $oUtilsViewMock */
|
||||
$oTotpExceptionMock = $this->getMockBuilder(d3totp_wrongOtpException::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
@ -305,29 +277,31 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'd3TotpIsNoTotpOrNoLogin',
|
||||
'd3TotpHasValidTotp',
|
||||
'd3TotpGetUtilsView',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'd3TotpRelogin',
|
||||
'd3GetUtilsView',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpIsNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('d3TotpHasValidTotp')->willThrowException($oTotpExceptionMock);
|
||||
$oControllerMock->method('d3TotpGetUtilsView')->willReturn($oUtilsViewMock);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('hasValidTotp')->willThrowException($oTotpExceptionMock);
|
||||
$oControllerMock->expects($this->never())->method('d3TotpRelogin')->willReturn(false);
|
||||
$oControllerMock->method('d3GetUtilsView')->willReturn($oUtilsViewMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
'd3totplogin',
|
||||
$this->callMethod($oControllerMock, 'd3TotpCheckTotpLogin')
|
||||
$this->callMethod($this->_oController, 'checkTotplogin')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpCheckTotpLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::checkTotplogin
|
||||
*/
|
||||
public function checkTotploginValidTotp()
|
||||
{
|
||||
@ -338,12 +312,6 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->atLeast(2))->method('setVariable');
|
||||
|
||||
/** @var UtilsView|MockObject $oUtilsViewMock */
|
||||
$oUtilsViewMock = $this->getMockBuilder(UtilsView::class)
|
||||
->onlyMethods(['addErrorToDisplay'])
|
||||
@ -353,64 +321,43 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'd3TotpIsNoTotpOrNoLogin',
|
||||
'd3TotpHasValidTotp',
|
||||
'd3TotpGetUtilsView',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'd3TotpRelogin',
|
||||
'd3GetUtilsView',
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSession',
|
||||
'setLoginStatus',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpIsNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('d3TotpHasValidTotp')->willReturn(true);
|
||||
$oControllerMock->method('d3TotpGetUtilsView')->willReturn($oUtilsViewMock);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('hasValidTotp')->willReturn(true);
|
||||
$oControllerMock->expects($this->once())->method('d3TotpRelogin')->willReturn(true);
|
||||
$oControllerMock->method('d3GetUtilsView')->willReturn($oUtilsViewMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->expects($this->once())->method('setLoginStatus')->with(
|
||||
$this->identicalTo(USER_LOGIN_SUCCESS)
|
||||
);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($oControllerMock, 'd3TotpCheckTotpLogin')
|
||||
$this->callMethod($this->_oController, 'checkTotplogin')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpGetUtilsView
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3GetUtilsView
|
||||
*/
|
||||
public function d3GetUtilsViewReturnsRightInstance()
|
||||
{
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
UtilsView::class,
|
||||
$this->callMethod($oController, 'd3TotpGetUtilsView')
|
||||
$this->callMethod($this->_oController, 'd3GetUtilsView')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpGetUtils
|
||||
*/
|
||||
public function d3GetUtilsReturnsRightInstance()
|
||||
{
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Utils::class,
|
||||
$this->callMethod($oController, 'd3TotpGetUtils')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpCancelTotpLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::cancelTotpLogin
|
||||
*/
|
||||
public function canCancelTotpLogin()
|
||||
{
|
||||
@ -420,17 +367,19 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oControllerMock->expects($this->once())->method('d3TotpClearSessionVariables')->willReturn(false);
|
||||
|
||||
$this->callMethod($oControllerMock, 'd3TotpCancelTotpLogin');
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'cancelTotpLogin');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpIsNoTotpOrNoLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginTrueNoSessionVariable()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, false);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -439,22 +388,19 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($oController, 'd3TotpIsNoTotpOrNoLogin', [$oTotpMock])
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpIsNoTotpOrNoLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginTrueTotpNotActive()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, true);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -463,22 +409,19 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($oController, 'd3TotpIsNoTotpOrNoLogin', [$oTotpMock])
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpIsNoTotpOrNoLogin
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginFalse()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_CURRENTUSER, true);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_CURRENTUSER, true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -487,22 +430,19 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($oController, 'd3TotpIsNoTotpOrNoLogin', [$oTotpMock])
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpHasValidTotp
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueSessionVarname()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_AUTH, true);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -511,22 +451,19 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpHasValidTotp
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueValidTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_AUTH, false);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -535,45 +472,40 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpHasValidTotp
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseMissingTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_AUTH, false);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willThrowException(oxNew(d3totp_wrongOtpException::class));
|
||||
$oTotpMock->method('verify')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->expectException(d3totp_wrongOtpException::class);
|
||||
$this->callMethod($oController, 'd3TotpHasValidTotp', [null, $oTotpMock]);
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', [null, $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpHasValidTotp
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseUnverifiedTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::SESSION_AUTH, false);
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -582,14 +514,49 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($oController, 'd3TotpHasValidTotp', ['123456', $oTotpMock])
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpRelogin
|
||||
*/
|
||||
public function d3TotpReloginPass()
|
||||
{
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->atLeast(2))->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['getId'])
|
||||
->getMock();
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods([
|
||||
'd3GetSession',
|
||||
'setUser',
|
||||
'setLoginStatus',
|
||||
'_afterLogin',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->expects($this->once())->method('setUser')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('setLoginStatus')->willReturn(false);
|
||||
$oControllerMock->expects($this->once())->method('_afterLogin')->willReturn(false);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'd3TotpRelogin', [$oUserMock, '123456']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
@ -605,26 +572,25 @@ class d3_totp_UserComponentTest extends d3TotpUnitTestCase
|
||||
|
||||
/** @var UserComponent|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(UserComponent::class)
|
||||
->onlyMethods(['d3TotpGetSession'])
|
||||
->onlyMethods(['d3GetSession'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->callMethod($oControllerMock, 'd3TotpClearSessionVariables');
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'd3TotpClearSessionVariables');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3TotpGetSession
|
||||
* @covers \D3\Totp\Modules\Application\Component\d3_totp_UserComponent::d3GetSession
|
||||
*/
|
||||
public function d3GetSessionReturnsRightInstance()
|
||||
{
|
||||
/** @var d3_totp_UserComponent $oController */
|
||||
$oController = oxNew(UserComponent::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod($oController, 'd3TotpGetSession')
|
||||
$this->callMethod($this->_oController, 'd3GetSession')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -11,28 +11,23 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Controller\Admin;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3backupcodelist;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
|
||||
use D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
|
||||
use Exception;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Language;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\UtilsServer;
|
||||
use OxidEsales\Eshop\Core\UtilsView;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use ReflectionException;
|
||||
|
||||
class d3_totp_LoginControllerTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3_totp_LoginController */
|
||||
protected $_oController;
|
||||
|
||||
@ -53,6 +48,186 @@ class d3_totp_LoginControllerTest extends d3TotpUnitTestCase
|
||||
unset($this->_oController);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::render
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getViewDataElement
|
||||
*/
|
||||
public function canRenderNoAuth()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'isActive',
|
||||
'loadByUserId',
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->expects($this->never())->method('isActive')->willReturn(false);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'getVariable',
|
||||
'setVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->will($this->onConsecutiveCalls(false, true));
|
||||
$oSessionMock->expects($this->never())->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3GetSession',
|
||||
'd3GetTotpObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame('login.tpl', $this->callMethod($this->_oController, 'render'));
|
||||
$this->assertNotTrue($this->callMethod($this->_oController, 'getViewDataElement', ['request_totp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::render
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getViewDataElement
|
||||
*/
|
||||
public function canRenderTotpNotActive()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods([
|
||||
'isActive',
|
||||
'loadByUserId',
|
||||
])
|
||||
->getMock();
|
||||
$oTotpMock->expects($this->once())->method('isActive')->willReturn(false);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'getVariable',
|
||||
'setVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->will($this->onConsecutiveCalls(true, true));
|
||||
$oSessionMock->expects($this->never())->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3GetSession',
|
||||
'd3GetTotpObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame('login.tpl', $this->callMethod($this->_oController, 'render'));
|
||||
$this->assertNotTrue($this->callMethod($this->_oController, 'getViewDataElement', ['request_totp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::render
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getViewDataElement
|
||||
*/
|
||||
public function canRenderInTotpLoginProcess()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'isActive',
|
||||
'loadByUserId',
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->expects($this->once())->method('isActive')->willReturn(false);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'getVariable',
|
||||
'setVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->will($this->onConsecutiveCalls(true, true));
|
||||
$oSessionMock->expects($this->never())->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3GetSession',
|
||||
'd3GetTotpObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame('login.tpl', $this->callMethod($this->_oController, 'render'));
|
||||
$this->assertNotTrue($this->callMethod($this->_oController, 'getViewDataElement', ['request_totp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::render
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getViewDataElement
|
||||
*/
|
||||
public function canRenderRequestTotp()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods([
|
||||
'isActive',
|
||||
'loadByUserId',
|
||||
])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->expects($this->once())->method('isActive')->willReturn(true);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods([
|
||||
'getVariable',
|
||||
'setVariable',
|
||||
])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->will($this->onConsecutiveCalls(true, false));
|
||||
$oSessionMock->expects($this->once())->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3GetSession',
|
||||
'd3GetTotpObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame('login.tpl', $this->callMethod($this->_oController, 'render'));
|
||||
$this->assertTrue($this->callMethod($this->_oController, 'getViewDataElement', ['request_totp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
@ -69,13 +244,39 @@ class d3_totp_LoginControllerTest extends d3TotpUnitTestCase
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3TotpGetSession
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3GetBackupCodeListObject
|
||||
*/
|
||||
public function d3GetBackupCodeListObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
d3backupcodelist::class,
|
||||
$this->callMethod($this->_oController, 'd3GetBackupCodeListObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3GetUtilsView
|
||||
*/
|
||||
public function d3GetUtilsViewReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
UtilsView::class,
|
||||
$this->callMethod($this->_oController, 'd3GetUtilsView')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3GetSession
|
||||
*/
|
||||
public function d3GetSessionReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod($this->_oController, 'd3TotpGetSession')
|
||||
$this->callMethod($this->_oController, 'd3GetSession')
|
||||
);
|
||||
}
|
||||
|
||||
@ -83,21 +284,47 @@ class d3_totp_LoginControllerTest extends d3TotpUnitTestCase
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::checklogin
|
||||
* @dataProvider checkloginNoTotpDataProvider
|
||||
*/
|
||||
public function canChecklogin()
|
||||
public function checkloginNoTotp($hasLoginCredentials)
|
||||
{
|
||||
$fixture = 'returnString';
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3CallMockableFunction'])
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'hasLoginCredentials',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3CallMockableFunction')->willReturn($fixture);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(true);
|
||||
$oControllerMock->method('hasValidTotp')->willReturn(false);
|
||||
$oControllerMock->method('hasLoginCredentials')->willReturn($hasLoginCredentials);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
if ($hasLoginCredentials) {
|
||||
// workaround, because test case runs into parent call, stop execution with exception and check thrown
|
||||
/** @var Session|MockObject $sessionMock */
|
||||
$sessionMock = $this->getMockBuilder(Session::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['initNewSession'])
|
||||
->getMock();
|
||||
$sessionMock->method('initNewSession')->willThrowException(new Exception('foo'));
|
||||
Registry::set(Session::class, $sessionMock);
|
||||
$this->expectException(Exception::class);
|
||||
}
|
||||
|
||||
$this->assertSame(
|
||||
$fixture,
|
||||
'login',
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'checklogin'
|
||||
@ -105,202 +332,417 @@ class d3_totp_LoginControllerTest extends d3TotpUnitTestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param $selectedProfile
|
||||
* @param $setCookie
|
||||
* @param $expectedCookie
|
||||
* @param $setSession
|
||||
*
|
||||
* @throws ReflectionException
|
||||
* @dataProvider canRunTotpAfterLoginDataProvider
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3totpAfterLogin
|
||||
*/
|
||||
public function canRunTotpAfterLogin($selectedProfile, $setCookie, $expectedCookie, $setSession)
|
||||
{
|
||||
/** @var Session|MockObject $sessionMock */
|
||||
$sessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable', 'setVariable'])
|
||||
->getMock();
|
||||
$variableMap = [
|
||||
[d3totp_conf::SESSION_ADMIN_PROFILE, $selectedProfile],
|
||||
['aAdminProfiles', [
|
||||
0 => ['abc', 0],
|
||||
1 => ['def', 1],
|
||||
2 => ['geh', 2],
|
||||
]],
|
||||
];
|
||||
$sessionMock->method('getVariable')->willReturnMap($variableMap);
|
||||
$sessionMock->expects($setSession)->method('setVariable')->willReturnMap($variableMap);
|
||||
|
||||
/** @var UtilsServer|MockObject $utilsServerMock */
|
||||
$utilsServerMock = $this->getMockBuilder(UtilsServer::class)
|
||||
->onlyMethods(['setOxCookie'])
|
||||
->getMock();
|
||||
$utilsServerMock->expects($setCookie)->method('setOxCookie')->with(
|
||||
$this->anything(),
|
||||
$expectedCookie
|
||||
);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $sut */
|
||||
$sut = $this->getMockBuilder(LoginController::class)
|
||||
->onlyMethods(['d3TotpGetUtilsServer', 'd3TotpGetSession', 'd3totpAfterLoginSetLanguage'])
|
||||
->getMock();
|
||||
$sut->method('d3TotpGetUtilsServer')->willReturn($utilsServerMock);
|
||||
$sut->method('d3TotpGetSession')->willReturn($sessionMock);
|
||||
$sut->expects($this->once())->method('d3totpAfterLoginSetLanguage')->willReturn($sessionMock);
|
||||
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3totpAfterLogin'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function canRunTotpAfterLoginDataProvider(): array
|
||||
public function checkloginNoTotpDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'no profile selected' => [null, $this->once(), '', $this->never()],
|
||||
'valid profile selected' => [2, $this->once(), '2@geh@2', $this->once()],
|
||||
'invalid profile selected' => [5, $this->never(), false, $this->never()],
|
||||
'no totp, no login credentials' => [false],
|
||||
'no totp, given login credentials' => [true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3totpAfterLoginSetLanguage
|
||||
* @dataProvider canRunTotpAfterLoginSetLanguageDataProvider
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::checklogin
|
||||
*/
|
||||
public function canRunTotpAfterLoginSetLanguage($languageId)
|
||||
public function checkloginInvalidTotp()
|
||||
{
|
||||
/** @var Session|MockObject $sessionMock */
|
||||
$sessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$sessionMock->method('getVariable')->willReturn($languageId);
|
||||
|
||||
/** @var UtilsServer|MockObject $utilsServerMock */
|
||||
$utilsServerMock = $this->getMockBuilder(UtilsServer::class)
|
||||
->onlyMethods(['setOxCookie'])
|
||||
/** @var d3totp_wrongOtpException|MockObject $oUtilsViewMock */
|
||||
$oTotpExceptionMock = $this->getMockBuilder(d3totp_wrongOtpException::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$utilsServerMock->expects($this->once())->method('setOxCookie');
|
||||
|
||||
/** @var Language|MockObject $langMock */
|
||||
$langMock = $this->getMockBuilder(Language::class)
|
||||
->onlyMethods(['setTplLanguage'])
|
||||
/** @var UtilsView|MockObject $utilsViewMock */
|
||||
$utilsViewMock = $this->getMockBuilder(UtilsView::class)
|
||||
->onlyMethods(['addErrorToDisplay'])
|
||||
->getMock();
|
||||
$langMock->expects($this->once())->method('setTplLanguage');
|
||||
$utilsViewMock->expects($this->once())->method('addErrorToDisplay')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $sut */
|
||||
$sut = $this->getMockBuilder(LoginController::class)
|
||||
->onlyMethods(['d3TotpGetUtilsServer', 'd3TotpGetSession', 'd3TotpGetLangObject'])
|
||||
->getMock();
|
||||
$sut->method('d3TotpGetUtilsServer')->willReturn($utilsServerMock);
|
||||
$sut->method('d3TotpGetSession')->willReturn($sessionMock);
|
||||
$sut->method('d3TotpGetLangObject')->willReturn($langMock);
|
||||
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3totpAfterLoginSetlanguage'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function canRunTotpAfterLoginSetLanguageDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'existing language' => [0],
|
||||
'not existing language' => [50],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $totpActive
|
||||
* @param $loggedin
|
||||
* @param $expected
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3TotpLoginMissing
|
||||
* @dataProvider d3TotpLoginMissingTestDataProvider
|
||||
*/
|
||||
public function d3TotpLoginMissingTest($totpActive, $loggedin, $expected)
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['isActive'])
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn($totpActive);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->with(d3totp_conf::SESSION_ADMIN_AUTH)->willReturn($loggedin);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3TotpGetSession',
|
||||
'd3GetTotpObject',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'd3GetUtilsView',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->method('hasValidTotp')->willThrowException($oTotpExceptionMock);
|
||||
$oControllerMock->method('d3GetUtilsView')->willReturn($utilsViewMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'd3TotpLoginMissing',
|
||||
[$oTotpMock]
|
||||
'login',
|
||||
$this->callMethod($this->_oController, 'checklogin')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::checklogin
|
||||
*/
|
||||
public function checkloginValidTotp()
|
||||
{
|
||||
/** @var UtilsView|MockObject $utilsViewMock */
|
||||
$utilsViewMock = $this->getMockBuilder(UtilsView::class)
|
||||
->onlyMethods(['addErrorToDisplay'])
|
||||
->getMock();
|
||||
$utilsViewMock->expects($this->never())->method('addErrorToDisplay')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['setVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->once())->method('setVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'isNoTotpOrNoLogin',
|
||||
'hasValidTotp',
|
||||
'd3GetUtilsView',
|
||||
'd3GetSession',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('isNoTotpOrNoLogin')->willReturn(false);
|
||||
$oControllerMock->method('hasValidTotp')->willReturn(true);
|
||||
$oControllerMock->method('d3GetUtilsView')->willReturn($utilsViewMock);
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertSame('admin_start', $this->callMethod($this->_oController, 'checklogin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getBackupCodeCountMessage
|
||||
*/
|
||||
public function getBackupCodeCountMessageShowMessage()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->method('getAvailableCodeCount')->willReturn(2);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetBackupCodeListObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetBackupCodeListObject')->willReturn($oBackupCodeListMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertGreaterThan(
|
||||
0,
|
||||
strpos(
|
||||
$this->callMethod($this->_oController, 'getBackupCodeCountMessage'),
|
||||
' 2 '
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::getBackupCodeCountMessage
|
||||
*/
|
||||
public function d3TotpLoginMissingTestDataProvider(): array
|
||||
public function getBackupCodeCountMessageDontShowMessage()
|
||||
{
|
||||
/** @var d3backupcodelist|MockObject $oBackupCodeListMock */
|
||||
$oBackupCodeListMock = $this->getMockBuilder(d3backupcodelist::class)
|
||||
->onlyMethods(['getAvailableCodeCount'])
|
||||
->getMock();
|
||||
$oBackupCodeListMock->method('getAvailableCodeCount')->willReturn(10);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetBackupCodeListObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetBackupCodeListObject')->willReturn($oBackupCodeListMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertEmpty(
|
||||
$this->callMethod($this->_oController, 'getBackupCodeCountMessage')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginIsAuth()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['isActive'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetSession'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginTotpNotActive()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['isActive'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetSession'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::isNoTotpOrNoLogin
|
||||
*/
|
||||
public function isNoTotpOrNoLoginPass()
|
||||
{
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['isActive'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('isActive')->willReturn(false);
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->method('getVariable')->willReturn(false);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetSession'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($this->_oController, 'isNoTotpOrNoLogin', [$oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueSessionVarname()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, true);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpTrueValidTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(true);
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseMissingTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(true);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', [null, $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::hasValidTotp
|
||||
*/
|
||||
public function hasValidTotpFalseUnverifiedTotp()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['verify'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$oTotpMock->method('verify')->willReturn(false);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($this->_oController, 'hasValidTotp', ['123456', $oTotpMock])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3CancelLogin
|
||||
*/
|
||||
public function d3CancelLoginPass()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['logout'])
|
||||
->getMock();
|
||||
$oUserMock->expects($this->once())->method('logout')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_LoginController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder(d3_totp_LoginController::class)
|
||||
->onlyMethods(['d3GetUserObject'])
|
||||
->getMock();
|
||||
$oControllerMock->method('d3GetUserObject')->willReturn($oUserMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->callMethod($this->_oController, 'd3CancelLogin');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3GetUserObject
|
||||
*/
|
||||
public function d3GetUserObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$this->callMethod($this->_oController, 'd3GetUserObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @dataProvider hasLoginCredentialsDataProvider
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::hasLoginCredentials
|
||||
*/
|
||||
public function hasLoginCredentials($user, $pass, $expected)
|
||||
{
|
||||
$_GET['user'] = $user;
|
||||
$_GET['pwd'] = $pass;
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$this->_oController,
|
||||
'hasLoginCredentials'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function hasLoginCredentialsDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'totp not active, not logged in'=> [false, false, false],
|
||||
'totp active, logged in' => [true, true, false],
|
||||
'totp active, not logged in' => [true, false, true],
|
||||
'totp not active, logged in' => [false, true, false],
|
||||
'user only' => ['user', null, false],
|
||||
'pass only' => [null, 'password', false],
|
||||
'both' => ['user', 'password', true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3TotpGetUtilsServer
|
||||
*/
|
||||
public function d3GetUtilsServerObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
UtilsServer::class,
|
||||
$this->callMethod($this->_oController, 'd3TotpGetUtilsServer')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\Admin\d3_totp_LoginController::d3TotpGetLangObject
|
||||
*/
|
||||
public function d3GetLangObjectReturnsRightObject()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
Language::class,
|
||||
$this->callMethod($this->_oController, 'd3TotpGetLangObject')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,9 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Controller;
|
||||
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_OrderController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_OrderController_parent;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Application\Controller\OrderController;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
@ -25,5 +22,25 @@ class d3_totp_OrderControllerTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use d3_totp_getUserTestTrait;
|
||||
|
||||
/** @var d3_totp_OrderController|MockObject */
|
||||
protected $_oController;
|
||||
|
||||
protected $sControllerClass = OrderController::class;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oController = oxNew(OrderController::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oController);
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Controller;
|
||||
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_PaymentController;
|
||||
@ -23,5 +21,25 @@ class d3_totp_PaymentControllerTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use d3_totp_getUserTestTrait;
|
||||
|
||||
/** @var d3_totp_PaymentController */
|
||||
protected $_oController;
|
||||
|
||||
protected $sControllerClass = PaymentController::class;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oController = oxNew(PaymentController::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oController);
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Controller;
|
||||
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_UserController;
|
||||
@ -23,5 +21,25 @@ class d3_totp_UserControllerTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use d3_totp_getUserTestTrait;
|
||||
|
||||
/** @var d3_totp_UserController */
|
||||
protected $_oController;
|
||||
|
||||
protected $sControllerClass = UserController::class;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oController = oxNew(UserController::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oController);
|
||||
}
|
||||
}
|
||||
|
@ -11,15 +11,10 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Controller;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_OrderController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_PaymentController;
|
||||
use D3\Totp\Modules\Application\Controller\d3_totp_UserController;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
@ -27,27 +22,6 @@ use ReflectionException;
|
||||
|
||||
trait d3_totp_getUserTestTrait
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
protected $userFixtureId = 'userIdFixture1';
|
||||
|
||||
/** @var User */
|
||||
protected $userFixture;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->userFixture = oxNew(User::class);
|
||||
$this->userFixture->setId($this->userFixtureId);
|
||||
$this->userFixture->assign(['oxlname' => __METHOD__]);
|
||||
$this->userFixture->save();
|
||||
$this->userFixture->load($this->userFixtureId);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$this->userFixture->delete($this->userFixtureId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
@ -57,14 +31,16 @@ trait d3_totp_getUserTestTrait
|
||||
*/
|
||||
public function getUserHasNoUser()
|
||||
{
|
||||
/** @var d3_totp_orderController|d3_totp_UserController|d3_totp_PaymentController|MockObject $oControllerMock */
|
||||
/** @var d3_totp_orderController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder($this->sControllerClass)
|
||||
->onlyMethods(['d3GetTotpObject'])
|
||||
->getMock();
|
||||
$oControllerMock->expects($this->never())->method('d3GetTotpObject');
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($oControllerMock, 'getUser')
|
||||
$this->callMethod($this->_oController, 'getUser')
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,6 +53,12 @@ trait d3_totp_getUserTestTrait
|
||||
*/
|
||||
public function getUserTotpNotActive()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['getId'])
|
||||
->getMock();
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
@ -94,23 +76,24 @@ trait d3_totp_getUserTestTrait
|
||||
$oTotpMock->method('isActive')->willReturn(false);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_orderController|d3_totp_UserController|d3_totp_PaymentController|MockObject $oControllerMock */
|
||||
/** @var d3_totp_orderController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder($this->sControllerClass)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSessionObject',
|
||||
'd3GetSessionObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->expects($this->once())->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSessionObject')->willReturn($oSessionMock);
|
||||
$oControllerMock->setUser($this->userFixture);
|
||||
$oControllerMock->method('d3GetSessionObject')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->setValue($this->_oController, '_oActUser', $oUserMock);
|
||||
|
||||
$this->assertSame(
|
||||
$this->userFixture,
|
||||
$this->callMethod($oControllerMock, 'getUser')
|
||||
$oUserMock,
|
||||
$this->callMethod($this->_oController, 'getUser')
|
||||
);
|
||||
|
||||
$oControllerMock->setUser(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,6 +105,12 @@ trait d3_totp_getUserTestTrait
|
||||
*/
|
||||
public function getUserTotpFinished()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['getId'])
|
||||
->getMock();
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
@ -138,23 +127,24 @@ trait d3_totp_getUserTestTrait
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_orderController|d3_totp_UserController|d3_totp_PaymentController|MockObject $oControllerMock */
|
||||
/** @var d3_totp_orderController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder($this->sControllerClass)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSessionObject',
|
||||
'd3GetSessionObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->expects($this->once())->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSessionObject')->willReturn($oSessionMock);
|
||||
$oControllerMock->setUser($this->userFixture);
|
||||
$oControllerMock->method('d3GetSessionObject')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->setValue($this->_oController, '_oActUser', $oUserMock);
|
||||
|
||||
$this->assertSame(
|
||||
$this->userFixture,
|
||||
$this->callMethod($oControllerMock, 'getUser')
|
||||
$oUserMock,
|
||||
$this->callMethod($this->_oController, 'getUser')
|
||||
);
|
||||
|
||||
$oControllerMock->setUser(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,6 +156,12 @@ trait d3_totp_getUserTestTrait
|
||||
*/
|
||||
public function getUserTotpNotFinished()
|
||||
{
|
||||
/** @var User|MockObject $oUserMock */
|
||||
$oUserMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['getId'])
|
||||
->getMock();
|
||||
$oUserMock->method('getId')->willReturn('foo');
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
@ -183,22 +179,23 @@ trait d3_totp_getUserTestTrait
|
||||
$oTotpMock->method('isActive')->willReturn(true);
|
||||
$oTotpMock->method('loadByUserId')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_orderController|d3_totp_UserController|d3_totp_PaymentController|MockObject $oControllerMock */
|
||||
/** @var d3_totp_orderController|MockObject $oControllerMock */
|
||||
$oControllerMock = $this->getMockBuilder($this->sControllerClass)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSessionObject',
|
||||
'd3GetSessionObject',
|
||||
])
|
||||
->getMock();
|
||||
$oControllerMock->expects($this->once())->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oControllerMock->method('d3TotpGetSessionObject')->willReturn($oSessionMock);
|
||||
$oControllerMock->setUser($this->userFixture);
|
||||
$oControllerMock->method('d3GetSessionObject')->willReturn($oSessionMock);
|
||||
|
||||
$this->_oController = $oControllerMock;
|
||||
|
||||
$this->setValue($this->_oController, '_oActUser', $oUserMock);
|
||||
|
||||
$this->assertFalse(
|
||||
$this->callMethod($oControllerMock, 'getUser')
|
||||
$this->callMethod($this->_oController, 'getUser')
|
||||
);
|
||||
|
||||
$oControllerMock->setUser(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,32 +207,26 @@ trait d3_totp_getUserTestTrait
|
||||
*/
|
||||
public function d3GetTotpObjectReturnsRightObject()
|
||||
{
|
||||
/** @var d3_totp_UserController|d3_totp_PaymentController|d3_totp_OrderController $oController */
|
||||
$oController = oxNew($this->sControllerClass);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
d3totp::class,
|
||||
$this->callMethod($oController, 'd3GetTotpObject')
|
||||
$this->callMethod($this->_oController, 'd3GetTotpObject')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_OrderController::d3TotpGetSessionObject
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_PaymentController::d3TotpGetSessionObject
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_UserController::d3TotpGetSessionObject
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_OrderController::d3GetSessionObject
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_PaymentController::d3GetSessionObject
|
||||
* @covers \D3\Totp\Modules\Application\Controller\d3_totp_UserController::d3GetSessionObject
|
||||
*/
|
||||
public function d3GetSessionObjectReturnsRightObject()
|
||||
{
|
||||
/** @var d3_totp_UserController|d3_totp_PaymentController|d3_totp_OrderController $oController */
|
||||
$oController = oxNew($this->sControllerClass);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod(
|
||||
$oController,
|
||||
'd3TotpGetSessionObject'
|
||||
$this->_oController,
|
||||
'd3GetSessionObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -11,13 +11,9 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Application\Model;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
@ -27,7 +23,25 @@ use ReflectionException;
|
||||
|
||||
class d3_totp_userTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
/** @var d3_totp_user */
|
||||
protected $_oModel;
|
||||
|
||||
/**
|
||||
* setup basic requirements
|
||||
*/
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->_oModel = oxNew(User::class);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
unset($this->_oModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -40,19 +54,19 @@ class d3_totp_userTest extends d3TotpUnitTestCase
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['deleteVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->atLeast(2))->method('deleteVariable')->willReturn(true);
|
||||
$oSessionMock->expects($this->once())->method('deleteVariable')->willReturn(true);
|
||||
|
||||
/** @var d3_totp_user|MockObject $oModelMock */
|
||||
$oModelMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['d3TotpGetSession'])
|
||||
->onlyMethods(['d3GetSession'])
|
||||
->getMock();
|
||||
$oModelMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oModelMock->method('d3GetSession')->willReturn($oSessionMock);
|
||||
|
||||
$sut = $oModelMock;
|
||||
$this->_oModel = $oModelMock;
|
||||
|
||||
$this->assertTrue(
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
$this->_oModel,
|
||||
'logout'
|
||||
)
|
||||
);
|
||||
@ -65,90 +79,22 @@ class d3_totp_userTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function d3getTotpReturnsRightInstance()
|
||||
{
|
||||
$sut = oxNew(User::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
d3totp::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3getTotp'
|
||||
)
|
||||
$this->callMethod($this->_oModel, 'd3getTotp')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Model\d3_totp_user::d3TotpGetSession
|
||||
* @covers \D3\Totp\Modules\Application\Model\d3_totp_user::d3GetSession
|
||||
*/
|
||||
public function d3GetSessionReturnsRightInstance()
|
||||
{
|
||||
$sut = oxNew(User::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3TotpGetSession'
|
||||
)
|
||||
$this->callMethod($this->_oModel, 'd3GetSession')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $currentUser
|
||||
* @param $isAdmin
|
||||
* @param $adminAuth
|
||||
* @param $frontendAuth
|
||||
* @param $expected
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Application\Model\d3_totp_user::d3TotpGetCurrentUser
|
||||
* @dataProvider d3TotpGetCurrentUserTestDataProvider
|
||||
*/
|
||||
public function d3TotpGetCurrentUserTest($currentUser, $isAdmin, $adminAuth, $frontendAuth, $expected)
|
||||
{
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['hasVariable', 'getVariable'])
|
||||
->getMock();
|
||||
$oSessionMock->expects($this->once())->method('hasVariable')->willReturn((bool) $currentUser);
|
||||
$getVariableMap = [
|
||||
[d3totp_conf::SESSION_CURRENTUSER, $currentUser],
|
||||
[d3totp_conf::SESSION_ADMIN_CURRENTUSER, $currentUser],
|
||||
[d3totp_conf::OXID_ADMIN_AUTH, $adminAuth],
|
||||
[d3totp_conf::OXID_FRONTEND_AUTH, $frontendAuth],
|
||||
];
|
||||
$oSessionMock->method('getVariable')->willReturnMap($getVariableMap);
|
||||
|
||||
/** @var d3_totp_user|MockObject $oModelMock */
|
||||
$oModelMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['d3TotpGetSession', 'isAdmin'])
|
||||
->getMock();
|
||||
$oModelMock->method('d3TotpGetSession')->willReturn($oSessionMock);
|
||||
$oModelMock->method('isAdmin')->willReturn($isAdmin);
|
||||
|
||||
$sut = $oModelMock;
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3TotpGetCurrentUser'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array[]
|
||||
*/
|
||||
public function d3TotpGetCurrentUserTestDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'adm login request' => ['currentFixture', true, 'adminFixture', 'frontendFixture', 'currentFixture'],
|
||||
'frnt login request' => ['currentFixture', false, 'adminFixture', 'frontendFixture', 'currentFixture'],
|
||||
'admin auth' => [null, true, 'adminFixture', 'frontendFixture', 'adminFixture'],
|
||||
'frontend auth' => [null, false, 'adminFixture', 'frontendFixture', 'frontendFixture'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,9 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit\Modules\Core;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Application\Model\d3totp_conf;
|
||||
use D3\Totp\Modules\Core\d3_totp_utils;
|
||||
use D3\Totp\tests\unit\d3TotpUnitTestCase;
|
||||
use OxidEsales\Eshop\Core\Config;
|
||||
@ -29,8 +25,6 @@ use ReflectionException;
|
||||
|
||||
class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/** @var d3_totp_utils */
|
||||
protected $_oCoreClass;
|
||||
|
||||
@ -58,7 +52,7 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function checkAccessRightsNoAuth()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, false);
|
||||
Registry::getSession()->setVariable("auth", false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -91,7 +85,7 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function checkAccessRightsForce2FA()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, false);
|
||||
Registry::getSession()->setVariable("auth", false);
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -128,7 +122,7 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function checkAccessRightsTotpNotActive()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, 'foo');
|
||||
Registry::getSession()->setVariable("auth", 'foo');
|
||||
|
||||
/** @var d3totp|MockObject $oTotpMock */
|
||||
$oTotpMock = $this->getMockBuilder(d3totp::class)
|
||||
@ -165,7 +159,7 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function checkAccessRightsTotpFinished()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, 'foo');
|
||||
Registry::getSession()->setVariable("auth", 'foo');
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
@ -188,13 +182,13 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
$oCoreMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSessionObject',
|
||||
'd3GetSessionObject',
|
||||
'fetchRightsForUser',
|
||||
'redirect',
|
||||
])
|
||||
->getMock();
|
||||
$oCoreMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oCoreMock->method('d3TotpGetSessionObject')->willReturn($oSessionMock);
|
||||
$oCoreMock->method('d3GetSessionObject')->willReturn($oSessionMock);
|
||||
$oCoreMock->method('fetchRightsForUser')->willReturn('malladmin');
|
||||
$oCoreMock->expects($this->never())->method('redirect')->willReturn(true);
|
||||
|
||||
@ -212,7 +206,7 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
*/
|
||||
public function checkAccessRightsTotpUnfinished()
|
||||
{
|
||||
Registry::getSession()->setVariable(d3totp_conf::OXID_ADMIN_AUTH, 'foo');
|
||||
Registry::getSession()->setVariable("auth", 'foo');
|
||||
|
||||
/** @var Session|MockObject $oSessionMock */
|
||||
$oSessionMock = $this->getMockBuilder(Session::class)
|
||||
@ -241,13 +235,13 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
$oCoreMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods([
|
||||
'd3GetTotpObject',
|
||||
'd3TotpGetSessionObject',
|
||||
'd3GetSessionObject',
|
||||
'fetchRightsForUser',
|
||||
'redirect',
|
||||
])
|
||||
->getMock();
|
||||
$oCoreMock->method('d3GetTotpObject')->willReturn($oTotpMock);
|
||||
$oCoreMock->method('d3TotpGetSessionObject')->willReturn($oSessionMock);
|
||||
$oCoreMock->method('d3GetSessionObject')->willReturn($oSessionMock);
|
||||
$oCoreMock->method('fetchRightsForUser')->willReturn('malladmin');
|
||||
$oCoreMock->expects($this->once())->method('redirect')->willReturn(true);
|
||||
|
||||
@ -259,13 +253,13 @@ class d3_totp_utilsTest extends d3TotpUnitTestCase
|
||||
/**
|
||||
* @test
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\d3_totp_utils::d3TotpGetSessionObject
|
||||
* @covers \D3\Totp\Modules\Core\d3_totp_utils::d3GetSessionObject
|
||||
*/
|
||||
public function d3GetSessionObjectReturnsRightInstance()
|
||||
{
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod($this->_oCoreClass, 'd3TotpGetSessionObject')
|
||||
$this->callMethod($this->_oCoreClass, 'd3GetSessionObject')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,253 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* https://www.d3data.de
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace unit\Modules\Core;
|
||||
|
||||
use D3\TestingTools\Development\CanAccessRestricted;
|
||||
use D3\Totp\Application\Model\d3totp;
|
||||
use D3\Totp\Modules\Application\Model\d3_totp_user;
|
||||
use D3\Totp\Modules\Core\totpSystemEventHandler;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use OxidEsales\Eshop\Core\SystemEventHandler;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use OxidEsales\TestingLibrary\UnitTestCase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use ReflectionException;
|
||||
|
||||
class totpSystemEventHandlerTest extends UnitTestCase
|
||||
{
|
||||
use CanAccessRestricted;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::onAdminLogin
|
||||
*/
|
||||
public function runOnAdminLogin()
|
||||
{
|
||||
/** @var totpSystemEventHandler|MockObject $sut */
|
||||
$sut = $this->getMockBuilder(SystemEventHandler::class)
|
||||
->onlyMethods(['d3CallMockableFunction', 'd3requestTotp'])
|
||||
->getMock();
|
||||
|
||||
$sut->method('d3CallMockableFunction')->willReturn(true);
|
||||
$sut->expects($this->once())->method('d3requestTotp')->willReturn(true);
|
||||
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'onAdminLogin'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @param $totpMissing
|
||||
* @param $doLogout
|
||||
* @param $doRedirect
|
||||
*
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @dataProvider canRequestTotpDataProvider
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::d3requestTotp
|
||||
*/
|
||||
public function canRequestTotp($totpMissing, $doLogout, $doRedirect)
|
||||
{
|
||||
/** @var Session|MockObject $sessionMock */
|
||||
$sessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$sessionMock->method('getVariable')->willReturn('myUserId');
|
||||
|
||||
/** @var d3_totp_user|MockObject $userMock */
|
||||
$userMock = $this->getMockBuilder(User::class)
|
||||
->onlyMethods(['logout'])
|
||||
->getMock();
|
||||
$userMock->expects($doLogout)->method('logout')->willReturn(true);
|
||||
|
||||
/** @var Utils|MockObject $utilsMock */
|
||||
$utilsMock = $this->getMockBuilder(Utils::class)
|
||||
->onlyMethods(['redirect'])
|
||||
->getMock();
|
||||
$utilsMock->expects($doRedirect)->method('redirect')->willReturn(true);
|
||||
|
||||
/** @var d3totp|MockObject $totpMock */
|
||||
$totpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['loadByUserId'])
|
||||
->getMock();
|
||||
$totpMock->expects($this->atLeastOnce())->method('loadByUserId')->with('myUserId')->willReturn(1);
|
||||
|
||||
/** @var totpSystemEventHandler|MockObject $sut */
|
||||
$sut = $this->getMockBuilder(SystemEventHandler::class)
|
||||
->onlyMethods(['d3GetTotpObject', 'd3TotpGetSession', 'd3TotpLoginMissing',
|
||||
'd3TotpGetUserObject', 'getUtilsObject', ])
|
||||
->getMock();
|
||||
$sut->method('d3GetTotpObject')->willReturn($totpMock);
|
||||
$sut->method('d3TotpGetSession')->willReturn($sessionMock);
|
||||
$sut->method('d3TotpLoginMissing')->with($totpMock)->willReturn($totpMissing);
|
||||
$sut->method('d3TotpGetUserObject')->willReturn($userMock);
|
||||
$sut->method('getUtilsObject')->willReturn($utilsMock);
|
||||
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3requestTotp'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function canRequestTotpDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'no totp missing' => [false, $this->never(), $this->never()],
|
||||
'totp missing' => [true, $this->once(), $this->once()],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::d3GetTotpObject
|
||||
*/
|
||||
public function canGetTotpObject()
|
||||
{
|
||||
/** @var totpSystemEventHandler $sut */
|
||||
$sut = oxNew(SystemEventHandler::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
d3totp::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3GetTotpObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::getUtilsObject
|
||||
*/
|
||||
public function canGetUtilsObject()
|
||||
{
|
||||
/** @var totpSystemEventHandler $sut */
|
||||
$sut = oxNew(SystemEventHandler::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Utils::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'getUtilsObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::d3TotpGetSession
|
||||
*/
|
||||
public function canGetSessionObject()
|
||||
{
|
||||
/** @var totpSystemEventHandler $sut */
|
||||
$sut = oxNew(SystemEventHandler::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
Session::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3TotpGetSession'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::d3TotpGetUserObject
|
||||
*/
|
||||
public function canGetUserObject()
|
||||
{
|
||||
/** @var totpSystemEventHandler $sut */
|
||||
$sut = oxNew(SystemEventHandler::class);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
User::class,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3TotpGetUserObject'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @param $isActive
|
||||
* @param $hasTotpAuth
|
||||
* @param $expected
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @dataProvider checkTotpLoginMissingDataProvider
|
||||
* @covers \D3\Totp\Modules\Core\totpSystemEventHandler::d3TotpLoginMissing
|
||||
*/
|
||||
public function checkTotpLoginMissing($isActive, $hasTotpAuth, $expected)
|
||||
{
|
||||
/** @var Session|MockObject $sessionMock */
|
||||
$sessionMock = $this->getMockBuilder(Session::class)
|
||||
->onlyMethods(['getVariable'])
|
||||
->getMock();
|
||||
$sessionMock->method('getVariable')->willReturn($hasTotpAuth);
|
||||
|
||||
/** @var d3totp|MockObject $totpMock */
|
||||
$totpMock = $this->getMockBuilder(d3totp::class)
|
||||
->onlyMethods(['isActive'])
|
||||
->getMock();
|
||||
$totpMock->method('isActive')->willReturn($isActive);
|
||||
|
||||
/** @var totpSystemEventHandler|MockObject $sut */
|
||||
$sut = $this->getMockBuilder(SystemEventHandler::class)
|
||||
->onlyMethods(['d3TotpGetSession'])
|
||||
->getMock();
|
||||
$sut->method('d3TotpGetSession')->willReturn($sessionMock);
|
||||
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
$this->callMethod(
|
||||
$sut,
|
||||
'd3TotpLoginMissing',
|
||||
[$totpMock]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function checkTotpLoginMissingDataProvider(): array
|
||||
{
|
||||
return [
|
||||
'totp not active' => [false, false, false],
|
||||
'missing totp' => [true, false, true],
|
||||
'totp exists' => [true, true, false],
|
||||
];
|
||||
}
|
||||
}
|
@ -10,12 +10,10 @@
|
||||
* @link https://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace D3\Totp\tests\unit;
|
||||
|
||||
use OxidEsales\TestingLibrary\UnitTestCase;
|
||||
use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase;
|
||||
|
||||
abstract class d3TotpUnitTestCase extends UnitTestCase
|
||||
abstract class d3TotpUnitTestCase extends d3ModCfgUnitTestCase
|
||||
{
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user