improve code
This commit is contained in:
bovenliggende
3baffaef2d
commit
5ed13d13d9
@ -107,7 +107,7 @@ class d3user_webauthn extends AdminDetailsController
|
||||
$publicKeyCredentialCreationOptions
|
||||
);
|
||||
} catch (WebauthnException $e) {
|
||||
// ToDo: log exc message
|
||||
// ToDo: log exc message and show message
|
||||
}
|
||||
|
||||
$this->addTplParam('isAdmin', isAdmin());
|
||||
|
@ -22,16 +22,17 @@ use D3\Webauthn\Application\Model\WebauthnErrors;
|
||||
use D3\Webauthn\Application\Model\WebauthnException;
|
||||
use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent;
|
||||
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
|
||||
use Exception;
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||
use Doctrine\DBAL\Exception as DoctrineException;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\AdminController;
|
||||
use OxidEsales\Eshop\Application\Controller\Admin\LoginController;
|
||||
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
|
||||
use OxidEsales\Eshop\Core\Exception\StandardException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Utils;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
class d3webauthnadminlogin extends AdminController
|
||||
{
|
||||
@ -44,8 +45,10 @@ class d3webauthnadminlogin extends AdminController
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws DoctrineDriverException
|
||||
* @throws DoctrineException
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
@ -62,11 +65,16 @@ class d3webauthnadminlogin extends AdminController
|
||||
|
||||
$this->generateCredentialRequest();
|
||||
|
||||
//$this->addTplParam('navFormParams', Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS));
|
||||
|
||||
return parent::render();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws DoctrineDriverException
|
||||
* @throws DoctrineException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function generateCredentialRequest()
|
||||
{
|
||||
try {
|
||||
@ -78,7 +86,11 @@ class d3webauthnadminlogin extends AdminController
|
||||
$this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions);
|
||||
$this->addTplParam('isAdmin', isAdmin());
|
||||
} catch (WebauthnException $e) {
|
||||
// ToDo write exc message to display and log
|
||||
Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
|
||||
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED'));
|
||||
Registry::getUtilsView()->addErrorToDisplay($exception);
|
||||
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
|
||||
$this->getUtils()->redirect('index.php?cl=login');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ use D3\Webauthn\Application\Model\WebauthnErrors;
|
||||
use D3\Webauthn\Application\Model\WebauthnException;
|
||||
use D3\Webauthn\Modules\Application\Component\d3_webauthn_UserComponent;
|
||||
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||
use Doctrine\DBAL\Exception as DoctrineException;
|
||||
use OxidEsales\Eshop\Application\Controller\FrontendController;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
@ -39,8 +40,12 @@ class d3webauthnlogin extends FrontendController
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
* @throws DoctrineDriverException
|
||||
* @throws DoctrineException
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
@ -64,7 +69,7 @@ class d3webauthnlogin extends FrontendController
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws \Doctrine\DBAL\Driver\Exception
|
||||
* @throws DoctrineDriverException
|
||||
* @throws DoctrineException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
@ -78,7 +83,11 @@ class d3webauthnlogin extends FrontendController
|
||||
$publicKeyCredentialRequestOptions = $webauthn->getRequestOptions($userId);
|
||||
$this->addTplParam('webauthn_publickey_login', $publicKeyCredentialRequestOptions);
|
||||
} catch (WebauthnException $e) {
|
||||
// ToDo: write exc msg to display and log
|
||||
Registry::getSession()->setVariable(WebauthnConf::GLOBAL_SWITCH, true);
|
||||
$exception = oxNew(WebauthnException::class, Registry::getLang()->translateString('D3_WEBAUTHN_ERR_LOGINPROHIBITED'));
|
||||
Registry::getUtilsView()->addErrorToDisplay($exception);
|
||||
Registry::getLogger()->error('webauthn request options: '.$e->getMessage());
|
||||
$this->getUtils()->redirect('index.php?cl=start');
|
||||
}
|
||||
|
||||
$this->addTplParam('isAdmin', isAdmin());
|
||||
|
@ -186,7 +186,8 @@ class Webauthn
|
||||
*/
|
||||
public function isActive($userId): bool
|
||||
{
|
||||
return false == Registry::getConfig()->getConfigParam('blDisableWebauthnGlobally')
|
||||
return !Registry::getConfig()->getConfigParam(WebauthnConf::GLOBAL_SWITCH)
|
||||
&& !Registry::getSession()->getVariable(WebauthnConf::GLOBAL_SWITCH)
|
||||
&& $this->UserUseWebauthn($userId);
|
||||
}
|
||||
|
||||
|
@ -23,4 +23,6 @@ class WebauthnConf
|
||||
public const WEBAUTHN_SESSION_LOGINUSER = 'd3webauthnLoginUser'; // username entered in login form
|
||||
public const WEBAUTHN_SESSION_CURRENTCLASS = 'd3webauthnCurrentClass'; // no usage
|
||||
public const WEBAUTHN_SESSION_NAVFORMPARAMS = 'd3webauthnNavFormParams'; // no usage
|
||||
|
||||
public const GLOBAL_SWITCH = 'blDisableWebauthnGlobally';
|
||||
}
|
@ -28,4 +28,6 @@ $aLang = array(
|
||||
'D3_WEBAUTHN_ACCOUNT_TYPE1' => 'nur Auth-Stick',
|
||||
'D3_WEBAUTHN_ACCOUNT_TYPE2' => 'nur Auth-Stick, Passwort als Alternative',
|
||||
'D3_WEBAUTHN_ACCOUNT_TYPE3' => 'Auth-Stick und Passwort in Kombination',
|
||||
|
||||
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Die Anmeldung mit Sicherheitsschlüssel ist aus technischen Gründen derzeit leider nicht möglich. Bitte verwenden Sie statt dessen Ihr Passwort.',
|
||||
);
|
||||
|
@ -46,4 +46,6 @@ $aLang = [
|
||||
'D3_WEBAUTHN_ERR_NOTSUPPORTED' => 'Die Aktion wird nicht unterstützt.',
|
||||
'D3_WEBAUTHN_ERR_UNKNOWN' => 'Die Aktion wurde wegen eines unbekannten Fehlers abgebrochen.',
|
||||
'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Ihr Browser unterstützt die Verwendung von Hardwareschlüsseln leider nicht.',
|
||||
|
||||
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Die Anmeldung mit Sicherheitsschlüssel ist aus technischen Gründen derzeit leider nicht möglich. Bitte verwenden Sie statt dessen Ihr Passwort.',
|
||||
];
|
||||
|
@ -47,4 +47,5 @@ $aLang = [
|
||||
'D3_WEBAUTHN_ERR_UNKNOWN' => 'The action was cancelled due to an unknown error.',
|
||||
'D3_WEBAUTHN_ERR_NOPUBKEYSUPPORT' => 'Unfortunately, your browser does not support the use of hardware keys.',
|
||||
|
||||
'D3_WEBAUTHN_ERR_LOGINPROHIBITED' => 'Unfortunately, logging in with a security key is currently not possible for technical reasons. Please use your password instead.',
|
||||
];
|
||||
|
@ -24,14 +24,10 @@ namespace D3\Webauthn\Modules\Application\Component
|
||||
|
||||
namespace D3\Webauthn\Modules\Application\Controller
|
||||
{
|
||||
|
||||
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_StartController_Webauthn_parent extends StartController {}
|
||||
|
||||
class d3_webauthn_UserController_parent extends UserController {}
|
||||
|
||||
class d3_webauthn_OrderController_parent extends OrderController {}
|
||||
|
@ -19,6 +19,7 @@ use Assert\AssertionFailedException;
|
||||
use D3\Webauthn\Application\Model\WebauthnConf;
|
||||
use D3\Webauthn\Application\Model\Webauthn;
|
||||
use D3\Webauthn\Application\Model\WebauthnException;
|
||||
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
@ -43,7 +44,9 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
public function login_noredirect()
|
||||
{
|
||||
$lgn_user = Registry::getRequest()->getRequestParameter('lgn_usr');
|
||||
$userId = $this->d3GetLoginUserId($lgn_user);
|
||||
/** @var d3_User_Webauthn $user */
|
||||
$user = oxNew(User::class);
|
||||
$userId = $user->d3GetLoginUserId($lgn_user);
|
||||
|
||||
if ($lgn_user && $userId) {
|
||||
$webauthn = $this->d3GetWebauthnObject();
|
||||
@ -63,8 +66,6 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
$this->getParent()->getViewConfig()->getNavFormParams()
|
||||
);
|
||||
|
||||
//$oUser->d3templogout();
|
||||
|
||||
return "d3webauthnlogin";
|
||||
}
|
||||
}
|
||||
@ -80,29 +81,6 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
return oxNew(Webauthn::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|string
|
||||
*/
|
||||
public function checkWebauthnlogin()
|
||||
{
|
||||
$sWebauth = base64_decode(Registry::getRequest()->getRequestParameter('keyauth'));
|
||||
|
||||
$userId = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
|
||||
$oUser = oxNew(User::class);
|
||||
$oUser->load($userId);
|
||||
|
||||
$webauthn = $this->d3GetWebauthnObject();
|
||||
|
||||
if (!$this->isNoWebauthnOrNoLogin($webauthn, $userId) && $this->hasValidWebauthn($sWebauth, $webauthn)) {
|
||||
$this->d3WebauthnRelogin($oUser, $sWebauth);
|
||||
$this->d3WebauthnClearSessionVariables();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'd3webauthnlogin';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UtilsView
|
||||
*/
|
||||
@ -111,7 +89,7 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
return Registry::getUtilsView();
|
||||
}
|
||||
|
||||
public function cancelWebauthnLogin()
|
||||
public function cancelWebauthnLogin(): bool
|
||||
{
|
||||
$this->d3WebauthnClearSessionVariables();
|
||||
|
||||
@ -151,16 +129,29 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $oUser
|
||||
* @param User $user
|
||||
* @param $sWebauthn
|
||||
*/
|
||||
public function d3WebauthnRelogin(User $oUser, $sWebauthn)
|
||||
public function d3WebauthnRelogin(User $user, $sWebauthn)
|
||||
{
|
||||
$setSessionCookie = Registry::getRequest()->getRequestParameter('lgn_cook');
|
||||
$this->d3GetSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $sWebauthn);
|
||||
$this->d3GetSession()->setVariable('usr', $oUser->getId());
|
||||
$this->d3GetSession()->setVariable('usr', $user->getId());
|
||||
$this->setUser(null);
|
||||
$this->setLoginStatus(USER_LOGIN_SUCCESS);
|
||||
$this->_afterLogin($oUser);
|
||||
|
||||
// cookie must be set ?
|
||||
if ($setSessionCookie && Registry::getConfig()->getConfigParam('blShowRememberMe')) {
|
||||
Registry::getUtilsServer()->setUserCookie(
|
||||
$user->oxuser__oxusername->value,
|
||||
$user->oxuser__oxpassword->value,
|
||||
Registry::getConfig()->getShopId(),
|
||||
31536000,
|
||||
User::USER_COOKIE_SALT
|
||||
);
|
||||
}
|
||||
|
||||
$this->_afterLogin($user);
|
||||
}
|
||||
|
||||
public function d3WebauthnClearSessionVariables()
|
||||
@ -178,39 +169,4 @@ class d3_webauthn_UserComponent extends d3_webauthn_UserComponent_parent
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @throws DoctrineDriverException
|
||||
* @throws Exception
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function d3GetLoginUserId($username): ?string
|
||||
{
|
||||
if (empty($username)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user = oxNew(User::class);
|
||||
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('oxid')
|
||||
->from($user->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'oxusername',
|
||||
$qb->createNamedParameter($username)
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
)
|
||||
)
|
||||
)->setMaxResults(1);
|
||||
|
||||
return $qb->execute()->fetchOne();
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ namespace D3\Webauthn\Modules\Application\Controller\Admin;
|
||||
|
||||
use D3\Webauthn\Application\Model\Webauthn;
|
||||
use D3\Webauthn\Application\Model\WebauthnConf;
|
||||
use D3\Webauthn\Modules\Application\Model\d3_User_Webauthn;
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineException;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
@ -50,10 +51,16 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
|
||||
*/
|
||||
public function checklogin()
|
||||
{
|
||||
$lgn_user = Registry::getRequest()->getRequestParameter('user');
|
||||
$userId = $this->d3GetLoginUserId($lgn_user);
|
||||
$lgn_user = Registry::getRequest()->getRequestParameter('user') ?:
|
||||
Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER);
|
||||
|
||||
if ($lgn_user && $userId && false === Registry::getSession()->hasVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) {
|
||||
/** @var d3_User_Webauthn $user */
|
||||
$user = $this->d3GetUserObject();
|
||||
$userId = $user->d3GetLoginUserId($lgn_user, 'malladmin');
|
||||
|
||||
if ($lgn_user && $userId &&
|
||||
false === Registry::getSession()->hasVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)
|
||||
) {
|
||||
$webauthn = $this->d3GetWebauthnObject();
|
||||
|
||||
if ($webauthn->isActive($userId)
|
||||
@ -72,14 +79,6 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
|
||||
$lgn_user
|
||||
);
|
||||
|
||||
/*
|
||||
Registry::getSession()->setVariable(
|
||||
WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS,
|
||||
$this->getViewConfig()->getNavFormParams()
|
||||
);
|
||||
*/
|
||||
//$oUser->d3templogout();
|
||||
|
||||
return "d3webauthnadminlogin";
|
||||
}
|
||||
}
|
||||
@ -87,46 +86,6 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
|
||||
return parent::checklogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $username
|
||||
* @return string|null
|
||||
* @throws DoctrineException
|
||||
* @throws Exception
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
protected function d3GetLoginUserId($username): ?string
|
||||
{
|
||||
if (empty($username)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user = oxNew(User::class);
|
||||
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('oxid')
|
||||
->from($user->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'oxusername',
|
||||
$qb->createNamedParameter($username)
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxrights',
|
||||
$qb->createNamedParameter('malladmin')
|
||||
)
|
||||
)
|
||||
)->setMaxResults(1);
|
||||
|
||||
return $qb->execute()->fetchOne();
|
||||
}
|
||||
|
||||
public function d3WebauthnCancelLogin()
|
||||
{
|
||||
$oUser = $this->d3GetUserObject();
|
||||
@ -136,7 +95,7 @@ class d3_LoginController_Webauthn extends d3_LoginController_Webauthn_parent
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function d3GetUserObject()
|
||||
public function d3GetUserObject(): User
|
||||
{
|
||||
return oxNew(User::class);
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
namespace D3\Webauthn\Modules\Application\Controller;
|
||||
|
||||
|
||||
class d3_webauthn_OrderController extends d3_webauthn_OrderController_parent
|
||||
{
|
||||
use d3_webauthn_getUserTrait;
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
namespace D3\Webauthn\Modules\Application\Controller;
|
||||
|
||||
|
||||
class d3_webauthn_PaymentController extends d3_webauthn_PaymentController_parent
|
||||
{
|
||||
use d3_webauthn_getUserTrait;
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
namespace D3\Webauthn\Modules\Application\Controller;
|
||||
|
||||
|
||||
class d3_webauthn_UserController extends d3_webauthn_UserController_parent
|
||||
{
|
||||
use d3_webauthn_getUserTrait;
|
||||
|
@ -17,14 +17,22 @@ namespace D3\Webauthn\Modules\Application\Controller;
|
||||
|
||||
use D3\Webauthn\Application\Model\Webauthn;
|
||||
use D3\Webauthn\Application\Model\WebauthnConf;
|
||||
use Doctrine\DBAL\Driver\Exception;
|
||||
use Doctrine\DBAL\Exception as DoctrineException;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
trait d3_webauthn_getUserTrait
|
||||
{
|
||||
/**
|
||||
* @return bool|object|User
|
||||
* @throws Exception
|
||||
* @throws DoctrineException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
@ -34,7 +42,7 @@ trait d3_webauthn_getUserTrait
|
||||
$webauthn = $this->d3GetWebauthnpObject();
|
||||
|
||||
if ($webauthn->isActive($user->getId())
|
||||
&& false == $this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)
|
||||
&& !$this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -46,7 +54,7 @@ trait d3_webauthn_getUserTrait
|
||||
/**
|
||||
* @return Webauthn
|
||||
*/
|
||||
public function d3GetWebauthnObject()
|
||||
public function d3GetWebauthnObject(): Webauthn
|
||||
{
|
||||
return oxNew(Webauthn::class);
|
||||
}
|
||||
@ -54,7 +62,7 @@ trait d3_webauthn_getUserTrait
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3GetSessionObject()
|
||||
public function d3GetSessionObject(): Session
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
|
@ -16,7 +16,15 @@
|
||||
namespace D3\Webauthn\Modules\Application\Model;
|
||||
|
||||
use D3\Webauthn\Application\Model\WebauthnConf;
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use OxidEsales\Eshop\Application\Model\User;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
|
||||
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use ReflectionClass;
|
||||
|
||||
class d3_User_Webauthn extends d3_User_Webauthn_parent
|
||||
@ -35,27 +43,6 @@ class d3_User_Webauthn extends d3_User_Webauthn_parent
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function d3templogout()
|
||||
{
|
||||
$varname = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH);
|
||||
$object = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT);
|
||||
$currentUser = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER);
|
||||
$currentClass = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS);
|
||||
$navFormParams = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS);
|
||||
$loginUser = Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER);
|
||||
|
||||
$return = $this->logout();
|
||||
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH, $varname);
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_LOGIN_OBJECT, $object);
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTUSER, $currentUser);
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_CURRENTCLASS, $currentClass);
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_NAVFORMPARAMS, $navFormParams);
|
||||
Registry::getSession()->setVariable(WebauthnConf::WEBAUTHN_SESSION_LOGINUSER, $loginUser);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function login($userName, $password, $setSessionCookie = false)
|
||||
{
|
||||
if (Registry::getSession()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH)) {
|
||||
@ -78,4 +65,43 @@ class d3_User_Webauthn extends d3_User_Webauthn_parent
|
||||
|
||||
return parent::login($userName, $password, $setSessionCookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $username
|
||||
* @param ?string $rights
|
||||
* @return string|null
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws DoctrineDriverException
|
||||
* @throws Exception
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function d3GetLoginUserId(string $username, string $rights = null): ?string
|
||||
{
|
||||
if (empty($username)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('oxid')
|
||||
->from($this->getViewName())
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'oxusername',
|
||||
$qb->createNamedParameter($username)
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
),
|
||||
$rights ? $qb->expr()->eq(
|
||||
'oxrights',
|
||||
$qb->createNamedParameter($rights)
|
||||
) : '1'
|
||||
)
|
||||
)->setMaxResults(1);
|
||||
|
||||
return $qb->execute()->fetchOne();
|
||||
}
|
||||
}
|
@ -18,16 +18,22 @@ namespace D3\Webauthn\Modules\Core;
|
||||
use D3\Webauthn\Application\Model\Webauthn;
|
||||
use D3\Webauthn\Application\Model\WebauthnConf;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use Doctrine\DBAL\Driver\Exception;
|
||||
use Doctrine\DBAL\Exception as DoctrineException;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\Session;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
class d3_webauthn_utils extends d3_webauthn_utils_parent
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws Exception
|
||||
* @throws DoctrineException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function checkAccessRights()
|
||||
{
|
||||
@ -35,12 +41,11 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
|
||||
|
||||
$userID = $this->d3GetSessionObject()->getVariable("auth");
|
||||
$webauthnAuth = (bool) $this->d3GetSessionObject()->getVariable(WebauthnConf::WEBAUTHN_SESSION_AUTH);
|
||||
/** @var Webauthn $webauthn */
|
||||
$webauthn = $this->d3GetWebauthnObject();
|
||||
|
||||
if ($blAuth && $webauthn->isActive($userID) && false === $webauthnAuth) {
|
||||
$this->redirect('index.php?cl=login', true, 302);
|
||||
if (false == defined('OXID_PHP_UNIT')) {
|
||||
if (!defined('OXID_PHP_UNIT')) {
|
||||
// @codeCoverageIgnoreStart
|
||||
exit;
|
||||
// @codeCoverageIgnoreEnd
|
||||
@ -53,7 +58,7 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
|
||||
/**
|
||||
* @return Session
|
||||
*/
|
||||
public function d3GetSessionObject()
|
||||
public function d3GetSessionObject(): Session
|
||||
{
|
||||
return Registry::getSession();
|
||||
}
|
||||
@ -61,7 +66,7 @@ class d3_webauthn_utils extends d3_webauthn_utils_parent
|
||||
/**
|
||||
* @return Webauthn
|
||||
*/
|
||||
public function d3GetWebauthnObject()
|
||||
public function d3GetWebauthnObject(): Webauthn
|
||||
{
|
||||
return oxNew(Webauthn::class);
|
||||
}
|
||||
|
@ -17,9 +17,20 @@
|
||||
|
||||
namespace D3\Webauthn\Setup;
|
||||
|
||||
use Doctrine\DBAL\Driver\Exception as DoctrineDriverException;
|
||||
use Doctrine\DBAL\Exception as DoctrineException;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use Exception;
|
||||
use OxidEsales\Eshop\Core\DatabaseProvider;
|
||||
use OxidEsales\Eshop\Core\DbMetaDataHandler;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
|
||||
use OxidEsales\Eshop\Core\Registry;
|
||||
use OxidEsales\Eshop\Core\UtilsView;
|
||||
use OxidEsales\EshopCommunity\Internal\Container\ContainerFactory;
|
||||
use OxidEsales\EshopCommunity\Internal\Framework\Database\QueryBuilderFactoryInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
class Events
|
||||
{
|
||||
@ -44,6 +55,9 @@ class Events
|
||||
|
||||
/**
|
||||
* Execute action on activate event
|
||||
* @return void
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
public static function onActivate()
|
||||
{
|
||||
@ -52,6 +66,8 @@ class Events
|
||||
self::regenerateViews();
|
||||
|
||||
self::clearCache();
|
||||
|
||||
self::seoUrl();
|
||||
}
|
||||
|
||||
public static function onDeactivate()
|
||||
@ -60,6 +76,9 @@ class Events
|
||||
|
||||
/**
|
||||
* Execute the sql at the first time of the module installation.
|
||||
* @return void
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
private static function setupModule()
|
||||
{
|
||||
@ -75,7 +94,7 @@ class Events
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function tableExists($sTableName)
|
||||
protected static function tableExists(string $sTableName): bool
|
||||
{
|
||||
$oDbMetaDataHandler = oxNew(DbMetaDataHandler::class );
|
||||
|
||||
@ -86,6 +105,8 @@ class Events
|
||||
* Executes given sql statement.
|
||||
*
|
||||
* @param string $sSQL Sql to execute.
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
private static function executeSQL($sSQL)
|
||||
{
|
||||
@ -100,7 +121,7 @@ class Events
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function fieldExists($sFieldName, $sTableName)
|
||||
protected static function fieldExists(string $sFieldName, string $sTableName): bool
|
||||
{
|
||||
$oDbMetaDataHandler = oxNew(DbMetaDataHandler::class );
|
||||
|
||||
@ -117,11 +138,11 @@ class Events
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty cache
|
||||
* clear cache
|
||||
*/
|
||||
private static function clearCache()
|
||||
{
|
||||
/** @var \OxidEsales\Eshop\Core\UtilsView $oUtilsView */
|
||||
/** @var UtilsView $oUtilsView */
|
||||
$oUtilsView = Registry::getUtilsView();
|
||||
$sSmartyDir = $oUtilsView->getSmartyDir();
|
||||
|
||||
@ -133,4 +154,65 @@ class Events
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private static function seoUrl()
|
||||
{
|
||||
try {
|
||||
if (!self::hasSeoUrl()) {
|
||||
self::createSeoUrl();
|
||||
}
|
||||
} catch (Exception|NotFoundExceptionInterface|DoctrineDriverException|ContainerExceptionInterface $e) {
|
||||
Registry::getUtilsView()->addErrorToDisplay('error wile creating SEO URLs: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DoctrineDriverException
|
||||
* @throws DoctrineException
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
private static function hasSeoUrl(): bool
|
||||
{
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = ContainerFactory::getInstance()->getContainer()->get(QueryBuilderFactoryInterface::class)->create();
|
||||
$qb->select('1')
|
||||
->from('oxseo')
|
||||
->where(
|
||||
$qb->expr()->and(
|
||||
$qb->expr()->eq(
|
||||
'oxstdurl',
|
||||
$qb->createNamedParameter('index.php?cl=d3_account_webauthn')
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxshopid',
|
||||
$qb->createNamedParameter(Registry::getConfig()->getShopId())
|
||||
),
|
||||
$qb->expr()->eq(
|
||||
'oxlang',
|
||||
$qb->createNamedParameter('1')
|
||||
)
|
||||
)
|
||||
)
|
||||
->setMaxResults(1);
|
||||
return $qb->execute()->fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
private static function createSeoUrl()
|
||||
{
|
||||
$query = "INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
|
||||
('ff57646b47249ee33c6b672741ac371a', 'be07f06fe03a4d5d7936f2eac5e3a87b', 1, 1, 'index.php?cl=d3_account_webauthn', 'en/key-authintication/', 'static', 0, 0, '', NOW()),
|
||||
('ff57646b47249ee33c6b672741ac371a', '220a1af77362196789eeed4741dda184', 1, 0, 'index.php?cl=d3_account_webauthn', 'key-authentisierung/', 'static', 0, 0, '', NOW());";
|
||||
|
||||
DatabaseProvider::getDb()->execute($query);
|
||||
}
|
||||
}
|
@ -1,246 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This Software is the property of Data Development and is protected
|
||||
* by copyright law - it is NOT Freeware.
|
||||
* Any unauthorized use of this software without a valid license
|
||||
* is a violation of the license agreement and will be prosecuted by
|
||||
* civil and criminal law.
|
||||
* http://www.shopmodule.com
|
||||
*
|
||||
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
|
||||
* @link http://www.oxidmodule.com
|
||||
*/
|
||||
|
||||
namespace D3\Webauthn\Setup;
|
||||
|
||||
use D3\ModCfg\Application\Model\d3database;
|
||||
use D3\ModCfg\Application\Model\Install\d3install_updatebase;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use OxidEsales\Eshop\Core\DatabaseProvider;
|
||||
use OxidEsales\Eshop\Core\Exception\ConnectionException;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
|
||||
use OxidEsales\Eshop\Core\Exception\DatabaseErrorException;
|
||||
|
||||
class Installation extends d3install_updatebase
|
||||
{
|
||||
protected $_aUpdateMethods = array(
|
||||
array('check' => 'doesPublicKeyCredentialTableNotExist',
|
||||
'do' => 'addPublicKeyCredentialTable'),
|
||||
array('check' => 'checkFields',
|
||||
'do' => 'fixFields'),
|
||||
array('check' => 'checkIndizes',
|
||||
'do' => 'fixIndizes'),
|
||||
array('check' => 'checkSEONotExists',
|
||||
'do' => 'addSEO'),
|
||||
);
|
||||
|
||||
public $aMultiLangTables = array();
|
||||
|
||||
public $aFields = array(
|
||||
'OXID' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'OXID',
|
||||
'sType' => 'CHAR(32)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'NAME' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'Name',
|
||||
'sType' => 'VARCHAR(255)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'CREDENTIALID' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'CredentialId',
|
||||
'sType' => 'BINARY(48)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'TYPE' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'Type',
|
||||
'sType' => 'CHAR(20)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'TRANSPORTS' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'Transports',
|
||||
'sType' => 'VARCHAR(255)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'ATTESTATIONTYPE' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'AttestationType',
|
||||
'sType' => 'CHAR(100)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'TRUSTPATH' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'TrustPath',
|
||||
'sType' => 'VARCHAR(255)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'AAGUID' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'Aaguid',
|
||||
'sType' => 'VARCHAR(255)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'PUBLICKEY' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'PublicKey',
|
||||
'sType' => 'BINARY(77)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'USERHANDLE' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'UserHandle',
|
||||
'sType' => 'CHAR(36)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'COUNTER' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'Counter',
|
||||
'sType' => 'INT(5)',
|
||||
'blNull' => false,
|
||||
'sDefault' => false,
|
||||
'sComment' => '',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
),
|
||||
'OXTIMESTAMP' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sFieldName' => 'oxtimestamp',
|
||||
'sType' => 'TIMESTAMP',
|
||||
'blNull' => false,
|
||||
'sDefault' => 'CURRENT_TIMESTAMP',
|
||||
'sComment' => 'Timestamp',
|
||||
'sExtra' => '',
|
||||
'blMultilang' => false,
|
||||
)
|
||||
);
|
||||
|
||||
public $aIndizes = array(
|
||||
'OXID' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sType' => d3database::INDEX_TYPE_PRIMARY,
|
||||
'sName' => 'PRIMARY',
|
||||
'aFields' => array(
|
||||
'OXID' => 'OXID',
|
||||
),
|
||||
),
|
||||
'OXUSERID' => array(
|
||||
'sTableName' => 'd3PublicKeyCredential',
|
||||
'sType' => d3database::INDEX_TYPE_UNIQUE,
|
||||
'sName' => 'CredentialId',
|
||||
'aFields' => array(
|
||||
'CredentialId' => 'CredentialId',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
protected $_aRefreshMetaModuleIds = array('d3webauthn');
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
public function doesPublicKeyCredentialTableNotExist()
|
||||
{
|
||||
return $this->_checkTableNotExist('d3PublicKeyCredential');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws ConnectionException
|
||||
* @throws DBALException
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
public function addPublicKeyCredentialTable()
|
||||
{
|
||||
$blRet = false;
|
||||
if ($this->doesPublicKeyCredentialTableNotExist()) {
|
||||
$this->setInitialExecMethod(__METHOD__);
|
||||
$blRet = $this->_addTable2(
|
||||
'd3PublicKeyCredential',
|
||||
$this->aFields,
|
||||
$this->aIndizes,
|
||||
'key credentials',
|
||||
'InnoDB'
|
||||
);
|
||||
}
|
||||
|
||||
return $blRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
*/
|
||||
public function checkSEONotExists()
|
||||
{
|
||||
$query = "SELECT 1 FROM " . getViewName('oxseo') . " WHERE oxstdurl = 'index.php?cl=d3_account_webauthn'";
|
||||
|
||||
return !DatabaseProvider::getDb()->getOne($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws DatabaseConnectionException
|
||||
* @throws DatabaseErrorException
|
||||
*/
|
||||
public function addSEO()
|
||||
{
|
||||
$query = [
|
||||
"INSERT INTO `oxseo` (`OXOBJECTID`, `OXIDENT`, `OXSHOPID`, `OXLANG`, `OXSTDURL`, `OXSEOURL`, `OXTYPE`, `OXFIXED`, `OXEXPIRED`, `OXPARAMS`, `OXTIMESTAMP`) VALUES
|
||||
('ff57646b47249ee33c6b672741ac371a', 'be07f06fe03a4d5d7936f2eac5e3a87b', 1, 1, 'index.php?cl=d3_account_webauthn', 'en/key-authintication/', 'static', 0, 0, '', NOW()),
|
||||
('ff57646b47249ee33c6b672741ac371a', '220a1af77362196789eeed4741dda184', 1, 0, 'index.php?cl=d3_account_webauthn', 'key-authentisierung/', 'static', 0, 0, '', NOW());"
|
||||
];
|
||||
|
||||
return $this->_executeMultipleQueries($query);
|
||||
}
|
||||
}
|
Laden…
Verwijs in nieuw issue
Block a user